Docker 23 + Traefik v2.9.10 and v1.7 + Let's Encrypt + Github Registry V2 ghcr.io + Updated on 12 April 2023 Content: - Ubuntu 22.04 - Docker Engine 23.0.3 - Docker Compose 2.17.2 - Traefik v1.7.18 with dnsChallenge - Traefik v2.9.9 with httpChallenge -- - Github Registry V2 ghcr.io - Let's Encrypt TL DR: - TLDR go to line 52 for Traefik v1.7 configs - TLDR go to line 178 for Traefik v2.9.9 configs Start: 1. Create a Ubuntu Droplet 1.1. You can create a Docker pre-installed Ubuntu too 2. Add domain to the Droplet -> yourdomain.com 2.1 Create A record for the Droplet -> @ for Droplet IP OR Change DNS on your domain provider 3. Connect to Ubuntu CLI with password or SSH 4. Install Docker 4.1. curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 4.2. sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 4.3. sudo apt-get update 4.4. apt-cache policy docker-ce 4.5. sudo apt-get install -y docker-ce 4.6. sudo systemctl status docker 5. Run your first docker image -> docker run ghcr.io/doxa-labs/docker-helloworld/docker-helloworld:latest 6. Install docker-compose 6.1. docker compose comes with docker-ce community edition v23. Still check the version. 6.2. docker compose --version -- 6.3. If it is not installed then install it like this: 6.4. Check the latest version. It's 2.17.2 on April 2023. https://github.com/docker/compose/releases 6.5. sudo curl -L "https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 6.6. sudo chmod +x /usr/local/bin/docker-compose 6.7. sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 6.8. docker-compose --version 7. Go to /opt Folder 8. Create a folder -> mkdir traefik && cd traefik 9. Create traefik files 9.1. sudo touch /opt/traefik/docker-compose.yml 9.2. sudo touch /opt/traefik/acme.json 9.3. sudo chmod 600 /opt/traefik/acme.json 9.4. sudo touch /opt/traefik/traefik.toml 10. Update your docker-compose.yml file 10.1. nano docker-compose.yml 10.2. I am using dnsChallenge on Traefik v1+ and httpChallenge on Traefik v2+ to create SSL on acme.json. My domain provider is GoDaddy. Create a production API KEY and update environment parameters. 10.3 Update yourdomain.com on labes. [Traefik v1.7] - docker-compose.yml with dnsChallenge version: '3.7' services: reverse-proxy: image: traefik:v1.7 restart: always container_name: traefik ports: - 80:80 - 443:443 expose: - 8080 networks: - external - internal environment: - GODADDY_API_KEY=... - GODADDY_API_SECRET=... volumes: - /var/run/docker.sock:/var/run/docker.sock - /opt/traefik/traefik.toml:/traefik.toml - /opt/traefik/acme.json:/acme.json labels: - "traefik.backend=traefik" - "traefik.docker.network=external" - "traefik.enable=true" - "traefik.frontend.rule=Host:traefik.yourdomain.com" - "traefik.port=8080" - "traefik.frontend.headers.forceSTSHeader=true" - "traefik.frontend.headers.STSSeconds=315360000" - "traefik.frontend.headers.STSIncludeSubdomains=true" - "traefik.frontend.headers.STSPreload=true" networks: external: external: true internal: 11. Update traefik.toml file 11.1. Update users on entryPoints.traefik with -> echo $(htpasswd -nb username password) | sed -e s/\\$/\\$\\$/g 11.2. Update your-domain and your-email fields 11.3. Update your domain provider on acme.dnsChallenge [Traefik v1.7] - traefik.toml with dnsChallenge debug = false loglevel = "ERROR" defaultEntryPoints = ["https", "http"] [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [entryPoints.traefik] address = ":8080" [entryPoints.traefik.auth.basic] users = ["username:hashed-password"] [api] entryPoint = "traefik" [retry] [docker] endpoint = "unix:///var/run/docker.sock" domain = "your-domain.com" watch = true exposedByDefault = false [acme] email = "your-email.com" storage = "acme.json" onHostRule = true entryPoint = "https" [acme.dnsChallenge] provider = "godaddy" delayBeforeCheck = 0 [[acme.domains]] main = "*.your-domain.com" sans = ["your-domain.com"] 12. Create a network -> docker network create external / or your name like traefik etc. 13. Run traefik 13.1. docker-compose up -d 13.2. docker ps 13.3. If you don't see traefik running then chek the logs -> docker logs containerId 13.4. If it's running then create a CNAME for traefik -> @ then visit traefik.your-domain.com 13.5. Enter your username and non-hashed password to see the dashboard 14. Run your own image from Github Registry / Others 14.1. Create a folder -> mkdir opt/my-container 14.2 Create docker-compose -> nano docker-compose.yml [Traefik 1.7] - docker-compose.yml version: "3.9" services: your-container-name: image: docker.pkg.github.com/github-username/repo-name/tag-name:latest restart: always container_name: your-container-name networks: - web labels: - traefik.docker.network=external - traefik.backend=your-container-name - traefik.frontend.rule=Host:your-container-name.your-domain.com - traefik.enable=true - traefik.port=80 networks: web: name: external 15. Docker authentication (GitHub Registry V2) 15.1. If you are using Ubuntu 19 then run -> apt install pass 15.2. docker login ghcr.io --username "github-username" 15.3. Create a Github Personal Access Token (classic) with repo, package write and read permission and enter this token as a password 16. Run your container 16.1. docker-compose up -d 16.2. docker ps 16.3. Create a CNAME for your-container-name -> @ then visit your-container-name.your-domain.com These configs are for Traefik v2.0+ [Traefik v2.9.10] - docker-compose.yml with httpChallenge version: '3.9' services: traefik: image: traefik:v2.9.10 container_name: traefik restart: unless-stopped security_opt: - no-new-privileges:true networks: - proxy ports: - 80:80 - 443:443 volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./traefik.yml:/traefik.yml:ro - ./acme.json:/acme.json labels: - "traefik.enable=true" - "traefik.http.routers.traefik.entrypoints=http" - "traefik.http.routers.traefik.rule=Host(`traefik.your-domain.com`)" - "traefik.http.middlewares.traefik-auth.basicauth.users=username:hashed-password" - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https" - "traefik.http.routers.traefik.middlewares=traefik-https-redirect" - "traefik.http.routers.traefik-secure.entrypoints=https" - "traefik.http.routers.traefik-secure.rule=Host(`traefik.your-domain.com`)" - "traefik.http.routers.traefik-secure.middlewares=traefik-auth" - "traefik.http.routers.traefik-secure.tls=true" - "traefik.http.routers.traefik-secure.tls.certresolver=http" - "traefik.http.routers.traefik-secure.service=api@internal" - "traefik.http.services.traefik.loadbalancer.server.port=8080" networks: proxy: external: true [Traefik v2.9.9] - traefik.yml with httpChallenge api: dashboard: true # Writing Logs to a File, in JSON log: level: DEBUG filePath: "log-file.log" format: json # Configuring a buffer of 100 lines accessLog: filePath: "log-access.log" bufferingSize: 100 entryPoints: http: address: ":80" https: address: ":443" providers: docker: endpoint: "unix:///var/run/docker.sock" exposedByDefault: false certificatesResolvers: http: acme: email: your-email.com storage: acme.json httpChallenge: entryPoint: http [Traefik v2.9.9] - your-container docker-compose.yml version: '3.8' services: your-container-name: image: docker.pkg.github.com/username/repo-name/image-name:latest container_name: your-container-name restart: unless-stopped security_opt: - no-new-privileges:true networks: - proxy volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro - ./data:/data labels: - "traefik.enable=true" - "traefik.http.routers.your-container-name.entrypoints=http" - "traefik.http.routers.your-container-name.rule=Host(`your-container-name.your-domain.com`, `www.your-container-name.your-domain.com`)" - "traefik.http.middlewares.your-container-name-https-redirect.redirectscheme.scheme=https" - "traefik.http.routers.your-container-name.middlewares=your-container-name-https-redirect" - "traefik.http.routers.your-container-name-secure.entrypoints=https" - "traefik.http.routers.your-container-name-secure.rule=Host(`your-container-name.your-domain.com`, `www.your-container-name.your-domain.com`)" - "traefik.http.routers.your-container-name-secure.tls=true" - "traefik.http.routers.your-container-name-secure.tls.certresolver=http" - "traefik.http.routers.your-container-name-secure.service=your-container-name" - "traefik.http.services.your-container-name.loadbalancer.server.port=80" - "traefik.docker.network=proxy" networks: proxy: external: true