Docker+Synapse+Traefik v2 stops working when I make a separate backend network
I'm trying to set up a Matrix Synapse server using Docker and a Traefik v2 reverse proxy.
My setup works if I define a single network in my docker-compose file and have Traefik, Synapse and postgres all use that network.
However, based on what I've learnt about Docker so far, I should put postgres on a separate network (backed
) than Traefik (web
). Synapse will then be on both networks. However, when I do so, I'm no longer able to connect to Synapse. It times out eventually saying Gateway Timeout
.
It's as if Synapse is only listening on the backend
network.
version: '3.2'
services:
synapse:
container_name: synapse
hostname: ${MATRIX_HOSTNAME}
image: docker.io/matrixdotorg/synapse:latest
restart: unless-stopped
environment:
- SYNAPSE_SERVER_NAME=${MATRIX_HOSTNAME}
- SYNAPSE_REPORT_STATS=yes
- SYNAPSE_NO_TLS=1
- SYNAPSE_ENABLE_REGISTRATION=no
- SYNAPSE_LOG_LEVEL=DEBUG
- SYNAPSE_REGISTRATION_SHARED_SECRET=${REG_SHARED_SECRET}
- POSTGRES_DB=synapse
- POSTGRES_HOST=db
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
# expose:
# - "8008"
volumes:
- type: bind
source: /opt/services/synapse
target: /data
depends_on:
- db
networks:
- web
- backend
labels:
- "traefik.enable=true"
- "traefik.http.routers.synapse.rule=Host(`${MATRIX_HOSTNAME}`)"
- "traefik.http.services.synapse.loadbalancer.server.port=8008"
- "traefik.http.routers.synapse.entrypoints=websecure"
- "traefik.http.routers.synapse.tls.certresolver=myresolver"
- "traefik.docker.network=web"
db:
image: docker.io/postgres:10-alpine
container_name: "synapse_db"
restart: unless-stopped
environment:
- POSTGRES_DB=synapse
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- /opt/services/synapse_db:/var/lib/postgresql/data
networks:
- backend
labels:
- "traefik.enable=false"
traefik:
image: traefik:v2.5
container_name: "traefik"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=web"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=${CERTBOT_EMAIL}"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
# Router forwards 443 on WAN to 8443 on host so we don't need root permissions
- "8443:443"
- "8080:8080"
networks:
- web
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
restart:
unless-stopped
networks:
web:
backend:
And within Synapse's homeserver.yaml
file, there is a section that could let me bind to a specific interface, but I have not made any changes so it should listen on all interfaces by default:
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
# - names: [client, federation]
- names: [client]
compress: false
If I go down to a single network setup it works. What am I doing wrong with the two network setup?
Solution 1:
Traefik doesn't know which IP of the container it should try to connect. You're close with traefik.docker.network=web
but that's not really the name of the network. The network will get a prefix for the project or stack name.
To hard code the network name, you can use the name field in the final network section (this is specific to version 3.5 or newer):
version '3.5'
services:
...
networks:
web:
name: web
backend:
Otherwise, set the project in your label (this is usually the current directory name when using docker-compose
):
labels:
...
- "traefik.docker.network=your_project_name_here_web"