Thứ ba, 27/10/2020 | 00:00 GMT+7

Cách sử dụng Traefik làm Reverse Proxy cho Docker Containers trên Ubuntu 18.04

Docker có thể là một cách hiệu quả để chạy các ứng dụng web trong production , nhưng bạn có thể cần chạy nhiều ứng dụng trên cùng một server Docker. Trong trường hợp này, bạn cần cài đặt Reverse Proxy vì bạn chỉ muốn hiển thị cổng 80443 với phần còn lại của thế giới.

Traefik là một Reverse Proxy nhận biết Docker bao gồm console giám sát của riêng nó. Trong hướng dẫn này, bạn sẽ sử dụng Traefik để định tuyến các yêu cầu đến hai containers ứng dụng web khác nhau: containers Wordpressvùng chứa Adminer , mỗi vùng nói chuyện với sở dữ liệu MySQL . Bạn sẽ cấu hình Traefik để phân phát mọi thứ qua HTTPS bằng Let's Encrypt .

Yêu cầu

Để làm theo hướng dẫn này, bạn cần những thứ sau:

Bước 1 - Cấu hình và chạy Traefik

Dự án Traefik có Docker image chính thức , vì vậy ta sẽ sử dụng hình ảnh đó để chạy Traefik trong containers Docker.

Nhưng trước khi cài đặt và chạy containers Traefik, ta cần tạo file cấu hình và cài đặt password được mã hóa để có thể truy cập trang tổng quan giám sát.

Ta sẽ sử dụng trình htpasswd để tạo password được mã hóa này. Đầu tiên, hãy cài đặt tiện ích có trong gói apache2-utils :

  • sudo apt-get install apache2-utils

Sau đó tạo password bằng htpasswd . Thay thế secure_password bằng password bạn muốn sử dụng cho admin-user Traefik:

  • htpasswd -nb admin secure_password

Kết quả kết quả từ chương trình sẽ như sau:

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

Bạn sẽ sử dụng kết quả này trong file cấu hình Traefik để cài đặt Xác thực cơ bản HTTP cho trang tổng quan giám sát và kiểm tra tình trạng Traefik. Sao chép toàn bộ dòng kết quả để bạn có thể dán nó sau này.

Để cấu hình server Traefik, ta sẽ tạo file cấu hình mới có tên traefik.toml bằng định dạng TOML. TOML là một ngôn ngữ cấu hình tương tự như các file INI, nhưng được tiêu chuẩn hóa. Tệp này cho phép ta cấu hình server Traefik và các tích hợp khác nhau hoặc các nhà cung cấp mà ta muốn sử dụng. Trong hướng dẫn này, ta sẽ sử dụng ba trong số các nhà cung cấp có sẵn của Traefik: api , dockeracme , được sử dụng để hỗ trợ TLS bằng Let's Encrypt.

Mở file mới của bạn trong nano hoặc editor yêu thích của bạn:

  • nano traefik.toml

Đầu tiên, hãy thêm hai điểm vào được đặt tên, httphttps , mà tất cả các phần backend sẽ có quyền truy cập theo mặc định:

traefik.toml
defaultEntryPoints = ["http", "https"] 

Ta sẽ cấu hình các điểm nhập httphttps sau trong file này.

Tiếp theo, cấu hình nhà cung cấp api , cung cấp cho bạn quyền truy cập vào giao diện console . Đây là nơi bạn sẽ dán kết quả từ lệnh htpasswd :

traefik.toml
... [entryPoints]   [entryPoints.dashboard]     address = ":8080"     [entryPoints.dashboard.auth]       [entryPoints.dashboard.auth.basic]         users = ["admin:your_encrypted_password"]  [api] entrypoint="dashboard" 

Trang tổng quan là một ứng dụng web riêng biệt sẽ chạy trong containers Traefik. Ta đặt console để chạy trên cổng 8080 .

Phần entrypoints.dashboard cấu hình cách ta sẽ kết nối với nhà cung cấp api và phần entrypoints.dashboard.auth.basic cấu hình Xác thực Cơ bản HTTP cho trang tổng quan. Sử dụng kết quả từ lệnh htpasswd mà bạn vừa chạy cho giá trị của mục nhập users . Bạn có thể chỉ định thông tin đăng nhập bổ sung bằng cách phân tách chúng bằng dấu phẩy.

Ta đã xác định entryPoint đầu tiên của entryPoint , nhưng ta cần xác định những điểm khác cho giao tiếp HTTP và HTTPS tiêu chuẩn không hướng tới nhà cung cấp api . Phần entryPoints cấu hình các địa chỉ mà Traefik và các containers được ủy quyền có thể lắng nghe. Thêm các dòng này vào file bên dưới tiêu đề entryPoints :

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

Điểm nhập http xử lý cổng 80 , trong khi điểm nhập https sử dụng cổng 443 cho TLS / SSL. Ta tự động chuyển hướng tất cả lưu lượng trên cổng 80 đến điểm nhập https để buộc kết nối an toàn cho tất cả các yêu cầu.

Tiếp theo, thêm phần này để cấu hình hỗ trợ certificate Let's Encrypt cho Traefik:

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

Phần này được gọi là acmeACME là tên của giao thức được sử dụng để giao tiếp với Let's Encrypt để quản lý certificate . Dịch vụ Encrypt của Hãy yêu cầu đăng ký với một địa chỉ email hợp lệ, vì vậy để có Traefik tạo certificate cho server của ta , cài đặt email key để địa chỉ email của bạn. Sau đó, ta chỉ định rằng ta sẽ lưu trữ thông tin mà ta sẽ nhận được từ Let's Encrypt trong một file JSON có tên là acme.json . Khóa entryPoint cần trỏ đến cổng xử lý điểm nhập 443 , trong trường hợp của ta là điểm nhập https .

Khóa onHostRule chỉ ra cách Traefik tiến hành tạo certificate . Ta muốn tìm nạp certificate của bạn ngay sau khi các containers của ta có tên server được chỉ định được tạo và đó là những gì cài đặt onHostRule sẽ thực hiện.

Phần acme.httpChallenge cho phép ta chỉ định cách Let's Encrypt có thể xác minh certificate sẽ được tạo. Ta đang cấu hình nó để phân phát file như một phần của thử thách thông qua điểm nhập http .

Cuối cùng, hãy cấu hình trình cung cấp docker bằng cách thêm các dòng sau vào file :

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

Các docker cung cấp dịch vụ cho phép Traefik để hoạt động như một proxy trước container Docker. Ta đã cấu hình nhà cung cấp để watch các containers mới trên mạng web (mà ta sẽ sớm tạo) và hiển thị chúng dưới dạng domain phụ của your_domain .

Đến đây, traefik.toml sẽ có các nội dung sau:

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" 

Lưu file và thoát khỏi editor . Với tất cả cấu hình này, ta có thể kích hoạt Traefik.

Bước 2 - Chạy Traefik Container

Tiếp theo, tạo một mạng Docker để proxy chia sẻ với các containers . Mạng Docker là cần thiết để ta có thể sử dụng nó với các ứng dụng đang chạy bằng Docker Compose. Hãy gọi mạng này là web .

  • docker network create web

Khi containers Traefik bắt đầu, ta sẽ thêm nó vào mạng này. Sau đó, ta có thể thêm các containers bổ sung vào mạng này sau đó để Traefik ủy quyền.

Tiếp theo, tạo một file trống chứa thông tin Let's Encrypt của ta . Ta sẽ chia sẻ cái này vào containers để Traefik có thể sử dụng nó:

  • touch acme.json

Traefik sẽ chỉ có thể sử dụng file này nếu user root bên trong containers có quyền truy cập đọc và ghi duy nhất vào nó. Để thực hiện việc này, hãy khóa các quyền trên acme.json để chỉ chủ sở hữu của file mới có quyền đọc và ghi.

  • chmod 600 acme.json

Khi file được chuyển đến Docker, chủ sở hữu sẽ tự động thay đổi thành user root bên trong containers .

Cuối cùng, tạo containers Traefik bằng lệnh này:

  • docker run -d \
  • -v /var/run/docker.sock:/var/run/docker.sock \
  • -v $PWD/traefik.toml:/traefik.toml \
  • -v $PWD/acme.json:/acme.json \
  • -p 80:80 \
  • -p 443:443 \
  • -l traefik.frontend.rule=Host:monitor.your_domain \
  • -l traefik.port=8080 \
  • --network web \
  • --name traefik \
  • traefik:1.7-alpine

Lệnh hơi dài nên hãy chia nhỏ nó ra.

Ta sử dụng cờ -d để chạy containers trong nền dưới dạng daemon. Sau đó, ta chia sẻ file docker.sock của docker.sock vào containers để quy trình Traefik có thể lắng nghe các thay đổi đối với containers . Ta cũng chia sẻ file cấu hình traefik.toml và file acme.json mà ta đã tạo vào containers .

Tiếp theo, ta ánh xạ các cổng :80:443 của server Docker của ta với các cổng giống nhau trong containers Traefik để Traefik nhận tất cả truy cập HTTP và HTTPS đến server .

Sau đó, ta cài đặt hai nhãn Docker yêu cầu Traefik hướng lưu lượng truy cập đến trình monitor. your_domain tên server monitor. your_domain đến cổng :8080 trong containers Traefik, hiển thị console giám sát.

Ta đặt mạng của containers thành web và ta đặt tên cho containers là traefik .

Cuối cùng, ta sử dụng hình ảnh traefik:1.7-alpine cho containers này, vì nó nhỏ.

ENTRYPOINT của Docker image là lệnh luôn chạy khi containers được tạo từ hình ảnh. Trong trường hợp này, lệnh là binary traefik trong containers . Bạn có thể chuyển các đối số bổ sung cho lệnh đó khi chạy containers , nhưng ta đã cấu hình tất cả các cài đặt của bạn trong file traefik.toml .

Khi containers được khởi động, bây giờ bạn có một trang tổng quan mà bạn có thể truy cập để xem tình trạng của containers của bạn . Bạn cũng có thể sử dụng console này để trực quan hóa các giao diện user và backend mà Traefik đã đăng ký. Truy cập trang tổng quan giám sát bằng cách trỏ trình duyệt của bạn tới https://monitor. your_domain . Bạn sẽ được yêu cầu nhập tên user và password của bạn , đó là administrator và password bạn đã cấu hình ở Bước 1.

Sau khi đăng nhập, bạn sẽ thấy một giao diện tương tự như sau:

Trang tổng quan Traefik trống

Vẫn chưa có nhiều thứ để xem, nhưng hãy để cửa sổ này mở và bạn sẽ thấy nội dung thay đổi khi bạn thêm các containers để Traefik làm việc.

Bây giờ ta có proxy Traefik của bạn đang chạy, được cấu hình để hoạt động với Docker và sẵn sàng theo dõi các containers Docker khác. Hãy bắt đầu một số containers để Traefik hoạt động như một proxy.

Bước 3 - Đăng ký containers với Traefik

Với containers Traefik đang chạy, bạn đã sẵn sàng chạy các ứng dụng đằng sau nó. Hãy chạy các cotainers sau Traefik:

  1. Một blog sử dụng hình ảnh Wordpress chính thức .
  2. Server quản lý database sử dụng hình ảnh Adminer chính thức .

Ta sẽ quản lý cả hai ứng dụng này bằng Docker Compose bằng cách sử dụng file docker-compose.yml . Mở file docker-compose.yml trong editor :

  • nano docker-compose.yml

Thêm các dòng sau vào file để chỉ định version và mạng ta sẽ sử dụng:

docker-compos.yml
version: "3"  networks:   web:     external: true   internal:     external: false 

Ta sử dụng Docker Compose version 3 vì đây là version chính mới nhất của định dạng file Compose.

Để Traefik nhận ra các ứng dụng của ta , chúng phải là một phần của cùng một mạng và vì ta đã tạo mạng theo cách thủ công, ta đưa nó vào bằng cách chỉ định tên mạng của web và đặt external thành true . Sau đó, ta xác định một mạng khác để ta có thể kết nối các containers được tiếp xúc với một containers database mà ta sẽ không hiển thị thông qua Traefik. Ta sẽ gọi mạng này là mạng internal .

Tiếp theo, ta sẽ xác định từng services của ta , từng services một. Hãy bắt đầu với containers blog , ta sẽ dựa trên hình ảnh WordPress chính thức. Thêm cấu hình này vào file :

docker-compos.yml
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 

Khóa environment cho phép bạn chỉ định các biến môi trường sẽ được đặt bên trong containers . Bằng cách không đặt giá trị cho WORDPRESS_DB_PASSWORD , ta đang yêu cầu Docker Compose lấy giá trị từ shell của ta và chuyển nó qua khi ta tạo containers . Ta sẽ xác định biến môi trường này trong shell của ta trước khi bắt đầu các containers . Bằng cách này, ta không đặt password vào file cấu hình.

Phần labels là nơi bạn chỉ định các giá trị cấu hình cho Traefik. Các nhãn Docker không tự làm bất cứ điều gì, nhưng Traefik đọc những thứ này để biết cách xử lý containers . Đây là những gì mỗi nhãn này thực hiện:

  • traefik.backend chỉ định tên của dịch vụ backend trong Traefik (trỏ đến containers blog thực tế).
  • traefik.frontend.rule=Host:blog. your_domain yêu cầu Traefik kiểm tra server được yêu cầu và server đó có trùng với mẫu blog. your_domain nó sẽ định tuyến lưu lượng truy cập đến containers blog .
  • traefik.docker.network=web chỉ định mạng nào cần xem để Traefik tìm IP nội bộ cho containers này. Vì containers Traefik của ta có quyền truy cập vào tất cả thông tin Docker, nên nó có khả năng lấy IP cho mạng internal nếu ta không chỉ định điều này.
  • traefik.port chỉ định cổng tiếp xúc mà Traefik nên sử dụng để định tuyến lưu lượng truy cập đến containers này.

Với cấu hình này, tất cả truy cập được gửi đến cổng 80 của server lưu trữ Docker của ta sẽ được chuyển đến containers blog .

Ta gán containers này cho hai mạng khác nhau để Traefik có thể tìm thấy nó qua mạng web và nó có thể giao tiếp với containers database thông qua mạng internal .

Cuối cùng, khóa depends_on nói với Docker Compose rằng containers này cần bắt đầu sau khi các depends_on phụ thuộc của nó đang chạy. Vì WordPress cần một database để chạy, ta phải chạy containers mysql trước khi bắt đầu containers blog của ta .

Tiếp theo, cấu hình dịch vụ MySQL bằng cách thêm cấu hình này vào file của bạn:

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

Ta đang sử dụng hình ảnh MySQL 5.7 chính thức cho containers này. Bạn sẽ nhận thấy rằng ta đang sử dụng một mục environment mà không có giá trị. Các MYSQL_ROOT_PASSWORDWORDPRESS_DB_PASSWORD cần được đặt thành cùng một giá trị đảm bảo rằng containers WordPress của ta có thể giao tiếp với MySQL. Ta không muốn hiển thị containers mysql với Traefik hoặc thế giới bên ngoài, vì vậy ta chỉ gán containers này cho mạng internal . Vì Traefik có quyền truy cập vào Docker socket, theo mặc định, quy trình sẽ vẫn hiển thị giao diện user cho containers mysql , vì vậy ta sẽ thêm nhãn traefik.enable=false để chỉ định rằng Traefik sẽ không hiển thị containers này.

Cuối cùng, thêm cấu hình này để xác định containers Adminer:

docker-compos.yml
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 

Vùng chứa này dựa trên hình ảnh Adminer chính thức. Cấu hình networkdepends_on cho containers này khớp chính xác với những gì ta đang sử dụng cho containers blog .

Tuy nhiên, vì ta đang hướng tất cả lưu lượng truy cập đến cổng 80 trên server Docker của ta trực tiếp đến containers blog , ta cần cấu hình containers này theo cách khác để lưu lượng truy cập đến adminer chứa adminer của ta . Dòng traefik.frontend.rule=Host:db-admin. your_domain yêu cầu Traefik kiểm tra server được yêu cầu. Nếu nó trùng với mẫu của db-admin. your_domain , Traefik sẽ định tuyến lưu lượng truy cập đến containers adminer .

Đến đây, docker-compose.yml sẽ có các nội dung sau:

docker-compos.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 

Lưu file và thoát khỏi editor .

Tiếp theo, đặt giá trị trong shell của bạn cho các WORDPRESS_DB_PASSWORDMYSQL_ROOT_PASSWORD trước khi bạn bắt đầu các containers của bạn :

  • export WORDPRESS_DB_PASSWORD=secure_database_password
  • export MYSQL_ROOT_PASSWORD=secure_database_password

Thay thế secure_database_password bằng password database mong muốn của bạn. Hãy nhớ sử dụng cùng một password cho cả WORDPRESS_DB_PASSWORDMYSQL_ROOT_PASSWORD .

Với các biến này đã được đặt, hãy chạy các containers bằng cách sử dụng docker-compose :

  • docker-compose up -d

Bây giờ hãy xem xét console quản trị Traefik. Bạn sẽ thấy rằng bây giờ có một chương trình backend và một frontend cho hai server được tiếp xúc:

 Control panel  Traefik được phổ biến

Điều hướng đến blog. your_domain , thay thế your_domain bằng domain của bạn. Bạn sẽ được chuyển hướng đến kết nối TLS và bây giờ có thể hoàn tất cài đặt Wordpress:

Màn hình  cài đặt  WordPress

Bây giờ truy cập Adminer bằng cách truy cập db-admin. your_domain trong trình duyệt của bạn, lại thay thế your_domain bằng domain của bạn. Vùng chứa mysql không được tiếp xúc với thế giới bên ngoài, nhưng containers adminer có quyền truy cập vào nó thông qua mạng Docker internal mà chúng chia sẻ bằng cách sử dụng tên containers mysql làm tên server .

Trên màn hình đăng nhập Adminer, sử dụng tên user root , sử dụng mysql cho server và sử dụng giá trị bạn đặt cho MYSQL_ROOT_PASSWORD cho password . Sau khi đăng nhập, bạn sẽ thấy giao diện user Adminer:

Adminer được kết nối với database  MySQL

Cả hai trang web hiện đang hoạt động và bạn có thể sử dụng console tại monitor. your_domain để theo dõi các ứng dụng của bạn.

Kết luận

Trong hướng dẫn này, bạn đã cấu hình Traefik cho các yêu cầu proxy tới các ứng dụng khác trong containers Docker.

Cấu hình khai báo của Traefik ở cấp containers ứng dụng giúp bạn dễ dàng cấu hình nhiều dịch vụ hơn và không cần khởi động lại containers traefik khi bạn thêm ứng dụng mới vào lưu lượng proxy vì Traefik nhận thấy các thay đổi ngay lập tức thông qua file socket Docker mà nó đang theo dõi.

Để tìm hiểu thêm về những gì bạn có thể làm với Traefik, hãy xem tài liệu Traefik chính thức.


Tags:

Các tin trước

Cách sử dụng Traefik làm Reverse Proxy cho Docker Containers trên Ubuntu 20.04 2020-10-27
Cách tự động hóa thiết lập Jenkins với cấu hình Docker và Jenkins dưới dạng mã 2020-09-29
Cách phát triển trang web Drupal 9 trên máy cục bộ của bạn bằng Docker và DDEV 2020-08-12
Cách truy cập từ xa các ứng dụng GUI bằng Docker và Caddy trên Ubuntu 18.04 2020-08-07
Cách truy cập từ xa các ứng dụng GUI bằng Docker và Caddy trên Debian 9 2020-08-07
Cách truy cập từ xa các ứng dụng GUI bằng Docker và Caddy trên Debian 10 2020-08-07
Cách loại bỏ image Docker, container và khối lượng 2020-08-06
Cách truy cập từ xa các ứng dụng GUI bằng Docker và Caddy trên Ubuntu 20.04 2020-08-04
Cách mở rộng và bảo mật một ứng dụng Django với Docker, Nginx và Let's Encrypt 2020-07-10
Cách tạo ứng dụng Node.js với Docker trên Ubuntu 20.04 2020-06-30