Port forwarding problem using Traefik and docker

Hi!

I want the next port forwarding:

http://traefik.service.localhost/ -> Traefik UI

http://api.service.localhost/ -> 'Hello-Word' page from api-service

Here is my attempt to create appropriate docker-compose.yml file:

version: '3.8'

services:

  reverse-proxy:
    image: traefik:v2.4
    container_name: reverse-proxy
    command: 
      - "--api.insecure=true"
      - "--providers.docker"
    ports:
      - "80:80"
      - "8080:8080"
    labels:
      - traefik.enable=true
      - traefik.docker.network=pred-network
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - pred-network


  api-service:
    image: x86_64/prediction-service:0.8.1
    container_name: api-service
    environment:
      SERVING_SERVICE: model-service
    expose:
      - 80
    labels:
      - traefik.enable=true
      - traefik.http.routers.api-service.rule=Host(`api.service.localhost`)
    networks:
      - pred-network

networks:
  pred-network:

I am getting the following:

http://traefik.service.localhost/ -> HTTP Error 404. The requested resource is not found.

http://api.service.localhost/ -> HTTP Error 404. The requested resource is not found.

The only link that actually works:

http://api.service.localhost:8080/ -> Traefik UI

If I would include:

ports:
  - "8070:80"

into api-service part of docker-compose.yml I could access my 'Hello-Word':
http://localhost:8070/ -> "Hello-Word"
In this case it not get routed through Traefik but directly through api-service. Is it possible to do it over Traefik?

I would appreciate any ideas!

To have a service routed by traefik with docker, you should have labels. Traefik will fetch those labels in order to know how to do routing.

Thus, to have request of api.service.localhost routed to your api service, you should have the label that define the corresponding rule:

traefik.http.routers.service.rule=Host(`api.service.localhost`)

As for the label of Traefik, you should have two labels:

traefik.http.routers.traefik.rule=Host(`traefik.service.localhost`)
traefik.http.routers.traefik.service=api@internal

Beside those traefik labels, you should tell traefik to expose the dashboard using a specific service by adding this configuration: --api.dashboard (More help to expose the dashboard here).

Note, if your api service uses another port than the one by default, you could add this label:

traefik.http.services.service.loadbalancer.server.port=80 

Here is a working example for you:

version: '3.7'

services:
  traefik:
    image: traefik:2.4
    command:
      - '--api.dashboard'
      - '--providers.docker'
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    labels:
      - traefik.http.routers.traefik.rule=Host(`traefik.service.localhost`)
      - traefik.http.routers.traefik.service=api@internal
  whoami:
    image: traefik/whoami
    labels:
      - traefik.http.routers.service.rule=Host(`api.service.localhost`)
      - traefik.http.services.service.loadbalancer.server.port=80

Ps, please refrain from using --api.insecure=true , this is insecure !

@tommoulard
Thank you for answer.

I do not know why but I still cannot access desirable paths.

Here is my full updated code:

version: '3.8'

services:
  reverse-proxy:
    image: traefik:v2.4
    container_name: reverse-proxy
    command: 
      - "--api.dashboard"
      - "--providers.docker"
    ports:
      - "80:80"
      - "8080:8080"
    labels:
      - traefik.http.routers.traefik.rule=Host(`traefik.service.localhost`)
      - traefik.http.routers.traefik.service=api@internal
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - pred-network
  api-service:
    image: x86_64/prediction-service:0.8.1
    container_name: api-service
    environment:
      SERVING_SERVICE: model-service
    expose:
      - 80
    labels:
      - traefik.http.routers.service.rule=Host(`api.service.localhost`)
      - traefik.http.services.service.loadbalancer.server.port=80
    networks:
      - pred-network

networks:
  pred-network:

@al-yakubovich

This topic is posted with the swarm label, are you actually using docker swarm with this compose ?

@cakiwi
No, but I am planning to use Swarm