Add Docker Microservices to Traefik

Hi all

I would like to use Traefik as our reverse proxy in the new docker environment we're spinning up.

The components consist of:

  • traefik container to manage routing
  • web-app container with nginx
  • microservice 1 container
  • microservice 2 container
  • microservice n...

Traefik takes the incoming traffic on 80 and 443 and forwards it to the web-app container. The web-app container then calls the other microservices for authentication, api calls and more.

So far I have Traefik and the web-app working together on SSL with the following docker-compose config (have to figure out later how to secure the dashboard too):

version: '3.7'

secrets:
  cf_api_email:
    file: "path/to/config"
  cf_dns_api_token:
    file: "path/to/config"
    
services:
  traefik:
    image: traefik:latest
    volumes:
      - "./config/letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    #  - "/etc/localtime:/etc/localtime"
    command:
      - "--log.level=DEBUG"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.dashboard.address=:8080"
      - "--certificatesresolvers.mydnschallenge.acme.dnschallenge=true"
      - "--certificatesresolvers.mydnschallenge.acme.dnschallenge.provider=cloudflare"
      #- "--certificatesresolvers.mydnschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.mydnschallenge.acme.email=mail@contoso.com"
      - "--certificatesresolvers.mydnschallenge.acme.storage=/letsencrypt/acme.json"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`contoso.io`) && PathPrefix(`/dashboard`)"
      - "traefik.http.routers.api.entryPoints=dashboard"
      - "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
      - "traefik.http.routers.api.service=api@internal"
      - "traefik.http.routers.api.middlewares=api-auth"
      - "traefik.http.middlewares.api-auth.basicauth.users=user:password"
      - "traefik.http.routers.https-redirect.entrypoints=web"
      - "traefik.http.routers.https-redirect.rule=HostRegexp(`{any:.*}`)"
      - "traefik.http.routers.https-redirect.middlewares=https-redirect"
      - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
    networks:
      - traefik_proxy
      - default
    ports:
      - "80:80"
      - "443:443"
      - "7777:8080"
    secrets:
      - "cf_api_email"
      - "cf_dns_api_token"
    environment:
      - "CF_API_EMAIL_FILE=/run/secrets/cf_api_email"
      - "CF_DNS_API_TOKEN_FILE=/run/secrets/cf_api_key"  
    restart: always

  contoso-web-app:
    image: <image>
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.contoso-web-app.rule=Host(`contoso.com`)"
      - "traefik.http.routers.contoso-web-app.entrypoints=websecure"
      - "traefik.http.routers.contoso-web-app.tls.certresolver=mydnschallenge"
    networks:
      - traefik_proxy
      - default

networks:
  traefik_proxy:
    external:
      name: traefik_proxy
  default:
    driver: bridge

Everything works fine so far and now I'm trying to add the microservices without any sucess.
I have them in a separate docker-compose (will also separate the web-app into an own file) and the web-app is not able to reach them.
As an example, the web-app called: https://contoso.com/api/v1/auth/
The API is running on the microservice under: https://contoso.com:2001/api/v1/auth/

This is the config I have used for the microservice:

version: '3.7'

services:
  redis:
    image: 'redis:5.0'
    ports:
      - "6379"
    volumes:
      - ./data/redis:/bitnami/redis/data
    networks:
      - traefik_proxy
      - default

  contoso-auth-service:
    image: <image>
    ports:
      - "2001:2000"
    depends_on:
      - 'redis'
    networks:
      - traefik_proxy
      - default
    labels:
      - "traefik.enable=true"
      #- "traefik.http.routers.contoso-web-app.rule=PathPrefix(`/api/v1/auth`)" # did not work
      - "traefik.http.routers.contoso-auth-service.rule=Host(`contoso.com`) && PathPrefix(`/api/v1/auth`)"
      - "traefik.http.routers.contoso-auth-service.tls.certresolver=mydnschallenge"
      - "traefik.http.services.contoso-auth-service.loadbalancer.server.port=2001"

networks:
  traefik_proxy:
    external:
      name: traefik_proxy
  default:
    driver: bridge

Would greatly appreciate your help

Kind regards

Hello,

I think it's a network problem, your containers are on multiple networks, so you have to tell traefik which network should be used.

https://docs.traefik.io/v2.1/providers/docker/#network

Hi @ldez

Many thanks for your reply!

I just tried to remove the additional network (only bridge is described in docker-compose) and restarted all containers, but I'm still unable to access:

https://contoso.com:2001/api/v1/auth/ (microservice directly)
https://contoso.com/api/v1/auth/ (proxied)

Do I need to add additional labels or change the entrypoint of the container microservice or traefik itself?

contoso-auth-service:
    image: <image>
    ports:
      - "2001:2000"
    depends_on:
      - 'redis'
    networks:
      - default
    labels:
      - "traefik.enable=true"
      #- "traefik.http.routers.contoso-web-app.rule=PathPrefix(`/api/v1/auth`)" # did not work
      - "traefik.http.routers.contoso-auth-service.rule=Host(`contoso.com`) && PathPrefix(`/api/v1/auth`)"
      - "traefik.http.routers.contoso-auth-service.tls.certresolver=mydnschallenge"
      - "traefik.http.services.contoso-auth-service.loadbalancer.server.port=2001"

you have to set entry point on all your routers.

- "traefik.http.routers.contoso-auth-service.entrypoints=websecure"

also the port must the port of your app and not the port defined in the docker-compose file.

 - "traefik.http.services.contoso-auth-service.loadbalancer.server.port=2000"