Search code examples
dockerdocker-composetraefik

Can't get correct container IP using traefik


When using Traefik and Docker-compose, I would like to get the container IP to perform IP-based filtering but instead get the docker network gateway IP.

Here is the results of a curl request from the curl-client container:

docker-compose exec curl-client curl https://whoami.domain.name

Hostname: 608f3dcaf7d9
IP: 127.0.0.1
IP: 172.18.0.2
GET / HTTP/1.1
Host: whoami.domain.name
User-Agent: curl/7.58.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 172.18.0.1
X-Forwarded-Host: whoami.domain.name
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: 88756553599b
X-Real-Ip: 172.18.0.1    

Here, 172.18.0.1 is the gateway for the traefik_net network. Instead, I would expect to see 172.18.0.9 in the X-Forwarded-For field, as it is the IP of the curl-client container:

docker-compose exec curl-client cat /etc/hosts

172.18.0.9      34f7b6e5472f

I've also tried using the 'traefik.frontend.whiteList.useXForwardedFor=true' option without success.

traefik.toml

logLevel = "ERROR"

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
  [entryPoints.http]
    address = ":80"
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
    address = ":443"
    [entryPoints.https.tls]

[api]
entrypoint="dashboard"

[acme]
email = "something@aaa.com"
storage = "acme.json"
entryPoint = "https"
  [acme.dnsChallenge]
  provider = "ovh"
  delayBeforeCheck = 0

[[acme.domains]]
  main = "*.domain.name"

[docker]
domain = "domain.name"
watch = true
network = "traefik_net"

docker-compose.yml

version: '3'

services:

  traefik_proxy:
    image: traefik:alpine
    container_name: traefik
    networks:
      - traefik_net
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik.toml:/traefik.toml
      - ./acme.json:/acme.json
    restart: unless-stopped
    environment:
      - OVH_ENDPOINT=ovh-eu
      - OVH_APPLICATION_KEY=secretsecret
      - OVH_APPLICATION_SECRET=secretsecret
      - OVH_CONSUMER_KEY=secretsecret
    labels:
      - 'traefik.frontend.rule=Host:traefik.domain.name'
      - 'traefik.port=8080'
      - 'traefik.backend=traefik'


  whoami:
    image: containous/whoami
    container_name: whoami
    networks:
      - traefik_net
    labels:
      - 'traefik.frontend.rule=Host:whoami.domain.name'


  curl-client:
    image: ubuntu
    networks:
      - traefik_net
    command: sleep infinity



networks:
  traefik_net:
    external: true

Edit: The domain name is resolved using the following dnsmasq.conf:

domain-needed
expand-hosts
bogus-priv

interface=eno1
domain=domain.name
cache-size=1024
listen-address=127.0.0.1
bind-interfaces

dhcp-range=10.0.10.10,10.0.10.100,24h
dhcp-option=3,10.0.10.1

dhcp-authoritative

server=208.67.222.222
server=208.67.220.220

address=/domain.name/10.0.10.3

Solution

  • After some investigation it seems that Traefik is not the problem here, the inability to access the container IP is due to the way Docker manages its internal network (see the following comments: https://github.com/containous/traefik/issues/4352 and https://github.com/docker/for-mac/issues/180).

    I was able to achieve my goal of whitelisting internal connections by running my openvpn container in nework_host mode, this way the client is assigned an IP by the system directly.