본문 바로가기
WIKI 기술 지식 베이스

Docker Swarm에서 Traefik Proxy 설정하기

원문 보기 위키 갱신

출처: Setup Traefik Proxy in Docker Swarm

본문

Swarm

이 가이드는 docker stack deploy로 Traefik Proxy를 Swarm 서비스로 설치하고 구성하는 과정을 깊이 있게 안내해요. standalone-Docker 튜토리얼과 같은 구조를 따르며 다음을 다룹니다:

  • Swarm 프로바이더 활성화하기

  • web(HTTP :80)과 websecure(HTTPS :443) 엔트리포인트 노출하기

  • 모든 HTTP 트래픽을 HTTPS로 리다이렉트하기

  • Traefik 대시보드를 basic-auth로 보호하기

  • *.swarm.localhost용 자체 서명 인증서로 TLS 종료하기

  • whoami 데모 서비스 배포하기

  • access-logs와 Prometheus 메트릭 활성화하기

사전 요구 사항

  • Swarm 모드가 초기화된 Docker Engine (docker swarm init)

  • Docker Compose

  • openssl

  • htpasswd

자체 서명 인증서 만들기

Traefik이 로컬에서 HTTPS를 제공하려면 먼저 인증서가 필요해요. 프로덕션에서는 신뢰할 수 있는 CA의 인증서를 사용하겠지만, 멀티 노드 개발 스웜에서는 빠른 자체 서명 인증서로 충분해요:

mkdir -p certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout certs/local.key -out certs/local.crt \
  -subj "/CN=*.swarm.localhost"

Traefik 대시보드 자격 증명 만들기

Traefik의 미들웨어가 검증할 해시된 사용자 이름/비밀번호 쌍을 생성하세요:

htpasswd -nb admin "P@ssw0rd" | sed -e 's/\$/\$\$/g'

전체 출력(예: admin:$$apr1$$…)을 복사하세요. 미들웨어 라벨에 붙여넣을 거예요.

docker-compose-swarm.yaml 만들기

Note

Swarm은 docker stack deploy를 사용해요. Compose 파일 이름은 아무거나 가능하지만, 우리는 docker-compose-swarm.yaml을 쓸 거예요.

먼저 dynamic이라는 폴더를 만들고 동적 TLS 구성을 위해 tls.yaml을 추가하세요:

# dynamic/tls.yaml
tls:
  certificates:
    - certFile: /certs/local.crt
      keyFile:  /certs/local.key

같은 디렉터리에 docker-compose-swarm.yaml을 만드세요:

services:
  traefik:
    image: traefik:v3.7

    networks:
    # Connect to the 'traefik_proxy' overlay network for inter-container communication across nodes
      - traefik_proxy

    ports:
        # Expose Traefik's entry points to the Swarm
        # Swarm requires the long syntax for ports.
      - target: 80 # Container port (Traefik web entry point)
        published: 80 # Host port exposed on the nodes
        protocol: tcp
        # 'host' mode binds directly to the node's IP where the task runs.
        # 'ingress' mode uses Swarm's Routing Mesh (load balances across nodes).
        # Choose based on your load balancing strategy. 'host' is often simpler if using an external LB.
        mode: host
      - target: 443 # Container port ( Traefik websecure entry point)
        published: 443 # Host port
        protocol: tcp
        mode: host

    volumes:
      # Mount the Docker socket for the Swarm provider
      # This MUST be run from a manager node to access the Swarm API via the socket.
      - /var/run/docker.sock:/var/run/docker.sock:ro   # Swarm API socket
      - ./certs:/certs:ro
      - ./dynamic:/dynamic:ro

    # Traefik Static configuration via command-line arguments
    command:
      # HTTP EntryPoint
      - "--entrypoints.web.address=:80"

      # Configure HTTP to HTTPS Redirection
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"

      # HTTPS EntryPoint
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"

      # Attach dynamic TLS file
      - "--providers.file.filename=/dynamic/tls.yaml"

      # Providers

      # Enable the Docker Swarm provider (instead of Docker provider)
      - "--providers.swarm.endpoint=unix:///var/run/docker.sock"

      # Watch for Swarm service changes (requires socket access)
      - "--providers.swarm.watch=true"

      # Recommended: Don't expose services by default; require explicit labels
      - "--providers.swarm.exposedbydefault=false"

      # Specify the default network for Traefik to connect to services
      - "--providers.swarm.network=traefik_traefik_proxy"

      # API & Dashboard
      - "--api.dashboard=true" # Enable the dashboard
      - "--api.insecure=false" # Explicitly disable insecure API mod

      # Observability
      - "--log.level=INFO" # Set the Log Level e.g INFO, DEBUG
      - "--accesslog=true" # Enable Access Logs
      - "--metrics.prometheus=true"  # Enable Prometheus

    deploy:
      mode: replicated
      replicas: 1
      placement:

      # Placement constraints restrict where Traefik tasks can run.
      # Running on manager nodes is common for accessing the Swarm API via the socket.
        constraints:
          - node.role == manager

      # Traefik Dynamic configuration via labels
      # In Swarm, labels on the service definition configure Traefik routing for that service.
      labels:
        - "traefik.enable=true"

        # Dashboard router
        - "traefik.http.routers.dashboard.rule=Host(`dashboard.swarm.localhost`)"
        - "traefik.http.routers.dashboard.entrypoints=websecure"
        - "traefik.http.routers.dashboard.service=api@internal"
        - "traefik.http.routers.dashboard.tls=true"

        # Basic‑auth middleware
        - "traefik.http.middlewares.dashboard-auth.basicauth.users=<PASTE_HASH_HERE>"
        - "traefik.http.routers.dashboard.middlewares=dashboard-auth@swarm"

        # Service hint
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"

  # Deploy the Whoami application
  whoami:
    image: traefik/whoami
    networks:
      - traefik_proxy
    deploy:
      labels:
        # Enable Service discovery for Traefik
        - "traefik.enable=true"
        # Define the WHoami router rule
        - "traefik.http.routers.whoami.rule=Host(`whoami.swarm.localhost`)"
        # Expose Whoami on the HTTPS entrypoint
        - "traefik.http.routers.whoami.entrypoints=websecure"
        # Enable TLS
        - "traefik.http.routers.whoami.tls=true"
        # Expose the whoami port number to Traefik
        - traefik.http.services.whoami.loadbalancer.server.port=80

# Define the overlay network for Swarm
networks:
  traefik_proxy:
    driver: overlay
    attachable: true

Info

  • 이전 단계의 이스케이프된 해시로 를 교체하세요.

  • 비밀번호 해시가 서비스 라벨에 직접 저장돼요. 로컬 개발에는 괜찮지만, Docker API에 접근할 수 있는 사람은 누구나 docker service inspect로 볼 수 있어요. 프로덕션에서는 시크릿을 저장하는 더 안전한 방법을 사용하세요.

스택 실행하기

오버레이 네트워크를 한 번 생성하고(아직 없다면) 배포하세요:

docker network create --driver overlay --attachable traefik_proxy || true
docker stack deploy -c docker-compose-swarm.yaml traefik

Swarm은 매니저 노드에 서비스를 스케줄링하고 포트 80/443을 바인딩해요.

대시보드 접근하기

브라우저에서 https://dashboard.swarm.localhost/를 여세요. 대시보드가 구성한 basic-auth 자격 증명을 요구할 거예요.

whoami 애플리케이션 테스트하기

curl로 애플리케이션을 테스트할 수 있어요:

curl -k https://whoami.swarm.localhost/
Hostname: whoami-76c9859cfc-k7jzs
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.59
IP: fe80::50d7:a2ff:fed5:2530
RemoteAddr: 10.42.0.60:54148
GET / HTTP/1.1
Host: whoami.swarm.localhost
User-Agent: curl/8.7.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami.swarm.localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: traefik-644b7c67d9-f2tn9
X-Real-Ip: 10.42.0.1

HTTP 엔트리포인트에 같은 요청을 하면 다음이 반환돼요:

curl -k http://whoami.swarm.localhost

Moved Permanently

HTTP 엔드포인트를 요청하면 HTTPS로 리다이렉트되어 설정이 제대로 동작함을 확인해 줘요.

브라우저를 열고 https://whoami.swarm.localhost로 이동해 서비스의 JSON 덤프를 볼 수도 있어요:

기타 주요 구성 영역

이 초기 설정 외에도 Traefik은 광범위한 구성 가능성을 제공해요. 여기서는 Docker Compose command 인자나 labels를 사용한 간단한 소개와 최소 예시를 다룰게요. 포괄적인 내용은 링크된 메인 문서를 참고하세요.

TLS 인증서 관리 (Let's Encrypt)

websecure 엔트리포인트가 유효한 HTTPS 인증서를 자동으로 제공하게 하려면 Let's Encrypt(ACME)를 활성화하세요.

command:
  # ...
  - "[email protected]"
  - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
  - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
  - "--entrypoints.websecure.http.tls.certresolver=le"

이것은 le라는 리졸버를 정의하고, 필요한 이메일과 저장 경로(마운트된 /letsencrypt 볼륨 안)를 설정하며, HTTP 챌린지를 활성화해요. 챌린지와 DNS 프로바이더 구성에 대한 자세한 내용은 HTTPS/TLS 문서와 Let's Encrypt 문서를 참고하세요.

Note

  • 모든 노드가 인증서를 읽을 수 있도록 /letsencrypt 경로가 공유 볼륨이나 NFS에 있어야 해요.

  • docker-compose-swarm.yaml 파일의 traefik 서비스에 /letsencrypt 볼륨을 마운트해야 해요.

메트릭 (Prometheus)

Traefik의 내부 메트릭을 Prometheus로 모니터링하기 위해 노출할 수 있어요. 우리는 이미 설정에서 prometheus를 활성화했지만 더 구성할 수 있어요. command 추가 예시:

command:
  # If using a dedicated metrics entry point, define it:
  - "--entrypoints.metrics.address=:8082"

  - "--metrics.prometheus=true"

  # Optionally change the entry point metrics are exposed on (defaults to 'traefik')
  - "--metrics.prometheus.entrypoint=metrics"

  # Add labels to metrics for routers/services (can increase cardinality)
  - "--metrics.prometheus.addrouterslabels=true"

이것은 /metrics 엔드포인트를 활성화해요(보통 내부 API 포트(보안되지 않으면 기본적으로 8080) 또는 전용 엔트리포인트를 통해 접근). 옵션에 대해서는 Metrics 문서를 참고하세요.

트레이싱 (OTel)

Traefik을 통해 요청을 따라가도록 분산 트레이싱을 활성화할 수 있어요. command 추가 예시:

command:
  # ...
  - "--tracing.otel=true"
  - "--tracing.otel.grpcendpoint=otel-collector:4317"

Note

이 옵션은 Traefik이 접근할 수 있는 실행 중인 OTEL 컬렉터가 필요해요. Tracing 문서를 참고하세요.

접근 로그 (Access Logs)

들어오는 요청을 디버깅과 분석을 위해 기록하도록 Traefik을 구성할 수 있어요. command 추가 예시:

command:
  # ... other command arguments ...
  - "--accesslog=true" # Enable access logs to stdout

  # Optionally change format or output file (requires volume)
  - "--accesslog.format=json"
  - "--accesslog.filepath=/path/to/access.log"

  # Optionally filter logs
  - "--accesslog.filters.statuscodes=400-599"

결론

이제 HTTPS, 보안된 대시보드, 자동 HTTP → HTTPS 리다이렉트, 기본적인 관측 가능성을 갖춘 Docker Swarm에서 실행되는 Traefik이 생겼어요. Swarm이 성장함에 따라 이 스택을 Let's Encrypt, 추가 미들웨어, 또는 여러 Traefik 복제본으로 확장하세요.

프로덕션에서 Traefik OSS를 사용 중인가요?

업무에서 Traefik을 사용한다면 엔터프라이즈급 API 게이트웨이 기능이나 Traefik OSS용 상용 지원을 고려해 보세요.

  • API Gateway 데모 영상 보기

  • 24/7/365 OSS 지원 요청하기

Traefik OSS에 API 게이트웨이 기능을 추가하는 건 빠르고 매끄러워요. 대체(rip and replace)가 필요 없고 모든 구성이 그대로 유지돼요. 이 짧은 영상으로 직접 확인해 보세요.

더 알아보기