웹사이트 검색

Ubuntu 18.04에서 Traefik을 Docker 컨테이너의 리버스 프록시로 사용하는 방법


작성자는 DOnations 프로그램에 쓰기를 선택했습니다.

참고: 이 튜토리얼은 Traefik v1용입니다. Traefik v2를 설치하고 구성하려면 이 최신 자습서를 사용하십시오.

소개

Docker는 프로덕션에서 웹 애플리케이션을 실행하는 효율적인 방법일 수 있지만 동일한 Docker 호스트에서 여러 애플리케이션을 실행하려고 할 수 있습니다. 이 상황에서는 포트 80443만 나머지 세계에 노출하려고 하므로 역방향 프록시를 설정해야 합니다.

암호화합시다.

전제 조건

이 자습서를 따르려면 다음이 필요합니다.

  • Ubuntu 18.04 초기 서버 설정 가이드. 여기에는 루트가 아닌 sudo 사용자와 방화벽이 포함됩니다.
  • Ubuntu 18.04에서 Docker를 설치 및 사용하는 방법에 따라 수행할 수 있는 서버에 Docker가 설치되었습니다.
  • Ubuntu 18.04에 Docker Compose를 설치하는 방법의 지침에 따라 Docker Compose가 설치되었습니다.
  • 각각 서버의 IP 주소를 가리키는 도메인 및 3개의 A 레코드, db-admin, blogmonitor. DigitalOcean의 Domains 및 DNS 설명서를 읽으면 DigitalOcean Droplets에 도메인을 지정하는 방법을 배울 수 있습니다. 이 자습서 전체에서 구성 파일 및 예제에서 your_domain을 사용자 도메인으로 대체합니다.

1단계 - Traefik 구성 및 실행

Traefik 프로젝트에는 공식 Docker 이미지가 있으므로 이를 사용하여 Docker 컨테이너에서 Traefik을 실행합니다.

그러나 Traefik 컨테이너를 시작하고 실행하기 전에 모니터링 대시보드에 액세스할 수 있도록 구성 파일을 만들고 암호화된 암호를 설정해야 합니다.

htpasswd 유틸리티를 사용하여 이 암호화된 비밀번호를 생성합니다. 먼저 apache2-utils 패키지에 포함된 유틸리티를 설치합니다.

  1. sudo apt-get install apache2-utils

그런 다음 htpasswd를 사용하여 암호를 생성합니다. secure_password를 Traefik 관리 사용자에 사용하려는 비밀번호로 바꿉니다.

  1. htpasswd -nb admin secure_password

프로그램의 출력은 다음과 같습니다.

Output
admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/

Traefik 구성 파일에서 이 출력을 사용하여 Traefik 상태 검사 및 모니터링 대시보드에 대한 HTTP 기본 인증을 설정합니다. 나중에 붙여넣을 수 있도록 전체 출력 줄을 복사합니다.

Traefik 서버를 구성하기 위해 TOML 형식을 사용하여 traefik.toml이라는 새 구성 파일을 만듭니다. TOML은 INI 파일과 유사하지만 표준화된 구성 언어입니다. 이 파일을 사용하여 Traefik 서버와 다양한 통합 또는 사용하려는 공급자를 구성할 수 있습니다. 이 자습서에서는 Let's Encrypt를 사용하여 TLS를 지원하는 데 사용되는 api, dockeracme의 세 가지 Traefik 제공자를 사용합니다. .

nano 또는 선호하는 텍스트 편집기에서 새 파일을 엽니다.

  1. nano traefik.toml

먼저 모든 백엔드가 기본적으로 액세스할 수 있는 두 개의 명명된 진입점 httphttps를 추가합니다.

defaultEntryPoints = ["http", "https"]

이 파일의 뒷부분에서 httphttps 진입점을 구성합니다.

다음으로 대시보드 인터페이스에 대한 액세스를 제공하는 api 공급자를 구성합니다. 여기에 htpasswd 명령의 출력을 붙여넣을 것입니다.

...
[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]

[api]
entrypoint="dashboard"

대시보드는 Traefik 컨테이너 내에서 실행되는 별도의 웹 애플리케이션입니다. 포트 8080에서 실행되도록 대시보드를 설정했습니다.

entrypoints.dashboard 섹션은 api 공급자와 연결하는 방법을 구성하고 entrypoints.dashboard.auth.basic 섹션은 다음을 구성합니다. 대시보드에 대한 HTTP 기본 인증. users 항목의 값에 대해 방금 실행한 htpasswd 명령의 출력을 사용합니다. 쉼표로 구분하여 추가 로그인을 지정할 수 있습니다.

첫 번째 entryPoint를 정의했지만 api 공급자를 향하지 않는 표준 HTTP 및 HTTPS 통신을 위해 다른 항목을 정의해야 합니다. entryPoints 섹션은 Traefik 및 프록시 컨테이너가 수신 대기할 수 있는 주소를 구성합니다. 파일의 entryPoints 제목 아래에 다음 줄을 추가합니다.

...
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]
...

http 진입점은 포트 80을 처리하는 반면 https 진입점은 TLS/SSL용 포트 443을 사용합니다. 포트 80의 모든 트래픽을 https 진입점으로 자동 리디렉션하여 모든 요청에 대한 보안 연결을 강제합니다.

다음으로 이 섹션을 추가하여 Traefik에 대한 Let’s Encrypt 인증서 지원을 구성합니다.

...
[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

ACME는 인증서를 관리하기 위해 Let’s Encrypt와 통신하는 데 사용되는 프로토콜의 이름이기 때문에 이 섹션을 acme라고 합니다. Let’s Encrypt 서비스를 사용하려면 유효한 이메일 주소로 등록해야 하므로 Traefik이 호스트에 대한 인증서를 생성하도록 하려면 email 키를 이메일 주소로 설정하십시오. 그런 다음 Let’s Encrypt에서 수신할 정보를 acme.json이라는 JSON 파일에 저장하도록 지정합니다. entryPoint 키는 포트 443을 처리하는 진입점을 가리켜야 합니다. 여기서는 https 진입점입니다.

onHostRule 키는 Traefik이 인증서를 생성하는 방법을 나타냅니다. 우리는 지정된 호스트 이름을 가진 컨테이너가 생성되는 즉시 인증서를 가져오려고 하며 이것이 onHostRule 설정이 수행하는 작업입니다.

acme.httpChallenge 섹션에서는 Let’s Encrypt가 인증서 생성 여부를 확인할 수 있는 방법을 지정할 수 있습니다. http 진입점을 통해 챌린지의 일부로 파일을 제공하도록 구성하고 있습니다.

마지막으로 파일에 다음 줄을 추가하여 docker 공급자를 구성해 보겠습니다.

...
[docker]
domain = "your_domain"
watch = true
network = "web"

docker 공급자를 사용하면 Traefik이 Docker 컨테이너 앞에서 프록시 역할을 할 수 있습니다. 우리는 공급자가 네트워크(곧 생성할 예정)에서 새 컨테이너를 감시하고 your_domain의 하위 도메인으로 노출하도록 구성했습니다. .

이 시점에서 traefik.toml에는 다음 내용이 있어야 합니다.

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]

[api]
entrypoint="dashboard"

[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

[docker]
domain = "your_domain"
watch = true
network = "web"

파일을 저장하고 편집기를 종료합니다. 이 모든 구성이 준비되면 Traefik을 실행할 수 있습니다.

2단계 - Traefik 컨테이너 실행

다음으로 프록시가 컨테이너와 공유할 Docker 네트워크를 만듭니다. Docker 네트워크는 Docker Compose를 사용하여 실행되는 애플리케이션과 함께 사용할 수 있도록 필요합니다. 이 네트워크를 web이라고 부르겠습니다.

  1. docker network create web

Traefik 컨테이너가 시작되면 이 네트워크에 추가합니다. 그런 다음 나중에 Traefik이 프록시할 수 있도록 이 네트워크에 추가 컨테이너를 추가할 수 있습니다.

다음으로 Let's Encrypt 정보를 저장할 빈 파일을 만듭니다. Traefik이 사용할 수 있도록 컨테이너에 공유합니다.

  1. touch acme.json

Traefik은 컨테이너 내부의 루트 사용자에게 고유한 읽기 및 쓰기 권한이 있는 경우에만 이 파일을 사용할 수 있습니다. 이렇게 하려면 파일 소유자만 읽기 및 쓰기 권한을 갖도록 acme.json에 대한 권한을 잠급니다.

  1. chmod 600 acme.json

파일이 Docker에 전달되면 소유자는 자동으로 컨테이너 내부의 루트 사용자로 변경됩니다.

마지막으로 다음 명령을 사용하여 Traefik 컨테이너를 생성합니다.

  1. docker run -d \
  2. -v /var/run/docker.sock:/var/run/docker.sock \
  3. -v $PWD/traefik.toml:/traefik.toml \
  4. -v $PWD/acme.json:/acme.json \
  5. -p 80:80 \
  6. -p 443:443 \
  7. -l traefik.frontend.rule=Host:monitor.your_domain \
  8. -l traefik.port=8080 \
  9. --network web \
  10. --name traefik \
  11. traefik:1.7-alpine

명령이 조금 길기 때문에 분해해 보겠습니다.

-d 플래그를 사용하여 백그라운드에서 컨테이너를 데몬으로 실행합니다. 그런 다음 docker.sock 파일을 컨테이너에 공유하여 Traefik 프로세스가 컨테이너의 변경 사항을 수신할 수 있도록 합니다. 또한 컨테이너에 생성한 traefik.toml 구성 파일과 acme.json 파일을 공유합니다.

다음으로 Docker 호스트의 포트 :80:443을 Traefik 컨테이너의 동일한 포트에 매핑하여 Traefik이 서버에 대한 모든 HTTP 및 HTTPS 트래픽을 수신하도록 합니다.

그런 다음 Traefik 컨테이너 내의 호스트 이름 monitor.your_domain에서 포트 :8080으로 트래픽을 보내도록 Traefik에게 지시하는 두 개의 Docker 레이블을 설정하여 노출합니다. 모니터링 대시보드.

컨테이너의 네트워크를 web로 설정하고 컨테이너 이름을 traefik로 지정합니다.

마지막으로 이 컨테이너의 크기가 작기 때문에 traefik:1.7-alpine 이미지를 사용합니다.

Docker 이미지의 ENTRYPOINT는 이미지에서 컨테이너가 생성될 때 항상 실행되는 명령입니다. 이 경우 명령은 컨테이너 내의 traefik 바이너리입니다. 컨테이너를 시작할 때 해당 명령에 추가 인수를 전달할 수 있지만 traefik.toml 파일에서 모든 설정을 구성했습니다.

컨테이너가 시작되면 이제 대시보드에 액세스하여 컨테이너의 상태를 확인할 수 있습니다. 이 대시보드를 사용하여 Traefik이 등록한 프런트엔드 및 백엔드를 시각화할 수도 있습니다. 브라우저에서 https://monitor.your_domain으로 이동하여 모니터링 대시보드에 액세스합니다. 사용자 이름과 비밀번호(admin)와 1단계에서 구성한 비밀번호를 입력하라는 메시지가 표시됩니다.

로그인하면 다음과 유사한 인터페이스가 표시됩니다.

아직 볼 것이 많지 않지만 이 창을 열어 두면 Traefik이 작업할 컨테이너를 추가할 때 내용이 변경되는 것을 볼 수 있습니다.

이제 Traefik 프록시가 실행 중이고 Docker와 함께 작동하도록 구성되었으며 다른 Docker 컨테이너를 모니터링할 준비가 되었습니다. Traefik이 프록시 역할을 할 일부 컨테이너를 시작하겠습니다.

3단계 - Traefik에 컨테이너 등록

Traefik 컨테이너가 실행되면 그 뒤에서 애플리케이션을 실행할 준비가 된 것입니다. Traefik 뒤에 다음 코테이너를 시작하겠습니다.

  1. 공식 Wordpress 이미지를 사용한 블로그
  2. 공식 관리자 이미지를 사용하는 데이터베이스 관리 서버.

docker-compose.yml 파일을 사용하여 Docker Compose로 이 두 애플리케이션을 모두 관리합니다. 편집기에서 docker-compose.yml 파일을 엽니다.

  1. nano docker-compose.yml

파일에 다음 줄을 추가하여 사용할 버전과 네트워크를 지정합니다.

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

Compose 파일 형식의 최신 주 버전인 Docker Compose 버전 3을 사용합니다.

Traefik이 우리의 애플리케이션을 인식하려면 동일한 네트워크의 일부여야 하며 네트워크를 수동으로 생성했기 때문에 web의 네트워크 이름을 지정하고 external을 설정하여 가져옵니다.를 true로 변경하십시오. 그런 다음 노출된 컨테이너를 Traefik을 통해 노출하지 않을 데이터베이스 컨테이너에 연결할 수 있도록 다른 네트워크를 정의합니다. 이 네트워크를 내부라고 합니다.

다음으로 각 서비스를 한 번에 하나씩 정의합니다. 공식 WordPress 이미지를 기반으로 할 blog 컨테이너부터 시작하겠습니다. 이 구성을 파일에 추가합니다.

version: "3"
...

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql

environment 키를 사용하면 컨테이너 내부에 설정할 환경 변수를 지정할 수 있습니다. WORDPRESS_DB_PASSWORD에 대한 값을 설정하지 않음으로써 Docker Compose가 셸에서 값을 가져오고 컨테이너를 생성할 때 전달하도록 지시합니다. 컨테이너를 시작하기 전에 셸에서 이 환경 변수를 정의합니다. 이렇게 하면 구성 파일에 암호를 하드 코딩하지 않습니다.

labels 섹션은 Traefik에 대한 구성 값을 지정하는 곳입니다. Docker 레이블은 그 자체로 아무 것도 수행하지 않지만 Traefik은 컨테이너를 처리하는 방법을 알기 위해 이를 읽습니다. 각 라벨의 역할은 다음과 같습니다.

  • traefik.backend는 Traefik의 백엔드 서비스 이름을 지정합니다(실제 블로그 컨테이너를 가리킴).
  • traefik.frontend.rule=Host:blog.your_domain은 Traefik에게 요청된 호스트를 검사하고 그것이 blog.의 패턴과 일치하는지 검사하도록 지시합니다. your_domain 트래픽을 blog 컨테이너로 라우팅해야 합니다.
  • traefik.docker.network=web은 이 컨테이너의 내부 IP를 찾기 위해 Traefik이 찾을 네트워크를 지정합니다. Traefik 컨테이너는 모든 Docker 정보에 액세스할 수 있으므로 이를 지정하지 않으면 잠재적으로 내부 네트워크의 IP를 사용합니다.
  • traefik.port는 Traefik이 이 컨테이너로 트래픽을 라우팅하는 데 사용해야 하는 노출된 포트를 지정합니다.

이 구성을 사용하면 Docker 호스트의 포트 80으로 전송되는 모든 트래픽이 blog 컨테이너로 라우팅됩니다.

Traefik이 네트워크를 통해 찾을 수 있고 내부 네트워크를 통해 데이터베이스 컨테이너와 통신할 수 있도록 이 컨테이너를 두 개의 서로 다른 네트워크에 할당합니다.

마지막으로 depends_on 키는 Docker Compose에게 이 컨테이너가 종속 항목이 실행 된 후 시작되어야 함을 알려줍니다. WordPress를 실행하려면 데이터베이스가 필요하므로 blog 컨테이너를 시작하기 전에 mysql 컨테이너를 실행해야 합니다.

다음으로 이 구성을 파일에 추가하여 MySQL 서비스를 구성합니다.

services:
...
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false

이 컨테이너에는 공식 MySQL 5.7 이미지를 사용하고 있습니다. 값이 없는 environment 항목을 다시 한 번 사용하고 있음을 알 수 있습니다. WordPress 컨테이너가 MySQL과 통신할 수 있도록 하려면 MYSQL_ROOT_PASSWORDWORDPRESS_DB_PASSWORD 변수를 동일한 값으로 설정해야 합니다. 우리는 mysql 컨테이너를 Traefik이나 외부 세계에 노출하고 싶지 않기 때문에 이 컨테이너를 내부 네트워크에만 할당합니다. Traefik은 Docker 소켓에 액세스할 수 있으므로 프로세스는 기본적으로 여전히 mysql 컨테이너의 프런트엔드를 노출하므로 traefik.enable=false 레이블을 추가합니다. Traefik이 이 컨테이너를 노출하지 않도록 지정합니다.

마지막으로 이 구성을 추가하여 관리자 컨테이너를 정의합니다.

services:
...
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

이 컨테이너는 공식 관리자 이미지를 기반으로 합니다. 이 컨테이너의 networkdepends_on 구성은 우리가 blog 컨테이너에 사용하는 구성과 정확히 일치합니다.

그러나 Docker 호스트의 포트 80에 대한 모든 트래픽을 blog 컨테이너로 직접 전달하기 때문에 트래픽이 다음으로 전달되도록 이 컨테이너를 다르게 구성해야 합니다. 관리자 컨테이너로 만듭니다. traefik.frontend.rule=Host:db-admin.your_domain 줄은 Traefik에게 요청된 호스트를 검사하도록 지시합니다. db-admin.your_domain 패턴과 일치하는 경우 Traefik은 트래픽을 adminer 컨테이너로 라우팅합니다.

이 시점에서 docker-compose.yml에는 다음 내용이 있어야 합니다.

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

파일을 저장하고 텍스트 편집기를 종료합니다.

다음으로 컨테이너를 시작하기 전에 WORDPRESS_DB_PASSWORDMYSQL_ROOT_PASSWORD 변수에 대해 셸에서 값을 설정합니다.

  1. export WORDPRESS_DB_PASSWORD=secure_database_password
  2. export MYSQL_ROOT_PASSWORD=secure_database_password

secure_database_password를 원하는 데이터베이스 비밀번호로 대체하십시오. WORDPRESS_DB_PASSWORDMYSQL_ROOT_PASSWORD 모두에 동일한 암호를 사용해야 합니다.

이러한 변수를 설정한 상태에서 docker-compose를 사용하여 컨테이너를 실행합니다.

  1. docker-compose up -d

이제 Traefik 관리 대시보드를 다시 살펴보십시오. 이제 노출된 두 서버에 대한 백엔드프론트엔드가 있음을 알 수 있습니다.

blog.your_domain으로 이동하여 your_domain을 귀하의 도메인으로 대체합니다. TLS 연결로 리디렉션되며 이제 Wordpress 설정을 완료할 수 있습니다.

이제 브라우저에서 db-admin.your_domain을 방문하여 Adminer에 액세스하고 다시 your_domain을 도메인으로 대체합니다. mysql 컨테이너는 외부 세계에 노출되지 않지만 adminer 컨테이너는 다음을 사용하여 공유하는 내부 Docker 네트워크를 통해 액세스할 수 있습니다. mysql 컨테이너 이름을 호스트 이름으로 사용합니다.

Adminer 로그인 화면에서 사용자 이름은 root, 서버는 mysql, 비밀번호는 MYSQL_ROOT_PASSWORD에 설정한 값을 사용합니다. 로그인하면 관리자 사용자 인터페이스가 표시됩니다.

현재 두 사이트 모두 작동 중이며 monitor.your_domain의 대시보드를 사용하여 애플리케이션을 계속 주시할 수 있습니다.

결론

이 자습서에서는 Docker 컨테이너의 다른 애플리케이션에 요청을 프록시하도록 Traefik을 구성했습니다.

애플리케이션 컨테이너 수준에서 Traefik의 선언적 구성을 사용하면 더 많은 서비스를 쉽게 구성할 수 있으며 Traefik이 Docker를 통해 변경 사항을 즉시 인식하므로 프록시 트래픽에 새 애플리케이션을 추가할 때 traefik 컨테이너를 다시 시작할 필요가 없습니다. 모니터링 중인 소켓 파일입니다.

Traefik으로 수행할 수 있는 작업에 대해 자세히 알아보려면 공식 Traefik 문서로 이동하세요.