All Articles

🚦🖥 Traefik and Docker labels

Here’s a small tip for if you have various containers running in a homelab that have front-ends.

There’s a number of options available to expose them to your local network like using a host port, assigning a dedicated IP from your LAN via MacVLAN or you could use a reverse proxy like Traefik.

The normal way to configure Traefik uses a config file which I found too much hassle with after a number of containers. Here’s an alternative and what I use in my setup instead:

My Traefik configuration:

version: '3.5'
services:
  traefik:
    image: traefik:latest
    container_name: traefik
    restart: unless-stopped
    hostname: traefik
    mac_address: 4a:86:5d:xx:xx:xx
    command:
      - "--api"
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--api.dashboard"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.dnschallenge=true"
      - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare"
      - "--certificatesresolvers.myresolver.acme.email=xxx"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
      - "--certificatesResolvers.myresolver.acme.dnsChallenge.delayBeforeCheck=15"
    networks:
      macvlan0:
        ipv4_address: 10.0.0.201
      traefik_public:

    environment:
      - CLOUDFLARE_EMAIL=xxx
      - CF_DNS_API_TOKEN=xxx
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
networks:
    macvlan0:
      external: true
    traefik_public:
      driver: overlay
      external: true

Most importantly it exposes Traefik on a dedicated IP.

Next a service:

version: "3.3"
networks:
  traefik_public:
    driver: overlay
    external: true
services:
  it-tools:
    container_name: it-tools
    restart: unless-stopped
    image: "corentinth/it-tools:latest"
    networks:
      traefik_public:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.ittool.rule=Host(`tools`)"
      - "traefik.http.routers.ittool.entrypoints=web"

The power here is the use of labels.

  - "traefik.http.routers.ittool.rule=Host(`tools`)"

This line tells Traefik which hostname to listen to, you can then add this to your home DNS server as an internal name -> 10.0.0.201 (my Traefik instance).

  - "traefik.http.routers.ittool.entrypoints=web"

The entry point to use, if the service is listening on HTTPs I use websecure.

Your service is now exposed on http://tools/

That’s it! It’s a fast and easy way to expose a service and saves on your internal networks IP address space.

Published Jun 12, 2023

Londoner. Senior Engineer of things Platform and DevOps.