Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save savepong/9e4fd4699c8adc6dcce022846bb1d046 to your computer and use it in GitHub Desktop.
Save savepong/9e4fd4699c8adc6dcce022846bb1d046 to your computer and use it in GitHub Desktop.
Setting Up EC2 Ubuntu ARM (Graviton) to Host Multiple Websites with Docker and Caddy

These steps are specifically for ARM-based EC2 instances (AWS Graviton) to host multiple websites using Docker and Caddy.

Step 1: Launch and Configure ARM-based Ubuntu EC2 Instance

  1. Launch an ARM-based Ubuntu EC2 instance (use t4g, c6g, or m6g family with Ubuntu 22.04 LTS)

  2. Configure security groups:

    • Allow SSH (port 22)
    • Allow HTTP (port 80)
    • Allow HTTPS (port 443)
  3. Connect to your instance:

    ssh -i your-key.pem ubuntu@your-ec2-ip
    

Step 2: Update System and Install Docker

# Update the system
sudo apt update && sudo apt upgrade -y

# Install required packages
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add Docker repository
echo "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io

# Add your user to the docker group
sudo usermod -aG docker $USER

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Apply group changes (log out and back in, or run this)
newgrp docker

Step 3: Create Project Directory Structure

# Create a main directory for hosting
mkdir -p ~/websites
cd ~/websites

# Create directories for Caddy
mkdir -p caddy/data caddy/config sites

Check for certificate directory permissions

sudo chown -R 1000:1000 caddy/data
sudo chmod -R 755 caddy/data

Step 4: Create Docker Compose Configuration

nano docker-compose.yml

Add the following content:

Docker Compose for Multiple Websites with Caddy (ARM-compatible)Code

Step 5: Create Caddyfile

nano caddy/Caddyfile

Add configuration for your websites:

Caddyfile for Multiple WebsitesCode

Step 6: Prepare Website Content

Website 1 (Static HTML)

mkdir -p sites/website1
nano sites/website1/index.html

Add simple HTML content:

html
Copy
<!DOCTYPE html>
<html>
<head>
    <title>Website 1</title>
</head>
<body>
    <h1>Welcome to Website 1</h1>
    <p>This is a static HTML site served through Caddy and Docker on an ARM-based EC2 instance.</p>
</body>
</html>

Website 2 (WordPress)

mkdir -p sites/website2/wordpress sites/website2/db

Website 3 (Node.js Example)

mkdir -p sites/website3
nano sites/website3/Dockerfile

Add Dockerfile content:

ARM-compatible Dockerfile for Node.js WebsiteCode

Step 7: Set Up DNS Records

Configure your domain's DNS settings to point each subdomain to your EC2 instance's IP address:

  • site1.example.com → Your EC2 IP
  • site2.example.com → Your EC2 IP
  • site3.example.com → Your EC2 IP

Step 8: Start the Services

cd ~/websites
docker-compose up -d

Step 9: Verify Container Status and ARM Compatibility

# Check running containers
docker ps

# Verify container architecture
docker inspect --format '{{.Architecture}}' $(docker ps -q)

Step 10: Set Up Monitoring and Maintenance for ARM

# Create a monitoring script
nano monitor.sh

Add the following content:

#!/bin/bash
echo "=== Docker Container Status ==="
docker ps -a
echo ""
echo "=== Container Architecture ==="
for container in $(docker ps -q); do
  echo -n "$(docker inspect --format '{{.Name}}' $container): "
  docker inspect --format '{{.Architecture}}' $container
done
echo ""
echo "=== Disk Usage ==="
df -h
echo ""
echo "=== Memory Usage ==="
free -m
echo ""
echo "=== CPU Info ==="
lscpu | grep "Architecture"

Make it executable:

chmod +x monitor.sh

ARM-Specific Tips and Troubleshooting

  1. Handling ARM compatibility issues:
    • If a specific image doesn't work, check the Docker Hub page for ARM64 support
    • Use docker manifest inspect image:tag to check supported architectures
    • For databases, MariaDB generally has better ARM support than MySQL
  2. Performance tuning for ARM:

Add content:

```bash

# Create tuning script
nano arm-tune.sh

```

```bash

#!/bin/bash
# Set CPU governor to performance
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# Optimize Docker storage
echo '{
  "storage-driver": "overlay2",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}' | sudo tee /etc/docker/daemon.json

# Restart Docker to apply changes
sudo systemctl restart docker

```
  1. Backup strategy (same as x86 but confirming ARM compatibility):

    # Test backup with ARM-compatible tools
    mkdir -p ~/backups
    tar -czf ~/backups/websites-test.tar.gz ~/websites/caddy
    
  2. Adding a fourth website with ARM compatibility: Add to docker-compose.yml:

Add to Caddyfile:

```yaml
yaml
Copy
website4:
  image: python:3.9-slim
  platform: linux/arm64
  container_name: website4
  restart: unless-stopped
  volumes:
    - ./sites/website4:/app
  command: python -m http.server 8000
  networks:
    - web_network

```

```
Copy
site4.example.com {
    reverse_proxy website4:8000
}

```

This setup is specifically optimized for ARM-based EC2 instances and addresses the architecture compatibility issues you were experiencing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment