Skip to main content

Traefik: Docker와 Let's Encrypt로 HTTPS 자동화 완전 정복

·1163 words·6 mins
미뇽
Author
미뇽
안녕하세요! 기술로 세상을 이롭게 만들고 싶은 개발자 미뇽입니다.
Table of Contents

서버를 직접 운영하다 보면 애플리케이션 개발 외에도 신경 쓸 일이 참 많습니다. 특히 서비스가 추가될 때마다 Nginx 같은 리버스 프록시 설정 파일을 수동으로 고치고, 잊을 만하면 다가오는 SSL 인증서를 갱신하는 작업은 꽤 번거로운 일입니다. 이런 번거로움을 멋지게 해결해 줄 현대적인 도구가 있습니다. 바로 클라우드 네이티브 엣지 라우터, Traefik(트래픽) 입니다.

이 글에서는 Docker 환경에서 Traefik을 설치하고, Let’s Encrypt를 연동하여 수동 작업 없이도 HTTPS를 완전 자동화하는 과정을 처음부터 끝까지 안내해 드리겠습니다. 더 이상 설정 파일과 씨름하지 않고, 오직 개발에만 집중할 수 있는 환경을 함께 만들어 보겠습니다.

Traefik, 무엇이 다른가요?
#

Traefik은 마이크로서비스 환경을 위해 태어난 리버스 프록시 및 로드 밸런서입니다. 기존 Nginx나 HAProxy와 가장 큰 차이점은 설정 파일을 직접 수정하고 재시작할 필요가 없다는 점입니다.

  • 자동 서비스 탐색 (Automatic Service Discovery): Docker나 Kubernetes 같은 환경에서 컨테이너가 새로 생기거나 사라지는 것을 Traefik이 스스로 감지하여 라우팅 규칙을 실시간으로 업데이트합니다.

  • 동적 설정 (Dynamic Configuration): 각 서비스(컨테이너)에 붙어있는 **레이블(Label)**만으로 라우팅 규칙, 사용할 도메인, 미들웨어 적용까지 모든 것을 정의할 수 있습니다.

  • TLS 인증서 완전 자동화: Let’s Encrypt와 완벽하게 연동되어, 필요한 도메인의 HTTPS 인증서를 자동으로 발급받고, 만료일이 다가오면 스스로 갱신까지 해줍니다.

구분TraefikNginx / HAProxy (전통적 방식)
설정 방식동적 (Dynamic): API, 컨테이너 레이블 기반정적 (Static): 설정 파일 (.conf) 기반
변경 적용자동, 실시간 (재시작 불필요)수동 수정 후 재시작/리로드 필요
주요 환경마이크로서비스, 컨테이너 환경에 최적화범용적이나, 정적 인프라 환경에 더 적합
TLS 관리완전 자동화 (Let’s Encrypt 연동)수동 설정 및 스크립트를 통한 갱신 관리

준비사항 확인하기
#

  • 공인 도메인: localhost가 아닌, 실제 소유하고 있는 도메인(예: mydomain.com)이 필요합니다.

  • DNS 설정: 위 도메인의 서브도메인(예: whoami.mydomain.com)이 Traefik을 실행하는 서버의 공인 IP 주소를 가리키도록 DNS 레코드(A 또는 CNAME)를 설정해야 합니다.

  • 방화벽: 서버의 80번(HTTP) 포트443번(HTTPS) 포트가 외부에서 접근 가능하도록 방화벽이 열려 있어야 합니다.

Ubuntu에 Docker 설치하기
·550 words·3 mins
DuckDNS로 나만의 무료 도메인 만들기
·464 words·3 mins

Traefik 설치하기
#

먼저 Docker 환경에서 Traefik을 설치하고, 간단한 웹 서비스를 HTTP로 연결하는 기본 과정을 진행하겠습니다.

디렉토리 및 파일 생성
#

Traefik 관련 파일들을 관리할 작업 디렉토리와 설정 파일들을 미리 생성합니다.

# 작업 디렉토리 생성 및 이동
mkdir traefik
cd traefik

# Traefik의 기본 설정을 담을 파일 생성
touch traefik.yml

# Docker Compose 실행을 위한 파일 생성
touch docker-compose.yml

Traefik 정적 설정 작성 (traefik.yml)
#

traefik.yml 파일은 Traefik이 시작될 때 단 한 번만 읽는 정적 설정 파일입니다. 여기에 Traefik의 기본 동작 방식을 정의합니다.

# traefik.yml

# API 및 대시보드 활성화
# 개발 환경에서는 insecure: true로 간단히 열 수 있습니다.
api:
  insecure: true
  dashboard: true

# Traefik이 외부 요청을 받아들일 통로(엔트리포인트)를 정의합니다.
entryPoints:
  web:
    address: ":80"      # HTTP 요청을 위한 80번 포트
  websecure:
    address: ":443"     # HTTPS 요청을 위한 443번 포트

# 어떤 환경의 설정을 동적으로 읽어올지 정의합니다.
providers:
  docker:
    exposedByDefault: false # ※보안상 매우 중요한 설정입니다.
    network: traefik-proxy    # Traefik이 연결될 Docker 네트워크를 지정합니다.

💡 exposedByDefault: false

이 설정을 false로 두면, traefik.enable=true 라는 레이블이 명시적으로 붙은 컨테이너만 Traefik이 관리하게 됩니다. 실수로 원치 않는 서비스가 외부에 노출되는 것을 막아주는 중요한 보안 설정입니다.

Docker Compose 파일 작성 (docker-compose.yml)
#

이제 Traefik 컨테이너와, 라우팅을 테스트할 whoami라는 간단한 웹 서비스 컨테이너를 정의합니다.

# docker-compose.yml

version: '3.8'

services:
  # 1. Traefik 서비스 정의
  traefik:
    image: "traefik:v3.0"
    container_name: "traefik"
    command:
      - "--configFile=/etc/traefik/traefik.yml" # 시작 시 읽을 정적 설정 파일 지정
    ports:
      - "80:80"        # HTTP
      - "443:443"      # HTTPS
      - "8080:8080"    # Traefik 대시보드 접속 포트
    volumes:
      # Docker 소켓을 읽기 전용으로 마운트하여 컨테이너의 생성/삭제를 감지 (핵심!)
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      # 위에서 작성한 설정 파일을 컨테이너 내부로 마운트
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
    networks:
      - traefik-proxy
    restart: unless-stopped

  # 2. 라우팅 테스트를 위한 whoami 서비스
  whoami:
    image: "traefik/whoami"
    container_name: "whoami"
    networks:
      - traefik-proxy
    # --- Traefik 동적 설정 (레이블) ---
    labels:
      # 이 컨테이너를 Traefik이 관리하도록 활성화
      - "traefik.enable=true"
      # 'whoami' 라우터 정의 및 규칙 설정: 'whoami.localhost' 호스트로 오는 요청을 처리
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
      # 이 라우터가 사용할 엔트리포인트(통로)는 'web'(80 포트)으로 지정
      - "traefik.http.routers.whoami.entrypoints=web"
      # 이 서비스가 실제로 응답하는 포트는 80번이라고 Traefik에 알려줌
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

# Traefik과 서비스들이 함께 사용할 외부 네트워크 정의
networks:
  traefik-proxy:
    external: true

실행 및 확인
#

모든 파일 작성이 끝났습니다. 이제 네트워크를 생성하고 컨테이너를 실행합니다.

# 1. Docker Compose에서 사용할 공용 네트워크 생성
docker network create traefik-proxy

# 2. Docker Compose로 Traefik과 whoami 서비스 실행 (-d는 백그라운드 실행)
docker-compose up -d

최종 확인 은 아래의 방법으로 할 수 있습니다.

  • 대시보드 접속: 웹 브라우저에서 http://localhost:8080 으로 접속하여 Traefik 대시보드가 보이는지 확인합니다. Routers 메뉴에 whoami가 등록되어 있다면 성공입니다.

  • 라우팅 테스트: 터미널에서 아래 명령을 실행합니다.

# 'Host' 헤더를 지정하여 Traefik이 올바른 라우팅 규칙을 찾도록 합니다.
curl -H Host:whoami.localhost http://localhost

결과로 whoami 컨테이너의 정보(Hostname, IP 주소 등)가 출력되면 기본 설정이 완벽하게 끝난 것입니다.

Let’s Encrypt로 HTTPS 자동화
#

이제 기본 설정이 완료되었으니, Traefik의 진정한 힘을 발휘할 시간입니다. Let’s Encrypt를 연동하여 whoami 서비스에 완전 자동화된 HTTPS를 적용해 보겠습니다.

traefik.yml 수정: 인증서 해석기 추가
#

traefik.yml 파일에 Let’s Encrypt 설정을 담당할 인증서 해석기(Certificates Resolver) 를 추가하고, HTTP를 HTTPS로 자동 리디렉션하는 설정을 추가합니다.

# traefik.yml

api:
  insecure: true
  dashboard: true

entryPoints:
  web:
    address: ":80"
    # (추가) 80포트로 온 모든 HTTP 요청을 websecure(HTTPS)로 리디렉션
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

providers:
  docker:
    exposedByDefault: false
    network: traefik-proxy

# (추가) Let's Encrypt를 위한 인증서 해석기 정의
certificatesResolvers:
  letsencrypt: # 이 해석기의 이름은 'letsencrypt'로 지정합니다.
    acme:
      # ※반드시 실제 사용하는 이메일 주소를 입력하세요. 인증서 만료 알림 등에 사용됩니다.
      email: "your-email@example.com"
      # 발급받은 인증서를 저장할 파일 경로
      storage: "/etc/traefik/acme.json"
      # 도메인 소유권 확인 방식 (HTTP-01 챌린지)
      httpChallenge:
        entryPoint: web

docker-compose.yml 수정: HTTPS 라우팅 규칙 적용
#

docker-compose.yml 파일을 수정하여 인증서 저장 파일을 볼륨으로 연결하고, whoami 서비스의 레이블을 HTTPS에 맞게 변경합니다.

# docker-compose.yml

version: '3.8'

services:
  traefik:
    image: "traefik:v3.0"
    container_name: "traefik"
    command:
      - "--configFile=/etc/traefik/traefik.yml"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
      # (추가) 인증서 파일(acme.json)을 호스트에 영속적으로 저장하기 위한 볼륨
      - "./acme.json:/etc/traefik/acme.json"
    networks:
      - traefik-proxy
    restart: unless-stopped

  whoami:
    image: "traefik/whoami"
    container_name: "whoami"
    networks:
      - traefik-proxy
    labels:
      - "traefik.enable=true"
      # (수정) 라우터가 사용할 엔트리포인트를 'websecure'(443 포트)로 변경
      - "traefik.http.routers.whoami.entrypoints=websecure"
      # (수정) Host 규칙을 실제 소유한 도메인으로 변경
      - "traefik.http.routers.whoami.rule=Host(`whoami.your-domain.com`)"
      # (추가) 이 라우터에 TLS를 활성화
      - "traefik.http.routers.whoami.tls=true"
      # (추가) TLS 인증서 발급을 위해 'letsencrypt' 해석기를 사용하도록 지정
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

networks:
  traefik-proxy:
    external: true

실행 및 최종 확인
#

마지막 단계입니다. 인증서 파일을 생성하고 권한을 설정한 뒤, 서비스를 다시 시작하겠습니다.

인증서 파일 생성 및 권한 설정:

이 과정은 매우 중요합니다. Traefik 컨테이너가 인증서 파일에 쓸 수 있는 권한이 없으면 인증서 발급에 실패합니다.
# 비어있는 acme.json 파일 생성
touch acme.json

# 파일 소유자만 읽고 쓸 수 있도록 권한 설정 (600)
chmod 600 acme.json

Docker Compose 재시작:

변경된 설정을 적용하기 위해 컨테이너를 다시 시작합니다.

docker-compose up -d

최종 확인:

웹 브라우저에서 https://whoami.your-domain.com 으로 접속합니다.

아래 이미지처럼 주소창에 자물쇠 아이콘이 나타나고, 클릭했을 때 “Let’s Encrypt"에서 발급한 유효한 인증서라는 정보가 보이면 성공입니다.

이제 http://whoami.your-domain.com (HTTP)으로 접속해도 자동으로 https:// (HTTPS) 주소로 리디렉션되는 것을 확인할 수 있습니다.

마치며
#

이것으로 Docker와 Traefik, Let’s Encrypt를 이용한 완전 자동화된 리버스 프록시 환경 구축이 모두 끝났습니다. 이제 여러분은 새로운 서비스를 추가할 때 docker-compose.yml 파일에 레이블 몇 줄만 추가하면, 라우팅부터 HTTPS 적용까지 모든 것이 자동으로 처리되는 편리함을 누릴 수 있습니다.

더 이상 번거로운 인프라 설정에 시간을 낭비하지 마십시오. 이 가이드가 여러분이 더 중요한 가치인 개발에 집중하는 데 작은 보탬이 되기를 바랍니다.


참조