Cách sử dụng Traefik làm reverse-proxy cho container Docker trên Debian 9
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ổ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 Debian 9 được cài đặt theo Cài đặt server ban đầu với Debian 9 , bao gồm user sudo không phải root và firewall .
- Docker được cài đặt trên server của bạn, bạn có thể thực hiện điều này theo Cách cài đặt và sử dụng Docker trên Debian 9 .
- Docker Compose được cài đặt theo hướng dẫn từ Cách cài đặt Docker Compose trên Debian 9 .
-  Một domain  và ba bản ghi A, db-admin,blogvàmonitor, mỗi bản ghi 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_domaintrong 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.
Tuy nhiên, 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 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ả 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 , docker và acme , đượ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 nhập được đặt tên, http và https , mà tất cả các phần  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 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.6-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, 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.6-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 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 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 . 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 file :
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.backendchỉ định tên của dịch vụ backend trong Traefik (trỏ đến containersblogthực tế).
-  traefik.frontend.rule=Host:blog. your_domainyêu cầu Traefik kiểm tra server được yêu cầu và server đó có trùng với mẫublog. your_domainnó sẽ định tuyến lưu lượng truy cập đến containersblog.
-  traefik.docker.network=webchỉ đị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ạnginternalnếu ta không chỉ định điều này.
-  traefik.portchỉ đị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  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:
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_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 để xác định containers  adminer :
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 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 , 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: 
 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: 
 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. Nếu bạn muốn khám phá thêm về containers Docker, hãy xem Cách cài đặt register Docker riêng trên Ubuntu 18.04 hoặc Cách bảo mật ứng dụng Node.js được chứa đựng bằng Nginx, Let's Encrypt và Docker Compose .
Các tin liên quan
Cách thiết lập registry Docker riêng trên Ubuntu 18.042019-01-07
Cách thiết lập triển khai nhiều node với Rancher 2.1, Kubernetes và Docker Machine trên Ubuntu 18.04
2019-01-03
Cách tạo ứng dụng Node.js với Docker
2018-11-29
Cách quản lý triển khai nhiều node với Máy Rancher và Docker trên Ubuntu 16.04
2018-10-30
Cách cài đặt và sử dụng Docker trên Ubuntu 16.04
2018-10-19
Cách cung cấp và quản lý server Docker từ xa bằng Máy Docker trên Ubuntu 18.04
2018-10-02
Cách cài đặt và bảo mật OpenFaaS bằng Docker Swarm trên Ubuntu 16.04
2018-09-19
Cách cài đặt Docker Compose trên Debian 9
2018-09-06
Cách cài đặt và sử dụng Docker trên Debian 9
2018-09-04
Cách chia sẻ dữ liệu giữa Docker Container và Host
2018-07-11
 

