Traefik Docker 문서
Traefik Docker 문서 (Traefik Docker Documentation)
본문
Traefik & Docker
퀵 스타트는 Docker를 사용해요 (The Quick Start Uses Docker)
아직 읽지 않았다면, Docker 프로바이더를 사용하는 퀵 스타트 가이드를 살펴보는 것도 좋아요.
설정 예시 (Configuration Example)
아래처럼 Docker 프로바이더를 활성화할 수 있어요:
파일 (YAML)
providers:
docker: {}
파일 (TOML)
[providers.docker]
CLI
--providers.docker=true
컨테이너에 라벨을 붙이세요 (Docker compose 파일에서):
services:
my-container:
# ...
labels:
- traefik.http.routers.my-container.rule=Host(`example.com`)
설정 옵션 (Configuration Options)
| 필드 (Field) | 설명 (Description) | 기본값 (Default) | 필수 (Required) |
| providers.providersThrottleDuration | 설정 리로드 후, 새 설정 갱신(refresh) 이벤트를 반영하기 전에 기다리는 최소 시간이에요. 이 시간 안에 여러 이벤트가 발생하면 가장 최근 것만 반영되고 나머지는 버려져요. 이 옵션은 프로바이더별로 설정할 수 없지만, 스로틀링 알고리즘은 각 프로바이더에 독립적으로 적용돼요. | 2s | 아니오 (No) |
| providers.docker.endpoint | Docker API 끝점(endpoint)을 지정해요. 자세한 내용은 여기를 참고하세요 | "unix:///var/run/docker.sock" | 아니오 (No) |
| providers.docker.username | Basic HTTP 인증의 사용자 이름을 정의해요. Docker 데몬 소켓이 Basic HTTP 인증을 요구하는 HTTP 프록시로 노출될 때 사용해야 해요. | "" | 아니오 (No) |
| providers.docker.password | Basic HTTP 인증의 비밀번호를 정의해요. Docker 데몬 소켓이 Basic HTTP 인증을 요구하는 HTTP 프록시로 노출될 때 사용해야 해요. | "" | 아니오 (No) |
| providers.docker.useBindPortIP | Traefik이 컨테이너의 내부 네트워크 IP/포트 대신 컨테이너 바인딩에 연결된 IP/포트를 사용하도록 지시해요. 자세한 내용은 여기를 참고하세요 | false | 아니오 (No) |
| providers.docker.exposedByDefault | 컨테이너를 기본적으로 Traefik을 통해 노출해요. false로 설정하면 traefik.enable=true 라벨이 없는 컨테이너는 결과 라우팅 설정에서 제외돼요. 추가 정보는 여기를 참고하세요 | true | 아니오 (No) |
| providers.docker.network | 모든 컨테이너와의 연결에 사용할 기본 docker 네트워크를 정의해요. 이 옵션은 traefik.docker.network 라벨로 컨테이너별로 덮어쓸 수 있어요. | "" | 아니오 (No) |
| providers.docker.defaultRule | 라벨로 규칙이 정의되지 않은 컨테이너에 적용할 라우팅 규칙을 정의해요. 자세한 내용은 여기를 참고하세요. | "Host({{ normalize .Name }})" | 아니오 (No) |
| providers.docker.httpClientTimeout | HTTP 연결의 클라이언트 타임아웃을 정의해요. 기간 문자열(예: 30s, 1m30s) 또는 초 단위 정수 값을 받아요. 값이 0이면 타임아웃이 설정되지 않아요. | 0 | 아니오 (No) |
| providers.docker.watch | Traefik이 Docker 이벤트를 감시할지 여부를 지시해요. | true | 아니오 (No) |
| providers.docker.constraints | Traefik이 컨테이너 라벨과 대조해 해당 컨테이너에 라우트를 만들지 결정하는 식(expression)을 정의해요. 자세한 내용은 여기를 참고하세요. | "" | 아니오 (No) |
| providers.docker.allowEmptyServices | 해당 컨테이너의 건강 상태와 관계없이 Docker 컨테이너용으로 정의된 서버 로드 밸런서를 만들도록 프로바이더에 지시해요. | false | 아니오 (No) |
| providers.docker.tls.ca | Docker와의 보안 연결에 사용하는 인증 기관의 경로로, 기본값은 시스템 번들이에요. | "" | 아니오 (No) |
| providers.docker.tls.cert | Docker와의 보안 연결에 사용하는 공개 인증서의 경로예요. 이 옵션을 사용할 때는 key 옵션을 설정해야 합니다. | "" | 예 (Yes) |
| providers.docker.tls.key | Docker와의 보안 연결에 사용하는 개인 키의 경로예요. 이 옵션을 사용할 때는 cert 옵션을 설정해야 합니다. | "" | 예 (Yes) |
| providers.docker.tls.insecureSkipVerify | TLS 연결을 맺을 때 인증서가 커버하는 호스트명과 관계없이 Docker 서버가 제시하는 어떤 인증서든 수락하도록 프로바이더에 지시해요. | false | 아니오 (No) |
endpoint
자세한 내용은 Docker API 접근(Docker API Access) 섹션을 참고하세요.
docker.sock 사용하기 (Using the docker.sock) docker-compose 파일이 docker sock을 Traefik 컨테이너와 공유해요
services:
traefik:
image: traefik:v3.1 # The official v3 Traefik docker image
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Traefik 설정 파일에 docker.sock을 지정해요.
파일 (YAML)
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
# ...
파일 (TOML)
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
# ...
CLI
--providers.docker.endpoint=unix:///var/run/docker.sock
# ...
SSH 사용하기 (Using SSH) Docker 18.09+에서는 SSH로 Traefik을 데몬에 연결할 수 있어요. Traefik 설정 파일에 SSH 호스트와 사용자를 지정해요. 서버가 인증을 위해 공개 키를 요구한다면, Traefik을 실행하는 사용자가 그 키에 접근할 수 있어야 한다는 점에 주의하세요.
파일 (YAML)
providers:
docker:
endpoint: "ssh://[email protected]:2022"
# ...
파일 (TOML)
[providers.docker]
endpoint = "ssh://[email protected]:2022"
# ...
CLI
--providers.docker.endpoint=ssh://[email protected]:2022
# ...
HTTP 사용하기 (Using HTTP) Docker Engine API를 사용해서 HTTP로 Traefik을 원격 데몬에 연결할 수 있어요.
파일 (YAML)
providers:
docker:
endpoint: "http://127.0.0.1:2375"
# ...
파일 (TOML)
[providers.docker]
endpoint = "http://127.0.0.1:2375"
# ...
CLI
--providers.docker.endpoint=http://127.0.0.1:2375
# ...
TCP 사용하기 (Using TCP) Docker Engine API를 사용해서 TCP로 Traefik을 원격 데몬에 연결할 수 있어요.
파일 (YAML)
providers:
docker:
endpoint: "tcp://127.0.0.1:2375"
# ...
파일 (TOML)
[providers.docker]
endpoint = "tcp://127.0.0.1:2375"
# ...
CLI
--providers.docker.endpoint=tcp://127.0.0.1:2375
# ...
파일 (YAML)
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
파일 (TOML)
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
CLI
--providers.docker.endpoint=unix:///var/run/docker.sock
useBindPortIP
Traefik은 일치하는 컨테이너의 IP/포트로 요청을 라우팅해요.
useBindPortIP=true로 설정하면 컨테이너의 내부 네트워크 IP/포트 대신 컨테이너 바인딩에 연결된 IP/포트를 사용하라고 Traefik에 지시하는 거예요.
traefik.http.services..loadbalancer.server.port 라벨(특정 포트로 요청을 라우팅하라고 Traefik에 지시하는 라벨)과 함께 사용하면,
Traefik은 traefik.http.services..loadbalancer.server.port 포트에서 바인딩을 찾으려 해요.
그런 바인딩을 찾지 못하면 컨테이너의 내부 네트워크 IP로 대체(fallback)하지만,
여전히 라벨에 설정된 traefik.http.services..loadbalancer.server.port를 사용해요.
다양한 상황에서 usebindportip의 예시들.
| 포트 라벨 (port label) | 컨테이너의 바인딩 (Container's binding) | 라우팅 대상 (Routes to) |
| - | - | IntIP:IntPort |
| - | ExtPort:IntPort | IntIP:IntPort |
| - | ExtIp:ExtPort:IntPort | ExtIp:ExtPort |
| LblPort | - | IntIp:LblPort |
| LblPort | ExtIp:ExtPort:LblPort | ExtIp:ExtPort |
| LblPort | ExtIp:ExtPort:OtherPort | IntIp:LblPort |
| LblPort | ExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2 | ExtIp2:LblPort |
위 표에서:
-
ExtIp는 "바인딩에서 찾은 외부 IP"를 뜻해요
-
IntIp는 "내부 네트워크 컨테이너의 IP"를 뜻해요,
-
ExtPort는 "바인딩에서 찾은 외부 포트"를 뜻해요
-
IntPort는 "내부 네트워크 컨테이너의 포트"를 뜻해요.
파일 (YAML)
providers:
docker:
useBindPortIP: true
# ...
파일 (TOML)
[providers.docker]
useBindPortIP = true
# ...
CLI
--providers.docker.useBindPortIP=true
# ...
defaultRule
defaultRule 옵션은 라벨로 규칙이 정의되지 않은 컨테이너에 적용할 라우팅 규칙을 정의해요.
유효한 Go 템플릿이어야 하고,
sprig 템플릿 함수를 사용할 수 있어요.
컨테이너 이름은 ContainerName 식별자로 접근할 수 있어요.
서비스 이름은 Name 식별자로 접근할 수 있어요.
템플릿은 Labels 식별자로 이 컨테이너에 정의된 모든 라벨에 접근할 수 있어요.
파일 (YAML)
providers:
docker:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
파일 (TOML)
[providers.docker]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
CLI
--providers.docker.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
# ...
기본 규칙과 Traefik 서비스 (Default rule and Traefik service) Traefik 컨테이너의 노출이 기본 규칙 메커니즘과 결합되면, 자기 자신을 대상으로 하는 라우터가 루프처럼 만들어질 수 있어요. 이 경우 무한 루프를 막기 위해, Traefik은 같은 라우터에서 온 요청이라면 거부하는 내부 미들웨어를 추가해요.
constraints
constraints 옵션은 Traefik이 컨테이너 라벨과 대조해 해당 컨테이너에 라우트를 만들지 결정하는 식으로 설정할 수 있어요. 어떤 컨테이너 라벨도 식과 일치하지 않으면 해당 컨테이너에 라우트가 만들어지지 않아요. 식이 비어 있으면 감지된 모든 컨테이너가 포함돼요.
식 구문은 아래 예시처럼 Label("key", "value"), LabelRegex("key", "value") 함수와 일반적인 불리언 논리를 기반으로 해요.
Constraints 키 제한 사항 (Constraints key limitations)
traefik.*는 설정용 예약 라벨 네임스페이스라서 커스텀 constraints의 키로 사용할 수 없다는 점에 주의하세요.
Constraints 식 예시 (Constraints Expression Examples)
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
추가 정보는 서비스 발견 범위 제한(Restrict the Scope of Service Discovery)을 참고하세요.
파일 (YAML)
providers:
docker:
constraints: "Label(`a.label.name`,`foo`)"
# ...
파일 (TOML)
[providers.docker]
constraints = "Label(`a.label.name`,`foo`)"
# ...
CLI
--providers.docker.constraints=Label(`a.label.name`,`foo`)
# ...
라우팅 설정 (Routing Configuration)
Docker를 프로바이더로 사용할 때, Traefik은 라우팅 설정을 얻기 위해 컨테이너 라벨을 사용해요.
라벨 목록은 라우팅의 전용 섹션을 참고하세요.
라벨을 사용한 라우팅 설정 (Routing Configuration with Labels)
기본적으로 Traefik은 독립형(standalone) Docker Engine에서 컨테이너 레벨 라벨을 감시해요.
Docker Compose를 사용할 때 라벨은
"services" 객체의 labels 지시문으로 지정돼요.
Docker만이 아닙니다 (Not Only Docker)
Nomad, Terraform, Ansible 등처럼 라벨이 있는 Docker 컨테이너를 정의할 수 있는 도구라면 모두 Traefik과 Docker 프로바이더와 함께 동작할 수 있다는 점을 알아두세요.
포트 감지 (Port Detection)
Traefik은 Docker API에서 컨테이너의 사설 IP와 포트를 가져와요.
사설 통신용 포트 감지는 다음과 같이 동작해요:
-
컨테이너가 단일 포트를 노출하면 Traefik이 그 포트를 사용해요.
-
컨테이너가 여러 포트를 노출하면 Traefik이 가장 낮은 포트를 사용해요. 예를 들어 80과 8080이 노출되면 Traefik은 80을 사용해요.
-
컨테이너가 포트를 노출하지 않거나 여러 포트 중 선택이 맞지 않으면, traefik.http.services..loadbalancer.server.port 라벨로 Traefik이 통신에 사용할 포트를 직접 지정해야 해요 (이 라벨에 대한 자세한 내용은 라우팅의 전용 섹션에서 읽을 수 있어요).
호스트 네트워킹 (Host networking)
호스트 네트워킹으로 설정된 컨테이너를 노출할 때, 호스트의 IP 주소는 다음과 같이 해석돼요:
-
host.docker.internal 검색을 시도해요
-
검색이 실패하면 host.containers.internal(Podman의 host.docker.internal 상당) 검색을 시도해요
-
그 검색도 실패하면 127.0.0.1로 대체(fallback)해요
Linux에서 Docker 20.10.0보다 오래된 버전의 경우, host.docker.internal이 정의되려면 --add-host 플래그로 Traefik 컨테이너에 extra_host로 제공해야 해요. 예를 들어 브리지 인터페이스(docker0 기본)의 IP 주소로 설정하려면: --add-host=host.docker.internal:172.17.0.1처럼요.
IPv4 & IPv6
IPv6을 사용하는 docker 스택을 사용할 때, Traefik은 IPv6보다 IPv4 컨테이너 IP를 먼저 사용해요. 따라서 IPv6 docker 스택에서는 IPv6 컨테이너 IP를 사용해요.
Docker API 접근 (Docker API Access)
Traefik은 동적 설정을 얻기 위해 docker 소켓에 접근해야 해요.
endpoint 지시문으로 사용할 Docker API 끝점을 지정할 수 있어요.
보안 참고 (Security Note)
제한 없이 Docker API에 접근하는 것은 보안 문제예요: Traefik이 공격받으면 공격자가 기본 호스트에 접근할 수도 있어요.
Docker 데몬 공격 표면(Docker Daemon Attack Surface) 문서에 설명된 대로:
인용 (Quote)
[...] 신뢰할 수 있는 사용자만 Docker 데몬을 제어하도록 허용해야 해요 [...]
해결책 (Solutions) 기본 Unix 소켓 파일 대신 TCP나 SSH로 Docker 소켓을 노출하세요. 이는 보안 평가에 따라 AAA(Authentication, Authorization, Accounting) 개념의 다양한 구현 수준을 허용해요:
-
"Docker 데몬 소켓 보호(Protect the Docker daemon socket)"에 설명된 대로 클라이언트 인증서로 인증해요.
-
Tecnativa Docker Socket Proxy로 요청을 허가(authorize)하고 필터링해 가능한 동작을 제한해요.
-
Docker Authorization Plugin 메커니즘으로 권한 부여해요.
-
소켓을 Docker 사설 네트워크 안에서만 노출해 네트워킹 수준에서 회계(accounting)해요 (Traefik만 접근 가능).
-
Traefik이 아닌 다른 컨테이너에 소켓을 노출해 컨테이너 수준에서 회계해요.
-
SELinux 같은 메커니즘으로 커널 호출을 강제해 Traefik 프로세스("소켓 노출자" 프로세스)에 대해 식별된 동작 집합만 허용해 커널 수준에서 회계해요.
-
SSH 공개 키 인증 (Docker > 18.09에서 SSH 지원)
-
Docker 데몬 소켓을 노출하는 HTTP 프록시를 통한 HTTP Basic 인증으로 인증해요.
더 많은 자료와 예시 (More Resources and Examples)
-
"/var/run/docker.sock 마운트에 대해 편집증적이신가요? (Paranoid about mounting /var/run/docker.sock?)"
-
Traefik and Docker: A Discussion with Docker Captain, Bret Fisher
-
KubeCon EU 2018 Keynote, Running with Scissors, from Liz Rice
-
Don't expose the Docker socket (not even to a container)
-
/var/run/docker.sock 파일 공유에 관한 Hacker News 스레드
-
To DinD or not to DinD
-
Docker 소켓 보안에 관한 Traefik 이슈 GH-4174
-
Socat로 Docker 활동 검사하기 (Inspecting Docker Activity with Socat)
-
Traefik을 워커 노드에서 실행하기 (Letting Traefik run on Worker Nodes)
-
Tecnativa의 Docker Socket Proxy
운영 환경에서 Traefik OSS를 사용하고 계신가요? (Using Traefik OSS in Production?)
직장에서 Traefik을 사용하고 있다면, Traefik OSS에 엔터프라이즈급 API 게이트웨이 기능이나 상업적 지원을 추가하는 것을 고려해 보세요.
-
API 게이트웨이 데모 영상 보기 (Watch our API Gateway Demo Video)
-
24/7/365 OSS 지원 요청 (Request 24/7/365 OSS Support)
Traefik OSS에 API 게이트웨이 기능을 추가하는 것은 빠르고 매끄러워요. 교체(rip and replace) 없이 모든 설정이 그대로 유지되며, 이 짧은 영상을 통해 실제 동작을 확인할 수 있어요.