Search code examples
dockertraefiklocalserver

Traefik setup on docker returning gateway timeout


I am setting up a local Debian server with Docker and multiple containers/services. I am trying to point a subdomain to each container with Traefik, it doesn't work and I don't know where the problem is.

I have created traefik and test-only containers following this guide, but I get gateway timeout when I call curl foo.myserver.local (see source code below).

# foo/docker-compose.yml
services:
  foo:
    image: httpd:alpine
    container_name: foo
    ports:
      - '9999:80'
    volumes:
      - ./website:/usr/local/apache2/htdocs

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.cal.rule=Host(`foo.myserver.local`)"
      - "traefik.http.routers.cal.entrypoints=web"
      - "traefik.http.services.cal.loadbalancer.server.port=9999"

Foo website:

# foo/website/index.html
Foo page

Traefik container:

# traefik/docker-compose.yml
services:
  traefik:
    image: traefik:v2.0
    container_name: traefik
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    restart: unless-stopped
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Hosts file:

# /etc/hosts

127.0.0.1       localhost
192.168.3.17   myserver.local      myserver
192.168.3.17   foo.myserver.local  myserver


# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Some tests:

user@myserver:~$ curl myserver.local
404 page not found

user@myserver:~$ curl foo.myserver.local
Gateway Timeout

user@myserver:~$ curl 192.168.3.17
404 page not found

user@myserver:~$ curl 192.168.3.17:9999
Foo page

user@myserver:~$ curl localhost
404 page not found

user@myserver:~$ curl localhost:9999
Foo page

Update 1

I have followed @Rockvlv answer and solved the problem by merging both docker-compose.yml files and by removing the port number:

# traefik/docker-compose.yml
services:
  traefik:
    image: traefik:v2.0
    container_name: traefik
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
    restart: unless-stopped
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  foo:
    image: httpd:alpine 
    container_name: foo
    volumes:
      - ./website:/usr/local/apache2/htdocs

    labels:
      - "traefik.http.routers.foo.rule=Host(`foo.myserver.local`)"

Next step is to learn how to split this compose file.

Update 2

Once more, I have followed @Rockvlv instructions and split the docker-compose files. The only difference was the network creation. I have used the automatically created traefik_default.

# traefik/docker-compose.yml
services:
  traefik:
    image: traefik:v2.0
    container_name: traefik
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
    restart: unless-stopped
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

# foo/docker-compose.yml
services:
  foo:
    image: httpd:alpine
    container_name: foo
    volumes:
      - ./website:/usr/local/apache2/htdocs
    networks:
      - traefik
    labels:
      - "traefik.http.routers.foo.rule=Host(`foo.myserver.local`)"

networks:
  traefik:
    name: traefik_default
    external: true

Solution

  • In official documentation you can find the example of service configuration

    version: "3"
    services:
      my-container:
        deploy:
          labels:
            - traefik.http.routers.my-container.rule=Host(`example.com`)
            - traefik.http.services.my-container.loadbalancer.server.port=8080
    

    When we set labels for Traefik we should set a proper name of service. As in example above service is called my-container and in labels we are referring to that name ...routers.my-container. ...

    UPDATE 1

    @msampaio It's not hard to split docker-compose on smaller chunks, all you need to remember that containers that you want to expose using Traefik should be running in same network. To do this you will need few steps:

    1. Create a docker network
    2. Set a networks: block in each docker-compose file
    networks:
      proxy:
        external: true
    
    1. Make sure to set in command for Traefik a information about which network to use
    --providers.docker.network=proxy
    
    1. Also in service definition you need to set networks parameter as well
    version: '3.8'
    services:
     nginx:
       image: nginx
       networks:
         - proxy
    

    After this manipulations you will be able to have as much docker-compose.yml files as you need.