Help wanted: HTTPS redirection with custom ports

Hi everyone !

I'm trying to use Traefik on Docker as an internal reverse-proxy for a container, but no matter what I try, it keeps exposing that container to the Internet.
I want 1 router to expose it internally, and 1 for the Internet. The Internet one works well.

I have a container A that must call another container B on port 80/443, but B only exposes port 2000.
Since A and B are on the same machine, I don't want to expose B on the Internet.

My idea is: A calls http://b.lan, Traefik catches it through a label on B, and passes the traffic to B port 2000.

Everytime I try to use a label on B, it gets exposed to the Internet.
Is there anyway to prevent this ?

PS: I have also tried to whitelist my LAN, but Traefik can only whitelist based on X-Forwarded-For and surprisingly doesn't provide that header on response and neither does B so no luck there.

Has anyone gone through this situation before and found a way ? Please tell me I'm getting desperate

Many thanks to everyone who tries to help :slight_smile:

Hello @schklom

Yes it's possible.
You have to play with networks.

Container A : Traefik expose in web
Container B : Mariadb in local

This is a docker-compose example.

version: '3.7'
services:

# Traefik
  traefik:
    image: traefik:latest
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
    environment:
      - "TZ=Europe/Paris"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./config.yml:/etc/traefik/traefik.yml:ro
      - ./config/:/etc/traefik/custom/:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - traefik
    restart: unless-stopped

database:
    image: mariadb:10
    container_name: db
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: unless-stopped
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
      MYSQL_USER_FILE: '/run/secrets/mysql-user'
      MYSQL_DATABASE_FILE: '/run/secrets/mysql-database'
      MYSQL_PASSWORD_FILE: '/run/secrets/mysql-password'
    secrets:
      - mysql-user
      - mysql-database
      - mysql-password
    networks:
      - lan
    volumes:
      - db:/var/lib/mysql

# Network config
networks:
  traefik:
    name: traefik
    external: true
  lan:
    name: lan
    external: false

With this configuration a container created with the network "traefik" will be exposed on the internet, and with the network "lan" only locally

Hoping to help you,

Hello @asterix, thanks for replying :slight_smile:
It seems that you put them on 2 different networks, and traefik can't redirect traffic to db.

Maybe I wasn't clear enough on what I want to do, so I will use your example to make it simpler.


Let's define container abc along with traefik and db.
db only has 3306 as an internal port.
So if you want to reach db from lan, you must call http://db:3306.

The problem is that abc can only call containers on port 80 (i.e. abc must call http://db or http://db.mysite.com). I don't want to mess with the source code of abc so I need to respect this constraint.

I could add

    ports:
      - "80:3306"

to db but port 80 is already exposed by traefik, so no.

Therefore, what I'm trying to do is:

  • abc calls http://db.mysite.com
  • traefik catches it
  • redirects to db:3306

But I don't want db.mysite.com to be on the Internet.
Ideally, I want this to work

version: '3.7'
services:

# Traefik
  traefik:
    image: traefik:latest
    container_name: traefik
    ports:
      - "80:80"
      - "443:443"
    environment:
      - "TZ=Europe/Paris"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./config.yml:/etc/traefik/traefik.yml:ro
      - ./config/:/etc/traefik/custom/:ro
      - ./letsencrypt:/letsencrypt
    networks:
      - traefik
    restart: unless-stopped

  database:
    image: mariadb:10
    container_name: db
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: unless-stopped
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
      MYSQL_USER_FILE: '/run/secrets/mysql-user'
      MYSQL_DATABASE_FILE: '/run/secrets/mysql-database'
      MYSQL_PASSWORD_FILE: '/run/secrets/mysql-password'
    secrets:
      - mysql-user
      - mysql-database
      - mysql-password
    networks:
      - lan
    volumes:
      - db:/var/lib/mysql
    labels:
      - traefik.enable=true
      - traefik.http.routers.db_rtr.entrypoints=web # port 80
      - traefik.http.routers.db_rtr.rule=Host(`db.mysite.com`)
      # service
      - traefik.http.services.db_svc.loadbalancer.server.port=3306
      - traefik.http.routers.db_rtr.service=db_svc
      # middleware (I can't make it work)
      - traefik.http.middlewares.lan_mw.ipwhitelist.sourcerange=abc
      - traefik.http.routers.db_rtr.middlewares=lan_mw@docker

  abc:
    image: something
    networks:
      - lan
      - traefik
    depends_on:
      - db
      - traefik

# Network config
networks:
  traefik:
    name: traefik
    external: true
  lan:
    name: lan
    external: false


PS: I think you're misunderstanding what

    external: false

does :stuck_out_tongue:
The doc says

If set to true , specifies that this network has been created outside of Compose. docker-compose up does not attempt to create it, and raises an error if it doesn’t exist.

Best, and keep safe :slight_smile:

Hello @schklom

Sorry I misunderstood it's true

I'm having trouble understanding your problem can you share your code?

Asterix,