Skip to content

Traefik:v2

Traefik v2 에 대한 설명

Redirection http to https

--entrypoints.web.address=:80
--entrypoints.web.http.redirections.entryPoint.to=websecure
--entrypoints.web.http.redirections.entryPoint.scheme=https
--entrypoints.web.http.redirections.entrypoint.permanent=true
--entrypoints.websecure.address=:443

Example:

  traefik:
    image: traefik:v2.2
    command:
      - "--providers.docker"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

Quick Start

version: "3.8"

services:

  traefik:
    image: "traefik:v2.4"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      - "traefik.http.routers.whoami.entrypoints=web"

HTTPS with Let's Encrypt

TLS Challenge

version: "3.3"

services:

  traefik:
    image: "traefik:v2.10"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=postmaster@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"
  1. 도메인을 해당 서버 IP로 연결하고
  2. 서버의 443 번 포트 인바운드 오픈
  3. [email protected]를 내 메일주소로 변경.
  4. whoami.example.com를 내 도메인으로 변경.
  5. docker compose up -d
  6. 도메인으로 접속. (바로 접속 안되고 좀 기다려야함)

HTTP Challenge

version: "3.3"

services:

  traefik:
    image: "traefik:v2.10"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
      #- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myresolver.acme.email=postmaster@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "traefik/whoami"
    container_name: "simple-service"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`whoami.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=myresolver"
  1. 도메인을 해당 서버 IP로 연결하고
  2. 서버의 80, 443 번 포트 인바운드 오픈
  3. [email protected]를 내 메일주소로 변경.
  4. whoami.example.com를 내 도메인으로 변경.
  5. docker compose up -d
  6. 도메인으로 접속. (바로 접속 안되고 좀 기다려야함)

Load Balancer

주의할 점은 swarm에서 사용할 때 처럼 deploy:안에 라벨을 적으면 안된다. 밖에 적어야 한다.

version: "3.3"

services:
  traefik:
    image: "traefik:v2.10"
    restart: always
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.your_resolver.acme.tlschallenge=true"
      - "--certificatesresolvers.your_resolver.acme.email=${ACME_EMAIL:?err}"
      - "--certificatesresolvers.your_resolver.acme.storage=/letsencrypt/acme.json"
      #-"--log.level=DEBUG"
    ports:
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"

  master:
    image: "ghcr.io/yourid/your-work:master"
    restart: always
    depends_on:
      - traefik
    deploy:
      mode: replicated
      replicas: 4
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.your_master.rule=Host(`${FRONTEND_HOST:?err}`)"
      - "traefik.http.routers.your_master.entrypoints=websecure"
      - "traefik.http.routers.your_master.tls.certresolver=your_resolver"
      - "traefik.http.services.your_master.loadbalancer.server.port=80"
    command:
      - "master"
      - "--port=80"
      - "--broker=${BROKER_URL:?err}"

PostgreSQL and Redis

version: "3.7"

services:
  proxy:
    image: traefik:latest
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      # Endpoints setup
      - "--entrypoints.postgres.address=:5432" # PostgreSQL endpoint
      - "--entrypoints.redis.address=:6379" # Redis endpoint
    ports:
      - "6969:8080" # Traefik dashboard
      - "5432:5432" # PostgreSQL port
      - "6379:6379" # Redis port
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  postgres:
    image: postgres
    restart: always
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASS}
    volumes:
      - ./appdata/postgres:/var/lib/postgresql/data
    labels:
      - "traefik.enable=true"
      # routers
      - "traefik.tcp.routers.postgres.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.postgres.entryPoints=postgres"
      - "traefik.tcp.routers.postgres.service=postgres"
      # services (needed for TCP)
      - "traefik.tcp.services.postgres.loadbalancer.server.port=5432"

  redis:
    image: bitnami/redis:latest
    restart: always
    environment:
      # ALLOW_EMPTY_PASSWORD is recommended only for development.
      - ALLOW_EMPTY_PASSWORD=yes
      - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
    volumes:
      - ./appdata/redis:/bitnami/redis/data
    labels:
      - "traefik.enable=true"
      # routers
      - "traefik.tcp.routers.redis.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.redis.entryPoints=redis"
      - "traefik.tcp.routers.redis.service=redis"
      # services (needed for TCP)
      - "traefik.tcp.services.redis.loadbalancer.server.port=6379"

Troubleshooting

Filtering unhealthy or starting container

your-master-traefik-1  | time="2023-11-24T12:11:51Z" level=debug msg="Serving default certificate for request: \"api.your.run\""
your-master-traefik-1  | time="2023-11-24T12:11:51Z" level=debug msg="http: TLS handshake error from 121.167.254.11:51798: local error: tls: bad record MAC"
your-master-traefik-1  | time="2023-11-24T12:12:13Z" level=debug msg="Serving default certificate for request: \"api.your.run\""
your-master-traefik-1  | time="2023-11-24T12:12:13Z" level=debug msg="http: TLS handshake error from 121.167.254.11:43892: local error: tls: bad record MAC"
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Serving default certificate for request: \"api.your.run\""
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Provider event received {Status:health_status: unhealthy ID:3b062375ee2d62985a84103335c5153b928f51ac35e4c70aaf58546d6b300197 From:ghcr.io/yourid/your-api:latest Type:container Action:health_status: unhealthy Actor:{ID:3b062375ee2d62985a84103335c5153b928f51ac35e4c70aaf58546d6b300197 Attributes:map[com.docker.compose.config-hash:3566c90185ea8f97f365687e0179beec0d8910c49b2a393c47d6b350a91ad56e com.docker.compose.container-number:1 com.docker.compose.depends_on:traefik:service_started:false com.docker.compose.image:sha256:c1939588c20c7da364a34a7ca9f6ce31bf96c87b65d57a57b337653b35295ad3 com.docker.compose.oneoff:False com.docker.compose.project:your-master com.docker.compose.project.config_files:/home/your/Project/your-api/docker-compose.master.yml com.docker.compose.project.working_dir:/home/your/Project/your-api com.docker.compose.service:master com.docker.compose.version:2.18.1 image:ghcr.io/yourid/your-api:latest name:your-master-master-1 org.opencontainers.image.created:2023-11-24T07:37:17.039Z org.opencontainers.image.description:your api org.opencontainers.image.licenses:MIT org.opencontainers.image.revision:75336e4a42950a7e4cc90745a57391db1b37eb32 org.opencontainers.image.source:https://github.com/yourid/your-api org.opencontainers.image.title:your-api org.opencontainers.image.url:https://github.com/yourid/your-api org.opencontainers.image.version:0.0.7 traefik.enable:true traefik.http.routers.master.entrypoints:websecure traefik.http.routers.master.rule:Host(`api.your.run`) traefik.http.routers.master.tls.certresolver:resolver]} Scope:local Time:1700827948 TimeNano:1700827948848883214}" providerName=docker
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Filtering unhealthy or starting container" providerName=docker container=master-your-master-3b062375ee2d62985a84103335c5153b928f51ac35e4c70aaf58546d6b300197
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Filtering disabled container" container=traefik-your-master-1117e84b730dcf810f6202d45db7249f71a73b27f24ef507a907a534b40799f4 providerName=docker
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Filtering disabled container" container=redis-your-redis-0fe2d35f7ade83c3c18c81cc2692768aa8b8c83c60bf05514f4fb834ab2ccada providerName=docker
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Configuration received: {\"http\":{},\"tcp\":{},\"udp\":{}}" providerName=docker
your-master-traefik-1  | time="2023-11-24T12:12:28Z" level=debug msg="Skipping unchanged configuration." providerName=docker

docker ps -a 명령으로 확인해보면 다음과 같이 unhealthy 상태가 확인된다:

...
3b062374ee2d   ghcr.io/yourid/your-api:latest   "python -OO -m your_…"   9 minutes ago   Up 9 minutes (unhealthy)
...

compose 의 healthcheck 명령 등을 확인하자.

See also

  • traefik
  • lets encrypt
  • Osom-api#2 replicated master docker compose - 2 replicated docker compose 를 적용한 예제