Cách sử dụng Traefik làm Reverse Proxy cho Docker Containers trên Ubuntu 20.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ác cổng80
và 443
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 Wordpress và vùng chứa Adminer , mỗi vùng nói chuyện với cơ 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:
- Một server Ubuntu 20.04 được cài đặt theo hướng dẫn cài đặt server ban đầu Ubuntu 20.04 , bao gồm user không phải root có quyền sudo và firewall .
- Docker được cài đặt trên server của bạn, bạn có thể thực hiện việc này theo Cách cài đặt và sử dụng Docker trên Ubuntu 20.04 .
- Docker Compose được cài đặt theo hướng dẫn từ Cách cài đặt Docker Compose trên Ubuntu 20.04 .
- Một domain và ba bản ghi A,
db-admin. your_domain
,blog. your_domain
vàmonitor. your_domain
. Mỗi thứ phải trỏ đến địa chỉ IP của server của bạn. Bạn có thể tìm hiểu cách trỏ domain tới DigitalOcean Server bằng cách đọc qua tài liệu DNS và Tên domain của DigitalOcean . Trong suốt hướng dẫn này, hãy thay thế domain của bạn choyour_domain
trong các file cấu hình và ví dụ.
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:
Outputadmin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
Bạn sẽ sử dụng kết quả duy nhất của bạn 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ả của bạn để bạn có thể dán nó sau này. Không sử dụng kết quả ví dụ.
Để 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 hoặc providers
khác nhau mà ta muốn sử dụng. Trong hướng dẫn này, ta sẽ sử dụng ba nhà cung cấp có sẵn của Traefik: api
, docker
và acme
. Cuối cùng trong số này, acme
hỗ trợ certificate 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 nhập được đặt tên, http
và https
, tất cả các điểm backend sẽ có quyền truy cập theo mặc định:
defaultEntryPoints = ["http", "https"]
Ta sẽ cấu hình các điểm nhập http
và https
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
:
... [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
:
... [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:
... [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à acme
vì ACME 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 :
... [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:
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 các cấu hình này, ta có thể khởi tạo 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
và :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, sẽ 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:
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 quản lý.
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 thêm một số containers cho Traefik vào 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 containers sau Traefik:
- Một blog sử dụng hình ảnh WordPress chính thức .
- 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
.
Tạo và 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:
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
, 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 cuối file của bạn:
... 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 containersblog
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ẫublog. your_domain
nó sẽ định tuyến lưu lượng truy cập đến containersblog
. -
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ạnginternal
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 cuối file của bạn:
... 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_PASSWORD
và WORDPRESS_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 vào cuối file của bạn để xác định containers Adminer:
... 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 network
và depends_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:
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_PASSWORD
và MYSQL_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_PASSWORD
và MYSQL_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:
Điều hướng đến blog. your_domain
. 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:
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, đặt menu thả xuống Hệ thống thành MySQL . Bây giờ hãy nhập mysql
cho Server , nhập root
cho tên user và nhập giá trị bạn đặt cho MYSQL_ROOT_PASSWORD
cho Mật khẩu . Để trống Database . Bây giờ nhấn Đăng nhập .
Sau khi đăng nhập, bạn sẽ thấy giao diện user Adminer:
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 phải 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 .
Các tin liên quan
Cách sử dụng Traefik làm Reverse Proxy cho Docker Containers trên Ubuntu 18.042020-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