Skip to content

Instantly share code, notes, and snippets.

@smashnet
Last active December 7, 2023 05:50
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save smashnet/38cf7c30cb06427bab78ae5ab0fd2ae3 to your computer and use it in GitHub Desktop.
Save smashnet/38cf7c30cb06427bab78ae5ab0fd2ae3 to your computer and use it in GitHub Desktop.
Docker-Compose: Mastodon v3.5.3 with Traefik v2.9
version: "3.5"
# Variables to fill in:
# Line 23: <LETSENCRYPT_MAIL_ADDRESS> - your mail address for contact with Let's Encrypt
# Line 36: <TRAEFIK_DASHBOARD_ADMIN_PASSWORD> - MD5 hash of your password (use http://www.htaccesstools.com/htpasswd-generator/)
# Line 54: <POSTGRES_PASSWORD> - the password for the postgres db. Use the same during mastodon:setup!
# Lines 31, 86, 111: <DOMAIN> - e.g. social.yourdomain.com (Must have an A record pointing to your box' IP) (AAAA for IPv6 ;)
services:
traefik:
image: traefik:v2.9
container_name: "traefik"
restart: always
command:
# - "--log.level=DEBUG"
- "--api.dashboard=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=<LETSENCRYPT_MAIL_ADDRESS>"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
labels:
- "traefik.enable=true"
# Dashboard
- "traefik.http.routers.traefik.rule=(Host(`<DOMAIN>`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)))"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.middlewares=dashboardauth"
- "traefik.http.middlewares.dashboardauth.basicauth.users=admin:<TRAEFIK_DASHBOARD_ADMIN_PASSWORD>"
# HTTPS Redirect
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https@docker"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./letsencrypt:/letsencrypt
networks:
- external_network
db:
restart: always
image: postgres:14-alpine
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
environment:
- POSTGRES_PASSWORD=<POSTGRES_PASSWORD>
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
- internal_network
redis:
restart: always
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
volumes:
- ./redis:/data
networks:
- internal_network
web:
image: tootsuite/mastodon:v3.5.3
restart: always
env_file: .env.production
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
healthcheck:
test: ["CMD-SHELL", "wget -q --spider --proxy=off localhost:3000/health || exit 1"]
expose:
- "3000"
depends_on:
- db
- redis
- traefik
labels:
- "traefik.enable=true"
- "traefik.docker.network=mastodon_external_network"
- "traefik.http.services.mastodon-web.loadbalancer.server.port=3000"
- "traefik.http.routers.mastodon-web.rule=Host(`<DOMAIN>`)"
- "traefik.http.routers.mastodon-web.entrypoints=websecure"
- "traefik.http.routers.mastodon-web.tls.certresolver=letsencrypt"
volumes:
- ./public/system:/mastodon/public/system
networks:
- external_network
- internal_network
streaming:
image: tootsuite/mastodon:v3.5.3
restart: always
env_file: .env.production
command: node ./streaming
healthcheck:
test: ["CMD-SHELL", "wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1"]
expose:
- "4000"
depends_on:
- db
- redis
- traefik
labels:
- "traefik.enable=true"
- "traefik.docker.network=mastodon_external_network"
- "traefik.http.services.mastodon-streaming.loadbalancer.server.port=4000"
- "traefik.http.routers.mastodon-streaming.rule=(Host(`<DOMAIN>`) && PathPrefix(`/api/v1/streaming`))"
- "traefik.http.routers.mastodon-streaming.entrypoints=websecure"
- "traefik.http.routers.mastodon-streaming.tls.certresolver=letsencrypt"
networks:
- external_network
- internal_network
sidekiq:
image: tootsuite/mastodon:v3.5.3
restart: always
env_file: .env.production
command: bundle exec sidekiq
depends_on:
- db
- redis
- traefik
volumes:
- ./public/system:/mastodon/public/system
networks:
- external_network
- internal_network
networks:
external_network:
name: mastodon_external_network
internal_network:
internal: true
@peterrus
Copy link

Alright, I have forked your gist @ https://gist.github.com/peterrus/0753fc3cf09b33a6253924cfc9f9b32f and made some changes:

  • The streaming service was not working because traefik was trying to connect to port 3000 instead of the exposed 4000. I corrected this with an explicit configuration.
  • This explicit configuration (for traefik) had to be applied on a traefik service. Traefik instantiates new services with names based on docker-compose project name. We can't guess this in advance (if we want to keep the docker-compose file universal) so we have to specify that through an environment variable. I added instructions on how to create an .env file that gets loaded by docker-compose automatically
  • this .env file now also contains other configuration parameters, so as to keep them out of git and to keep the docker-compose file universal.
  • Traefik was trying to connect to the web and streaming through the 'internal_network' network. This does not seem to be correct nor desirable. I have created an explicit configuration to use the 'external_network' network. Again, I needed to refer to the docker-compose project name.

Feel free to port any of my changes back to your file as you see fit and thank you for setting up the initial example! You have saved me quite some headaches ;)

@encryptblockr
Copy link

encryptblockr commented Jun 20, 2020

where did you get the documentation for using these labels?
i can't find documentation on using these labels anywhere on the traefik website

    labels:
      - "traefik.enable=true"
      # Dashboard
      - "traefik.http.routers.traefik.rule=(Host(`<DOMAIN>`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)))"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.middlewares=dashboardauth"
      - "traefik.http.middlewares.dashboardauth.basicauth.users=admin:<TRAEFIK_DASHBOARD_ADMIN_PASSWORD>"
      # HTTPS Redirect
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https@docker"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

i am looking for the v2 replacement for targeting network

   labels:
     - "traefik.docker.network=traefiknetwork"

@smashnet
Copy link
Author

where did you get the documentation for using these labels?
i can't find documentation on using these labels anywhere on the traefik website

You may have a look at this section of the Traefik docs: Traefik & Docker

... but especially here: Docker network

There it says that traefik.docker.network is still a valid label in v2.

@dweipert-3138720606
Copy link

I created a set of scripts with the help of your gist and @peterrus project.
It builds a docker-compose.yml from the official project's file and modifies it to include the traefik labels with some tweaks, so you can use an external running traefik container instead.

https://gitlab.com/dweipert.de/devops/mastodon-docker-traefik

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