Jan 24, 2019 · by Tim Kamanin
Traefik is a great reverse-proxy for Docker, but it can take some time to set it up correctly.
Here I'm posting a reference config that adds a domain name, a certificate generated by letsencrypt and directs all incoming traffic to a container of choice.
Before we begin let's prepare the following directory structure:
- app # this where our app lives - traefik # directory to hold traefik config - volumes # here we store our local mounts
At first, we create a
version: "3" services: app: build: ./app # A node app command: pm2-docker start server.js # Start server via pm2 ports: - 3000 labels: - "traefik.enable=true" # Enable reverse-proxy for this service - "traefik.frontend.rule=Host:example.com" # Domain name for the app reverse-proxy: image: traefik command: --api # Enables the web UI - "80:80" # The HTTP port - "443:443" # The HTTPS port - "8080:8080" # The web UI volumes: - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events - ./traefik/traefik.toml:/traefik.toml # Traefik configuration file - ./volumes/traefik-acme:/acme # Tell Traefik to save SSL certs here
The app service is not essential here; it can be any Docker service, the primary requirement it should fulfill is to have
labels defined as in the example.
Note how we mapped
./volumes/traefik-acme:/acme volumes. In official Traefik document the suggested mapping is something like
./volumes/acme.json:/acme.json. But if we map a file to a file instead of a directory to a directory we'll get a nasty error Failed to read new account, ACME data conversion is not available : read acme.json: is a directory. Btw, thanks to this error I'm writing this post.
Now let's add a
traefik/traefik.toml file with the following contents:
debug = false logLevel = "ERROR" defaultEntryPoints = ["https","http"] [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.redirect] entryPoint = "https" [entryPoints.https] address = ":443" [entryPoints.https.tls] [retry] [docker] exposedByDefault = false [acme] email = "email@example.com" storage = "acme/certs.json" entryPoint = "https" onHostRule = true [acme.httpChallenge] entryPoint = "http"
Notice how we defined
acme/certs.json, this is to prevent the acme.json mapping issue I've described earlier.
Now you can go and run
docker-compose up on your server, and if everything is done right, you should be able to access your service via https://example.com. If you have issues, please check the Web UI output at https://example.com:8080 and make sure you run this setup on a server, not on your local machine.
This is because
acme in Traefik is letsencrypt.org and to generate a certificate for you, it needs to make a callback to your server and access Traefik reverse-proxy via the domain name that you've defined (example.com in our case).
Hope this all works for you... or for future me.
Hey, if you've found this useful, please share the post to help other folks find it: