Traefik 공식 문서를 보면 foo bar 이렇게 해놔서 헷갈리는 부분이 많죠. 띄어쓰기에 엄격한 Yaml, 이스케이핑이 필요한 문법, 등등 같이 결합해서 아주 그냥 환상의 하모니를 자랑합니다.
간단하게 정리해 보겠습니다. Traefik은 크게 세 가지로 구성됩니다.
Service(서비스)
Middleware(미들웨어)
Router(라우터)
큰 틀에서 Traefik의 문법을 따라간다.
이름을 붙이고 그걸 연결한다
Traefik 설정에서 핵심은 1. 서비스
와 3. 라우터
입니다.
서비스와 라우터만 제대로 설정하면 크게 문제없고 미들웨어는 라우터를 보조한다고 생각하시면 편합니다. 사용자가 이름을 부여 한대로 된다는 것에서 쿠버네티스와 비슷한 성격을 갖고 있습니다. Traefik의 설정은 큰 틀은 Traefik의 문법을 따라가지만, 그 안에서 이름붙이는 것은 사용자의 맘입니다.
# Attach add-foo-prefix@file middleware (declared in file)
- ' traefik.http.routers.my-container.middlewares=add-foo-prefix@file '
이렇게 foo, bar, my-container 이렇게만 달랑 해놓고 이름붙이는 것에 대한 설명을 안해주니 문서를 보고 있으면 정신이 아득해 집니다.
- " --ping.entrypoint=ping "
- " --entryPoints.ping.address=:8082 "
- " --entryPoints.web.address=:80 "
- " --entryPoints.websecure.address=:443 "
- " --entryPoints.web.http.redirections.entryPoint.to=websecure "
- " --entrypoints.web.http.redirections.entryPoint.scheme=https "
- " --entrypoints.web.http.redirections.entrypoint.permanent=true "
- " --providers.docker=true "
- " --providers.docker.watch=true "
- " --providers.docker.network=traefik-network "
- " --providers.docker.endpoint=unix:///var/run/docker.sock "
- " --providers.docker.exposedByDefault=false "
- " --certificatesresolvers.letsencrypt.acme.tlschallenge=true "
- " --certificatesresolvers.letsencrypt.acme.keyType=EC256 "
- " --certificatesresolvers.letsencrypt.acme.email=webmaster@example.com "
- " --certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json "
# Let's Encrypt ACME DNS Challenge (CLoudflare)
#- "--certificatesResolvers.letsencrypt.acme.dnsChallenge=true"
#- "--certificatesResolvers.letsencrypt.acme.dnsChallenge.provider=cloudflare"
#- "--certificatesResolvers.letsencrypt.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
#- "--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0"
- " --metrics.prometheus=true "
- " --metrics.prometheus.buckets=0.1,0.3,1.2,5.0 "
- " --metrics.prometheus.addServicesLabels=true "
- " --metrics.prometheus.addrouterslabels=true "
- " --metrics.prometheus.addEntryPointsLabels=true "
- " --global.checkNewVersion=true "
- " --global.sendAnonymousUsage=false "
- " --experimental.http3=true "
- " --entrypoints.websecure.http3 "
- " --entrypoints.websecure.http3.advertisedport=443 "
test : [ " CMD " , " wget " , " http://localhost:8082/ping " , " --spider " ]
- " traefik.http.services.dashboard.loadbalancer.server.port=8080 "
- " traefik.http.services.dashboard.loadbalancer.passhostheader=true "
- " traefik.http.routers.dashboard.rule=Host(`web.example.com`) "
- " traefik.http.routers.dashboard.entrypoints=websecure "
- " traefik.http.routers.dashboard.service=api@internal "
- " traefik.http.routers.dashboard.tls=true "
- " traefik.http.routers.dashboard.tls.certresolver=letsencrypt "
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik-certificates:/etc/traefik/acme
image : navystack/rhymix:latest
- " traefik.docker.network=traefik-network "
- " traefik.http.services.rhymix-srv.loadbalancer.server.port=80 "
- " traefik.http.services.rhymix-srv.loadbalancer.passhostheader=true "
- " traefik.http.middlewares.www-redir.redirectregex.regex=^https://www.(.*) "
- " traefik.http.middlewares.www-redir.redirectregex.replacement=https://$${1} "
- " traefik.http.middlewares.www-redir.redirectregex.permanent=true "
- " traefik.http.middlewares.compresstraefik.compress=true "
- " traefik.http.routers.rhymix-rt.rule=Host(`example.com`) || Host(`www.example.com`) "
- " traefik.http.routers.rhymix-rt.entrypoints=websecure "
- " traefik.http.routers.rhymix-rt.service=rhymix-srv "
- " traefik.http.routers.rhymix-rt.middlewares=www-redir, compresstraefik "
- " traefik.http.routers.rhymix-rt.tls=true "
- " traefik.http.routers.rhymix-rt.tls.certresolver=letsencrypt "
- " traefik.http.routers.rhymix-rt.tls.domains[0].main=example.com "
- " traefik.http.routers.rhymix-rt.tls.domains[0].sans=*.example.com "
- rhymix-data:/var/www/html
위의 코드 스니펫은 docker-compose의 일부입니다. 처음 볼 때는 한숨만 나오죠 길기도 길 뿐더러 낯선 개념들 뿐입니다.
천천히 뜯어보겠습니다. 아래의 모든 줄 번호는 docker-compose.yml
예제에 있는 번호입니다.
처음 말씀 드린것 처럼 기억할 것은 딱 두가지 입니다.
핵심은 서비스와 라우터다
큰 틀은 Traefik의 문법을 따르지만 이름 붙이는 것은 내 마음이다.
- ' --ping.entrypoint=ping '
전반적으로 Traefik 문법입니다. 규칙 2번(큰 틀은 Traefik의 문법을 따르지만 이름 붙이는 것은 내 마음이다.)입니다. ⓐ 역시 규칙 2번입니다. --ping.entrypoint=
여기까지가 Traefik 문법이고 ping
여기는 내가 지은 이름입니다.
- ' --entryPoints.ping.address=:8082 '
- ' --entryPoints.web.address=:80 '
- ' --entryPoints.websecure.address=:443 '
각각의 앞부분 --entryPoints.
까지는 Traefik 문법이고 .
을 기준으로 각각 ping
, web
, websecure
은 내가 지은 이름입니다.
그리고 그다음부터 각각의 줄에서 이어지는 address부터는 역시 Traefik 문법이고 :
을 기준으로 나오는 숫자들은 역시 내가 부여한 번호들입니다. (물론 HTTP, HTTPS를 위한 포트이기는 하지만요)
앞에서
- ' --ping.entrypoint=ping '
라고 ping
이라고 이름 붙였죠? (“=
” 다음에 오는 ping
) 앞에서 선언한 엔트리포인트 ping
에 대해서 나는
- ' --entryPoints.ping.address=:8082 '
8082번을 “사용하겠다.” 입니다.
- ' --entryPoints.web.http.redirections.entryPoint.to=websecure '
- ' --entrypoints.web.http.redirections.entryPoint.scheme=https '
- ' --entrypoints.web.http.redirections.entrypoint.permanent=true '
각각의 --entryPoints
.는 트래픽 문법입니다. 그다음에 오는 web
은 내가 위에서지은 이름입니다. 나머지는 Traefik 문법 이고, 그 중에서 redirections에 대해서 정의하고 있습니다.
위에 세 줄을 뜯으면 내가 정의한 web
에대해서 내가 정의한 websecure
로 리다이렉션 하겠다. 이 때의 스키마는 https
이고, permanent
즉 301 리다이렉션 하겠다 입니다.
간단히 이야기해서 http 80으로 들어오면 나는 https 443으로 돌리겠다 입니다.
- ' --providers.docker=true '
- ' --providers.docker.watch=true '
- ' --providers.docker.network=traefik-network '
- ' --providers.docker.endpoint=unix:///var/run/docker.sock '
- ' --providers.docker.exposedByDefault=false '
여기서는 traefik 문법입니다.
ⓐ의 첫 번째 줄은 docker
를 사용하겠다. 두 번째 줄은 label
이 변경되면 즉시 적용하겠다.
ⓑ는 traefik이 감시할 네트워크는 내가 이름붙인 traefik-network
이다.
ⓒ의 첫번째 줄: 사용할 도커의 엔드포인트는 unix:///var/run/docker.sock
이다. 두 번째 줄: 내가 true
한 것만 노출해라
- ' --certificatesresolvers.letsencrypt.acme.tlschallenge=true '
- ' --certificatesresolvers.letsencrypt.acme.keyType=EC256 '
- ' --certificatesresolvers.letsencrypt.acme.email=webmaster@example.com '
- ' --certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json '
각각의 줄에서 --certificatesresolvers.
은 Traefik 문법입니다. 그리고 그다음에 오는 letsencrypt
는 letsencrypt를 사용할 것이니 그냥 내가 지은
이름입니다.
풀어서 설명하면.
certificatesresolvers
로 나는 letsencrypt
라고 이름붙인 것을 사용할거고 acme
프로토콜이고 tlschallenge
를 사용할 것이다.
인증서는 EC256
로 발급해라
사용할 이메일은 webmaster@example.com
이다
인증서를 저장할 장소는 Traefik에 바인드된 /etc/traefik/acme/acme.json
이다.
마찬가지로 현재는 주석처리 되어있지만 아래는 DNS챌린지를 사용하는 경우입니다.
# Let's Encrypt ACME DNS Challenge (CLoudflare)
#- "--certificatesResolvers.letsencrypt.acme.dnsChallenge=true"
#- "--certificatesResolvers.letsencrypt.acme.dnsChallenge.provider=cloudflare"
#- "--certificatesResolvers.letsencrypt.acme.dnsChallenge.resolvers=1.1.1.1:53,8.8.8.8:53"
#- "--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=0"
이거는 한번 해석해 보세요 :)
- ' --metrics.prometheus=true '
- ' --metrics.prometheus.buckets=0.1,0.3,1.2,5.0 '
- ' --metrics.prometheus.addServicesLabels=true '
- ' --metrics.prometheus.addrouterslabels=true '
- ' --metrics.prometheus.addEntryPointsLabels=true '
- ' --global.checkNewVersion=true '
- ' --global.sendAnonymousUsage=false '
여기는 그냥 Traefik 문법입니다. 자세한 사항은 공식문서 보시면 됩니다.
- ' --experimental.http3=true '
- ' --entrypoints.websecure.http3 '
- ' --entrypoints.websecure.http3. advertisedport=443 '
여기는 현재 HTTP3를 사용하려면 활성화 해야하는 설정입니다.
현재는 experimental 이고 --entrypoints.websecure.http3
여기에서 websecure
는 https라서 websecure가 아니고, 우리가 websecure
라고 이름지었기 때문에 websecure
인겁니다.
자 쭉 넘어가서
- ' traefik.http.services.dashboard.loadbalancer.server.port=8080 '
- ' traefik.http.services.dashboard.loadbalancer.passhostheader=true '
- ' traefik.http.routers.dashboard.rule=Host(`web.example.com`) '
- ' traefik.http.routers.dashboard.entrypoints=websecure '
- ' traefik.http.routers.dashboard.service=api@internal '
- ' traefik.http.routers.dashboard.tls=true '
- ' traefik.http.routers.dashboard.tls.certresolver=letsencrypt '
자 여기 보시면 이제
핵심은 서비스와 라우터다
큰 틀은 Traefik의 문법을 따르지만 이름 붙이는 것은 내 마음이다. 요기에서 1번이 나옵니다.
- ' traefik.http.services.dashboard.loadbalancer.server.port= 8080 '
- ' traefik.http.services.dashboard.loadbalancer. passhostheader =true '
아까 26번 줄에서 선언했기 때문에 활성화하는 옵션입니다. - ' --providers.docker.exposedByDefault=false '
라고 선언했기 때문에 활성화하는 옵션입니다.
여기에서 - "traefik.http.services.
는 서비스를 정의하겠다. 이름은 dashboard
이고 로드밸런스(리버스 프록싱)할 포트는 8080
이다 라고 선언하는 겁니다.
passhostheader헤더
를 넘기겠다.
여기까지가 서비스 정의를 한것입니다. 이제 핵심 중 서비스를 정의했으며 라우터를 정의하겠습니다.
- ' traefik.http.routers.dashboard.rule= Host(`web.example.com`) '
- ' traefik.http.routers.dashboard.entrypoints= websecure '
- ' traefik.http.routers.dashboard.service=api@internal '
- ' traefik.http.routers.dashboard. tls=true '
- ' traefik.http.routers.dashboard.tls.certresolver= letsencrypt '
traefik.http.routers.
라우터를 정의하겠다 이름은 dashboard
라고 지을거고 도메인(Host)는 web.example.com
이다.
내가 이름 붙인 dashboard
가 들어올 곳은 내가 이름붙인 websecure
이다.
중간에 뺀건 traefik문법입니다. :)
tls(ssl)사용할거고
인증서는 내가 이름 붙인 letsencrypt
로 제공해라 입니다.
자 거의 다왔습니다.
- ' traefik.docker.network=traefik-network '
traefik아 감시해라, 감시할 네트워크는 내가 이름 붙인 traefik-network
이다. - ' traefik.http.services.rhymix-srv.loadbalancer.server.port=80 '
- ' traefik.http.services.rhymix-srv.loadbalancer.passhostheader=true '
서비스의 이름은 rhymix-srv
이고 리버스프록싱(로드밸런싱)할 포트는 80 포트
이다.
헤더 넘긴다.
- ' traefik.http.middlewares.www-redir.redirectregex.regex=^https://www.(.*) '
- ' traefik.http.middlewares.www-redir.redirectregex. replacement =https://$${1} '
- ' traefik.http.middlewares.www-redir.redirectregex.permanent=true '
www-redir
라는 이름의 미들웨어를 정의하는데 그게 무엇이냐하면 redirectregex 정규식으로 리다이렉션 하겠다. 정규식은 ^https://www.(.*)
로 시작하면이다.redirectregex 할 것인데 어떻게 할 것인가 하면 replacement
(교체) 하겠다. (.*)
인 부분을 잘라서 ${1}
여기에 넣겠다 https://$${1}
에 넣을 건데 왜 $가 2개냐 하면 제가 달러를 좋아해서가 아니고 이스케이핑 하는겁니다.$${1}
이렇게 적어줘야 안으로 넘어갈 때는 ${1}
로 넘어갑니다.301(permanent)로 하겠다 - ' traefik.http.middlewares.compresstraefik.compress=true '
117번 줄 미들웨어를 하나 더 정의할 것인데 이름은 compresstraefik
이다 - ' traefik.http.routers.rhymix-rt.rule=Host(`example.com`) || Host(`www.example.com`) '
- ' traefik.http.routers.rhymix-rt.entrypoints=websecure '
- ' traefik.http.routers.rhymix-rt.service=rhymix-srv '
- ' traefik.http.routers.rhymix-rt.middlewares=www-redir, compresstraefik '
라우터의 이름은 rhymix-rt
이고 도메인은 example.com
혹은 www.example.com
이다.
이름이 rhymix-rt
인 라우터가 들어올 곳은 websecure
이고
라우팅할 서비스의 이름은 rhymix-srv
이다
이름이 rhymix-rt
에 적용할 미들웨어는 내가 앞에서 정의한 www-redir
, compresstraefik
이다.
- ' traefik.http.routers.rhymix-rt.tls=true '
- ' traefik.http.routers.rhymix-rt.tls.certresolver=letsencrypt '
- ' traefik.http.routers.rhymix-rt.tls.domains[0].main=example.com '
- ' traefik.http.routers.rhymix-rt.tls.domains[0].sans=*.example.com '
tls(ssl)
적용할거고
내가 정의한 letsencrypt
로 제공해라
혹시 인증서 없으면 메인은 example.com
로 발급하고 SANS로 *.example.com
로 발급해라.
와일드카드 발급은 DNS 챌린지
로 하셔야 발급됩니다.
이게 전부입니다.
가끔 보면 이름짓는다는 것에 착안해서
- ' traefik.docker.network=traefik-network '
- ' traefik.http.services.rhymix.loadbalancer.server.port=80 '
- ' traefik.http.services.rhymix.loadbalancer.passhostheader=true '
- ' traefik.http.middlewares.www-redir.redirectregex.regex=^https://www.(.*) '
- ' traefik.http.middlewares.www-redir.redirectregex.replacement=https://$${1} '
- ' traefik.http.middlewares.www-redir.redirectregex.permanent=true '
- ' traefik.http.middlewares.compresstraefik.compress=true '
- ' traefik.http.routers.rhymix.rule=Host(`example.com`) || Host(`www.example.com`) '
- ' traefik.http.routers.rhymix.entrypoints=websecure '
- ' traefik.http.routers.rhymix.service=rhymix '
- ' traefik.http.routers.rhymix.middlewares=www-redir, compresstraefik '
- ' traefik.http.routers.rhymix.tls=true '
- ' traefik.http.routers.rhymix.tls.certresolver=letsencrypt '
- ' traefik.http.routers.rhymix.tls.domains[0].main=example.com '
- ' traefik.http.routers.rhymix.tls.domains[0].sans=*.example.com '
서비스의 이름이 rhymix
이고 라우터의 이름도 rhymix
인 것은 아무런 인과 관계가 없습니다. 이렇게 기술하면 이해하기 어려울 수 있지만, 전역으로 정의하는 방법도 있습니다. 또한 다이나믹 라우팅이나 명령어를 줄여서 기록할 수도 있습니다. 나중에 기회가 되면 이에 대해 더 자세히 설명하겠습니다.
docker-compose.yml
로 직접 해보면서 해보실 분은 github 에 코드를 올려놓았습니다. 확인해 보시면서 하면 금방 이해하실 것 같습니다.
수고 많으셨습니다. 감사합니다.
Askfront.com (에스크프론트) 초보자도 편하게 질문할 수 있는 자유로운 포럼을 준비했어요! 💬
에스크프론트
에서는 NavyStack 가이드뿐만 아니라, 궁금한 모든 질문을 환영합니다. 😊
검색해도 원하는 답을 찾지 못해 답답했던 경험 있으시죠?
🔍 그럴 땐 부담 없이 질문해 주세요!
함께 이야기하며 답을 찾아갈 수 있을 거예요. 🤝
제가 직접 답변드릴 수 있다면 언제든 도와드릴게요. 감사합니다! 🙏