lovis91
lovis91

Reputation: 2171

Docker-compose and traefik port mapping

I'm currently trying to run multiple instances of the same docker-compose file.

Each instance have a traefik service which should only listen for a given host.

I want to have only one docker-compose file, and all params are stored in env variables. Each instance is run in its own directory.

In order to do that, i want traefik to redirect the http traffic (80 and 443) to my internal network, with the ability to define custom ports (eg 81 and 444) to avoid conflict when running more than one instance.

I try to use traefik constraint and port mapping, but if i put other values than 80, 443, and 8080 to TRAEFIK_XXX vars, no traffic seem to reach my containers.

Here is the relevant part of my docker-compose file :

version: "3.9"

services:
  traefik:
    image: traefik:2.10.7
    restart: always
    networks:
      - traefik
    ports:
      - "${TRAEFIK_HTTP_PORT}:80"
      - "${TRAEFIK_HTTPS_PORT}:443"
      - "${TRAEFIK_API_PORT}:8080"
    command:
      # provider
      - "--providers.docker=true"

      # log
      - "--log.level=DEBUG"

      # entry points
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"

      # for https
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"

      # constraint
      - "--providers.docker.constraints=Label(`traefik.constraint-label`, `traefik_${INSTANCE_ID}`)"

    labels:
      - "traefik.enable=true"
      - "traefik.constraint-label=traefik_${INSTANCE_ID}"
      - "traefik.docker.network=traefik_${INSTANCE_ID}"
      - "traefik.http.routers.traefik.rule=Host(`traefik.${BASE_DOMAIN}`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.tls.certresolver=myresolver"

  strapi:
    build:
      context: ./strapi
      dockerfile: Dockerfile.prod
    restart: unless-stopped
    hostname: "strapi.${BASE_DOMAIN}"
    depends_on:
      - postgres
      - redis
    networks:
      - samplstrap
      - traefik
    ports:
      - "${STRAPI_PORT}:1337"
    labels:
      - "traefik.enable=true"
      - "traefik.constraint-label=traefik_${INSTANCE_ID}"
      - "traefik.docker.network=traefik_${INSTANCE_ID}"
      - "traefik.http.services.strapi.loadbalancer.server.port=1337"
      - "traefik.http.routers.strapi.rule=Host(`strapi.${BASE_DOMAIN}`)"
      - "traefik.http.routers.strapi.entrypoints=websecure"
      - "traefik.http.routers.strapi.tls.certresolver=myresolver"

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.prod
    restart: always
    depends_on:
      - strapi
    networks:
      - samplstrap
      - traefik
    volumes:
      - frontend_node_modules:/app/frontend/node_modules
    ports:
      - "${FRONTEND_PORT}:3000"
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_${INSTANCE_ID}"
      - "traefik.constraint-label=traefik_${INSTANCE_ID}"
      - "traefik.http.services.frontend.loadbalancer.server.port=3000"
      - "traefik.http.routers.frontend.rule=Host(`www.${BASE_DOMAIN}`, `${BASE_DOMAIN}`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.routers.frontend.tls.certresolver=myresolver"
  
networks:
  traefik:
    external: true
    name: traefik_${INSTANCE_ID}
  samplstrap:
    internal: true

Thanks !

Upvotes: 1

Views: 368

Answers (1)

Emil Carpenter
Emil Carpenter

Reputation: 2209

A better solution for that setup is probably having one docker-compose file for Traefik and then another docker-compose file for all other services. Because only one Traefik container is needed and the other services are to be run as several instances.

My suggestions start with ### in the code.

File to be used only in/for one directory/instance:

Filename: compose.traefik.yml

services:
  traefik:
    image: traefik:2.10.7
    restart: always
    networks:
      - traefik
    ports:
      ### Ports without variables, always like this
      - "80:80"
      - "443:443"
      - "8080:8080"

    ### This needs to be added
    volumes: 
      - /var/run/docker.sock:/var/run/docker.sock:ro

    command:
      # provider
      - "--providers.docker=true"

      # log
      - "--log.level=DEBUG"

      # entry points
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"

      # for https
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"

      # constraint
      ### Remove this line
      #- "--providers.docker.constraints=Label(`traefik.constraint-label`, `traefik_${INSTANCE_ID}`)"

    labels:
      - "traefik.enable=true"

      ### Remove this line
      #- "traefik.constraint-label=traefik_${INSTANCE_ID}"

      - "traefik.docker.network=traefik"
      - "traefik.http.routers.traefik.rule=Host(`traefik.${BASE_DOMAIN}`)"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.tls.certresolver=myresolver"

networks:
  traefik:
    external: true
    ### Network name just 'traefik'
    name: traefik

File to be used in/for several directories/instances:

Filename: compose.instance.yml

services:

  strapi:
    build:
      context: ./strapi
      dockerfile: Dockerfile.prod
    restart: unless-stopped
    hostname: "strapi.${BASE_DOMAIN}"
    depends_on:
      - postgres
      - redis
    networks:
      - samplstrap
      ### Network name just 'traefik'
      - traefik

    ### Remove this
    #ports:
    #  - "${STRAPI_PORT}:1337"

    labels:
      - "traefik.enable=true"

      ### Remove this line
      #- "traefik.constraint-label=traefik_${INSTANCE_ID}"

      ### Network name just 'traefik'
      - "traefik.docker.network=traefik"

      ### Remove this line
      #- "traefik.http.services.strapi.loadbalancer.server.port=1337"

      - "traefik.http.routers.strapi.rule=Host(`strapi.${BASE_DOMAIN}`)"
      - "traefik.http.routers.strapi.entrypoints=websecure"
      - "traefik.http.routers.strapi.tls.certresolver=myresolver"

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.prod
    restart: always
    depends_on:
      - strapi
    networks:
      - samplstrap
      ### Network name just 'traefik'
      - traefik
    volumes:
      - frontend_node_modules:/app/frontend/node_modules

    ### Remove this
    #ports:
      #- "${FRONTEND_PORT}:3000"

    labels:
      - "traefik.enable=true"

      ### Network name just 'traefik'
      - "traefik.docker.network=traefik"

      ### Remove this line
      #- "traefik.constraint-label=traefik_${INSTANCE_ID}"

      ### Remove this line
      #- "traefik.http.services.frontend.loadbalancer.server.port=3000"

      - "traefik.http.routers.frontend.rule=Host(`www.${BASE_DOMAIN}`, `${BASE_DOMAIN}`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.routers.frontend.tls.certresolver=myresolver"
  
networks:
  traefik:
    external: true
    ### Network name just 'traefik'
    name: traefik
  samplstrap:
    internal: true

This answer is for making Traefik configuration work. Methods or ports for communication between strapi and frontend is not in the scope of this answer.

Upvotes: 1

Related Questions