Cách cài đặt WordPress với Docker Compose
WordPress là một Hệ thống Quản lý Nội dung (CMS) open-souce và miễn phí được xây dựng trên cơ sở dữ liệu MySQL với xử lý PHP . Nhờ kiến trúc plugin có thể mở rộng và hệ thống tạo mẫu, và thực tế là hầu hết việc quản trị của nó có thể được thực hiện thông qua giao diện web, WordPress là một lựa chọn phổ biến khi tạo các loại trang web khác nhau, từ blog đến các trang sản phẩm đến các trang Thương mại điện tử.Chạy WordPress thường liên quan đến việc cài đặt ngăn xếp LAMP (Linux, Apache, MySQL và PHP) hoặc LEMP (Linux, Nginx, MySQL và PHP), điều này có thể tốn nhiều thời gian. Tuy nhiên, bằng cách sử dụng các công cụ như Docker và Docker Compose , bạn có thể đơn giản hóa quá trình cài đặt ngăn xếp ưa thích của bạn và cài đặt WordPress. Thay vì cài đặt các thành phần riêng lẻ bằng tay, bạn có thể sử dụng hình ảnh để chuẩn hóa những thứ như thư viện, file cấu hình và biến môi trường và chạy những hình ảnh này trong các containers , các quy trình riêng biệt chạy trên hệ điều hành dùng chung. Ngoài ra, bằng cách sử dụng Soạn thư, bạn có thể phối hợp nhiều containers - ví dụ: một ứng dụng và database - để giao tiếp với nhau.
 Trong hướng dẫn này, bạn sẽ xây dựng một cài đặt WordPress nhiều containers . Vùng chứa của bạn sẽ bao gồm database  MySQL,  web server  Nginx và chính WordPress. Bạn cũng sẽ bảo mật cài đặt  của bạn  bằng cách lấy certificate  TLS / SSL với Let's Encrypt cho domain  bạn muốn liên kết với trang web  của bạn . Cuối cùng, bạn sẽ  cài đặt  một cron việc cron để gia hạn certificate   của bạn  để domain  của bạn vẫn an toàn.
Yêu cầu
Để làm theo hướng dẫn này, bạn cần :
-   Server  chạy Ubuntu 18.04, cùng với  user  không phải root có  quyền  sudovà firewall đang hoạt động. Để được hướng dẫn về cách cài đặt những điều này, vui lòng xem hướng dẫn Cài đặt Server Ban đầu này.
- Docker được cài đặt trên server của bạn, làm theo các Bước 1 và 2 của Cách cài đặt và sử dụng Docker trên Ubuntu 18.04 .
- Docker Compose được cài đặt trên server của bạn, làm theo Bước 1 của Cách cài đặt Docker Compose trên Ubuntu 18.04 .
- Tên domain đã đăng ký. Hướng dẫn này sẽ sử dụng example.com xuyên suốt. Bạn có thể nhận một miễn phí tại Freenom hoặc sử dụng công ty đăng ký domain mà bạn chọn.
- Cả hai bản ghi DNS sau được cài đặt cho server của bạn. Bạn có thể theo dõi phần giới thiệu này về DigitalOcean DNS để biết chi tiết về cách thêm chúng vào account DigitalOcean, nếu đó là những gì bạn đang sử dụng: -  Bản ghi A với example.comtrỏ đến địa chỉ IP công cộng của server của bạn.
-  Một bản ghi A với www. example.comtrỏ đến địa chỉ IP công cộng của server của bạn.
 
-  Bản ghi A với 
Bước 1 - Xác cấu hình web server
Trước khi chạy bất kỳ containers nào, bước đầu tiên của ta sẽ là xác cấu hình cho web server Nginx của ta . Tệp cấu hình của ta sẽ bao gồm một số khối vị trí dành riêng cho WordPress, cùng với khối vị trí để hướng các yêu cầu xác minh Let's Encrypt đến ứng dụng client Certbot để gia hạn certificate tự động.
 Đầu tiên, hãy tạo một folder  dự án cho  cài đặt  WordPress của bạn có tên là wordpress và  chuyển  đến nó:
- mkdir wordpress && cd wordpress 
Tiếp theo, tạo một folder cho file cấu hình:
- mkdir nginx-conf 
Mở file  bằng nano  hoặc editor bạn quen dùng :
- nano nginx-conf/nginx.conf 
Trong file này, ta sẽ thêm một khối server với các lệnh cho tên server và root tài liệu của ta cũng như các khối vị trí để định hướng yêu cầu của ứng dụng client Certbot đối với certificate , PHP processor và các yêu cầu nội dung tĩnh.
 Dán đoạn mã sau vào file . Đảm bảo thay thế example.com bằng domain   của bạn :
server {         listen 80;         listen [::]:80;          server_name example.com www.example.com;          index index.php index.html index.htm;          root /var/www/html;          location ~ /.well-known/acme-challenge {                 allow all;                 root /var/www/html;         }          location / {                 try_files $uri $uri/ /index.php$is_args$args;         }          location ~ \.php$ {                 try_files $uri =404;                 fastcgi_split_path_info ^(.+\.php)(/.+)$;                 fastcgi_pass wordpress:9000;                 fastcgi_index index.php;                 include fastcgi_params;                 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;                 fastcgi_param PATH_INFO $fastcgi_path_info;         }          location ~ /\.ht {                 deny all;         }          location = /favicon.ico {                  log_not_found off; access_log off;          }         location = /robots.txt {                  log_not_found off; access_log off; allow all;          }         location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {                 expires max;                 log_not_found off;         } } Khối server của ta bao gồm các thông tin sau:
Chỉ thị:
-  listen: Đây nói với Nginx để lắng nghe trên cổng80, mà sẽ cho phép ta sử dụng Certbot của Plugin webroot cho các yêu cầu giấy chứng nhận của ta . Lưu ý ta chưa bao gồm cổng443- ta sẽ cập nhật cấu hình của bạn để bao gồm SSL khi ta đã lấy được certificate thành công.
-  server_name: Điều này xác định tên server của bạn và khối server sẽ được sử dụng cho các yêu cầu tới server của bạn. Đảm bảo thay thếexample.comtrong dòng này bằng domain của bạn .
-  index:indexthịindexxác định các file sẽ được sử dụng làm index khi xử lý các yêu cầu đến server của bạn. Ta đã sửa đổi thứ tự ưu tiên mặc định ở đây, di chuyểnindex.phptrướcindex.htmlđể Nginx ưu tiên các file được gọi làindex.phpkhi có thể.
-  root: Chỉ thịrootcủa ta đặt tên cho folder root cho các yêu cầu tới server của ta . Thư mục này,/var/www/html, được tạo như một điểm mount tại thời điểm xây dựng theo hướng dẫn trong WordPress Dockerfile của ta . Các hướng dẫn Dockerfile này cũng đảm bảo các file từ bản phát hành WordPress được gắn vào ổ đĩa này.
Khối vị trí:
-  location ~ /.well-known/acme-challenge: Khối vị trí này sẽ xử lý các yêu cầu.well-knownfolder .well.well-known, nơi Certbot sẽ đặt một file tạm thời để xác thực rằng DNS cho domain của ta phân giải tới server của ta . Với cấu hình này, ta sẽ có thể sử dụng plugin webroot của Certbot để lấy certificate cho domain của ta .
-  location /: Trong khối vị trí này, ta sẽ sử dụng lệnhtry_filesđể kiểm tra các file phù hợp với các yêu cầu URI riêng lẻ. Tuy nhiên, thay vì trả về trạng thái 404Not Foundlàm mặc định, ta sẽ chuyển quyền kiểm soát đếnindex.phpcủa WordPress với các đối số yêu cầu.
-  location ~ \.php$: Khối vị trí này sẽ xử lý quá trình PHP processor và ủy quyền các yêu cầu này tới containerswordpresscủa ta . Vì Docker image WordPress của ta sẽ dựa trên hình ảnhphp:fpm, ta cũng sẽ bao gồm các tùy chọn cấu hình dành riêng cho giao thức FastCGI trong khối này. Nginx yêu cầu một PHP processor độc lập cho các yêu cầu PHP: trong trường hợp của ta , các yêu cầu này sẽ được xử lý bởi bộ xử lýphp-fpmbao gồm trong hình ảnhphp:fpm. Ngoài ra, khối vị trí này bao gồm các chỉ thị, biến và tùy chọn dành riêng cho FastCGI sẽ ủy quyền các yêu cầu đến ứng dụng WordPress đang chạy trong containerswordpresscủa ta , đặt index ưu tiên cho URI yêu cầu được phân tích cú pháp và phân tích cú pháp các yêu cầu URI.
-  location ~ /\.ht: Khối này sẽ xử lý các.htaccessvì Nginx sẽ không phân phát chúng. Chỉ thịdeny_allđảm bảo các.htaccesssẽ không bao giờ được cung cấp cho user .
-  location = /favicon.ico,location = /robots.txt: Các khối này đảm bảo các yêu cầu đến/favicon.icovà/robots.txtsẽ không được ghi lại.
-  location ~* \.(css|gif|ico|jpeg|jpg|js|png)$: Khối này tắt ghi log cho các yêu cầu nội dung tĩnh và đảm bảo những nội dung này có khả năng lưu vào bộ nhớ cache cao, vì chúng thường đắt tiền để phân phát.
Để biết thêm thông tin về FastCGI proxy, hãy xem Hiểu và triển khai FastCGI Proxying trong Nginx . Để biết thông tin về khối server và vị trí, hãy xem Tìm hiểu về server Nginx và các thuật toán lựa chọn khối vị trí .
  Lưu file   khi bạn hoàn tất chỉnh sửa.Nếu bạn sử dụng nano , hãy làm như vậy bằng cách nhấn CTRL+X , Y , sau đó ENTER .
Với cấu hình Nginx của bạn tại chỗ, bạn có thể chuyển sang tạo các biến môi trường để chuyển đến ứng dụng và containers database của bạn trong thời gian chạy.
Bước 2 - Xác định các biến môi trường
Database và containers ứng dụng WordPress của bạn cần quyền truy cập vào các biến môi trường nhất định trong thời gian chạy để dữ liệu ứng dụng của bạn tồn tại và có thể truy cập vào ứng dụng của bạn. Các biến này bao gồm cả thông tin nhạy cảm và không nhạy cảm: giá trị nhạy cảm cho password gốc MySQL và password user và database ứng dụng của bạn và thông tin không nhạy cảm cho tên và server database ứng dụng của bạn.
 Thay vì đặt tất cả các giá trị này trong file  Docker Compose của  ta  - file  chính chứa thông tin về cách các containers  của  ta  sẽ chạy -  ta  có thể đặt các giá trị nhạy cảm trong file  .env và hạn chế lưu thông của nó. Điều này sẽ ngăn các giá trị này sao chép vào kho dự án của  ta  và bị lộ công khai.
 Trong folder  dự án chính của bạn, ~/ wordpress , hãy mở một file  có tên .env :
- nano .env 
Các giá trị bí mật mà ta sẽ đặt trong file này bao gồm password cho user gốc MySQL của ta , tên user và password mà WordPress sẽ sử dụng để truy cập database .
Thêm các tên và giá trị biến sau vào file . Hãy nhớ cung cấp các giá trị của bạn tại đây cho mỗi biến:
MYSQL_ROOT_PASSWORD=your_root_password MYSQL_USER=your_wordpress_database_user MYSQL_PASSWORD=your_wordpress_database_password Ta đã bao gồm password cho account quản trị gốc , cũng như tên user và password ưa thích cho database ứng dụng của ta .
Lưu file khi bạn hoàn tất chỉnh sửa.
 Bởi vì file  .env của bạn chứa thông tin nhạy cảm,  bạn cần   đảm bảo  nó  có trong  các file  .gitignore và .dockerignore của dự án .gitignore .dockerignore file  này sẽ cho Git và Docker biết những file  nào không được sao chép vào repository  Git và  Docker image  của bạn.
 Nếu bạn định làm việc với Git để kiểm soát version , hãy khởi tạo folder  làm việc hiện tại của bạn dưới dạng repository  với git init :
- git init 
Sau đó, mở file  .gitignore :
- nano .gitignore 
Thêm .env vào file :
.env Lưu file khi bạn hoàn tất chỉnh sửa.
 Tương tự như vậy, bạn nên thận trọng khi thêm .env vào file  .dockerignore , để nó không kết thúc trên containers  của bạn khi bạn đang sử dụng folder  này làm ngữ cảnh xây dựng  của bạn .
Mở tập tin:
- nano .dockerignore 
Thêm .env vào file :
.env Dưới đây, bạn có thể tùy chọn thêm các file và folder được liên kết với sự phát triển ứng dụng của bạn :
.env .git docker-compose.yml .dockerignore Lưu file khi bạn hoàn tất.
 Với thông tin nhạy cảm của bạn đã có sẵn, giờ đây bạn có thể chuyển sang xác định các dịch vụ  của bạn  trong file  docker-compose.yml .
Bước 3 - Xác định Dịch vụ với Docker Compose
 Tệp docker-compose.yml của bạn sẽ chứa các định nghĩa dịch vụ cho  cài đặt  của bạn. Dịch vụ trong Soạn là một containers  đang chạy và các định nghĩa dịch vụ chỉ định thông tin về cách mỗi containers  sẽ chạy.
Sử dụng tính năng Soạn thư, bạn có thể xác định các dịch vụ khác nhau để chạy các ứng dụng nhiều containers , vì tính năng Soạn thư cho phép bạn liên kết các dịch vụ này với nhau với các mạng và dung lượng chia sẻ. Điều này sẽ hữu ích cho cài đặt hiện tại của ta vì ta sẽ tạo các containers khác nhau cho database , ứng dụng WordPress và web server của ta . Ta cũng sẽ tạo một containers để chạy ứng dụng client Certbot nhằm lấy certificate cho web server của ta .
 Để bắt đầu, hãy mở file  docker-compose.yml :
- nano docker-compose.yml 
Thêm mã sau để xác định version  file  Soạn và dịch vụ database  db :
version: '3'  services:   db:     image: mysql:8.0     container_name: db     restart: unless-stopped     env_file: .env     environment:       - MYSQL_DATABASE=wordpress     volumes:        - dbdata:/var/lib/mysql     command: '--default-authentication-plugin=mysql_native_password'     networks:       - app-network Định nghĩa dịch vụ db chứa các tùy chọn sau:
-  image: Điều này cho biết Soạn hình ảnh nào cần kéo để tạo containers . Ta đang ghim hình ảnhmysql: 8.0ở đây để tránh xung đột trong tương lai vì hình ảnhmysql:latesttiếp tục được cập nhật. Để biết thêm thông tin về ghim version và tránh xung đột phụ thuộc, hãy xem tài liệu Docker về các phương pháp hay nhất của Dockerfile .
-  container_name: Điều này chỉ định tên cho containers .
-  restart: Điều này xác định policy khởi động lại containers . Mặc định làno, nhưng ta đã đặt containers khởi động lại trừ khi nó bị dừng theo cách thủ công.
-  env_file: Tùy chọn này cho Soạn biết rằng ta muốn thêm các biến môi trường từ một file có tên.env, nằm trong ngữ cảnh xây dựng của ta . Trong trường hợp này, bối cảnh xây dựng là folder hiện tại của ta .
-  environment: Tùy chọn này cho phép bạn thêm các biến môi trường bổ sung, ngoài những biến số được xác định trong file.envcủa bạn. Ta sẽ đặt biếnMYSQL_DATABASEbằng vớiwordpressđể cung cấp tên cho database ứng dụng của ta . Vì đây là thông tin không nhạy cảm nên ta có thể đưa trực tiếp thông tin đó vào filedocker-compose.yml.
-  volumes: Ở đây, ta đang gắn một volume có tên làdbdatavào folder/var/lib/mysqltrên containers . Đây là folder dữ liệu tiêu chuẩn cho MySQL trên hầu hết các bản phân phối.
-  command: Tùy chọn này chỉ định một lệnh để overrides lệnh CMD mặc định cho hình ảnh. Trong trường hợp của ta , ta sẽ thêm một tùy chọn vào lệnhmysqldchuẩn của Docker image , lệnh này khởi động server MySQL trên containers . Tùy chọn này,--default-authentication-plugin=mysql_native_password, đặt biến hệ thốngmysql_native_password--default-authentication-pluginthànhmysql_native_password, chỉ định cơ chế xác thực nào sẽ chi phối các yêu cầu xác thực mới tới server . Vì PHP và do đó hình ảnh WordPress của ta sẽ không hỗ trợ mặc định xác thực mới hơn của MySQL , ta phải thực hiện điều chỉnh này để xác thực user database ứng dụng của ta .
-  networks: Điều này chỉ định rằng dịch vụ ứng dụng của ta sẽ tham giaapp-networkmà ta sẽ xác định ở cuối file .
 Tiếp theo, bên dưới định nghĩa dịch vụ db của bạn, hãy thêm định nghĩa cho dịch vụ ứng dụng wordpress của bạn:
...   wordpress:     depends_on:        - db     image: wordpress:5.1.1-fpm-alpine     container_name: wordpress     restart: unless-stopped     env_file: .env     environment:       - WORDPRESS_DB_HOST=db:3306       - WORDPRESS_DB_USER=$MYSQL_USER       - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD       - WORDPRESS_DB_NAME=wordpress     volumes:       - wordpress:/var/www/html     networks:       - app-network Trong định nghĩa dịch vụ này,  ta  đang đặt tên containers   của bạn  và xác định policy  khởi động lại, như  ta  đã làm với dịch vụ db .  Ta  cũng đang thêm một số tùy chọn cụ thể cho containers  này:
-  depends_on: Tùy chọn này đảm bảo các containers của ta sẽ bắt đầu theo thứ tự phụ thuộc, với containerswordpressbắt đầu sau containersdb. Ứng dụng WordPress của ta dựa trên sự tồn tại của database ứng dụng và user của ta , vì vậy việc thể hiện thứ tự phụ thuộc này sẽ cho phép ứng dụng của ta khởi động đúng cách.
-  image: Đối với cài đặt này, ta đang sử dụng hình ảnh WordPress5.1.1 -fpm-alpine. Như đã thảo luận trong Bước 1 , việc sử dụng hình ảnh này đảm bảo ứng dụng của ta sẽ có bộ xử lýphp-fpmmà Nginx yêu cầu để xử lý quá trình PHP processor . Đây cũng là một hình ảnhalpine, có nguồn root từ dự án Alpine Linux , sẽ giúp giảm kích thước hình ảnh tổng thể của ta . Để biết thêm thông tin về lợi ích và hạn chế của việc sử dụng hình ảnhalpinevà liệu điều này có phù hợp với ứng dụng của bạn hay không, hãy xem toàn bộ cuộc thảo luận trong phần Biến thể hình ảnh của trang Docker image Hub WordPress .
-  env_file: , ta chỉ định rằng ta muốn lấy các giá trị từ file.env, vì đây là nơi ta xác định user và password database ứng dụng của bạn .
-  environment: Ở đây, ta đang sử dụng các giá trị mà ta đã xác định trong file.envcủa.env, nhưng ta đang gán chúng cho các tên biến mà hình ảnh WordPress mong đợi:WORDPRESS_DB_USERvàWORDPRESS_DB_PASSWORD. Ta cũng đang định nghĩaWORDPRESS_DB_HOST, sẽ là server MySQL chạy trên containersdbcó thể truy cập trên cổng mặc định của MySQL,3306.WORDPRESS_DB_NAMEcủa ta sẽ có cùng giá trị mà ta đã chỉ định trong định nghĩa dịch vụ MySQL choMYSQL_DATABASE:wordpresscủa ta .
-  volumes: Ta đang gắn một volume có tên làwordpressvào mountpoint/var/www/htmlđược tạo bởi hình ảnh WordPress . Sử dụng một ổ đĩa được đặt tên theo cách này sẽ cho phép ta chia sẻ mã ứng dụng của bạn với các containers khác.
-  networks: Ta cũng đang thêm containerswordpressvàoapp-networkmạng.
 Tiếp theo, bên dưới định nghĩa dịch vụ ứng dụng wordpress , hãy thêm định nghĩa sau cho dịch vụ webserver Nginx của bạn:
...   webserver:     depends_on:       - wordpress     image: nginx:1.15.12-alpine     container_name: webserver     restart: unless-stopped     ports:       - "80:80"     volumes:       - wordpress:/var/www/html       - ./nginx-conf:/etc/nginx/conf.d       - certbot-etc:/etc/letsencrypt     networks:       - app-network   ,  ta  đặt tên cho containers   của bạn  và làm cho nó phụ thuộc vào containers  wordpress theo thứ tự bắt đầu.  Ta  cũng đang sử dụng một alpine hình ảnh - những 1.15.12 -alpine Nginx hình ảnh .
Định nghĩa dịch vụ này cũng bao gồm các tùy chọn sau:
-  ports: Điều này cho thấy cổng80để kích hoạt các tùy chọn cấu hình mà ta đã xác định trong filenginx.confcủa ta ở Bước 1 .
-  volumes: Ở đây, ta đang xác định sự kết hợp của các volume được đặt tên và các mount liên kết :-  wordpress:/var/www/html: Thao tác này sẽ gắn mã ứng dụng WordPress của ta vào folder/var/www/html, folder mà ta đặt làm folderroottrong khối server Nginx của ta .
-  ./nginx-conf:/etc/nginx/conf.d: Thao tác này sẽ mount folder cấu hình Nginx trên server lưu trữ với folder liên quan trên containers , đảm bảo bất kỳ thay đổi nào ta thực hiện đối với file trên server lưu trữ sẽ được phản ánh trong thùng đựng hàng.
-  certbot-etc:/etc/letsencrypt: Điều này sẽ gắn các certificate và khóa Let's Encrypt có liên quan cho domain của ta vào folder thích hợp trên containers .
 
-  
 Và   ,  ta  đã thêm containers  này vào app-network mạng.
 Cuối cùng, bên dưới định nghĩa webserver của bạn, hãy thêm định nghĩa dịch vụ cuối cùng của bạn cho dịch vụ certbot . Đảm bảo thay thế địa chỉ email và domain  được liệt kê ở đây bằng thông tin  của bạn :
  certbot:     depends_on:       - webserver     image: certbot/certbot     container_name: certbot     volumes:       - certbot-etc:/etc/letsencrypt       - wordpress:/var/www/html     command: certonly --webroot --webroot-path=/var/www/html --email sammy@example.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com Định nghĩa này yêu cầu Soạn thảo kéo hình ảnh certbot/certbot từ Docker Hub. Nó cũng sử dụng  dung lượng  được đặt tên để chia sẻ tài nguyên với containers  Nginx, bao gồm certificate  domain  và khóa trong certbot-etc và mã ứng dụng trong wordpress .
   ,  ta  đã sử dụng depends_on để chỉ định rằng containers  certbot sẽ được khởi động khi dịch vụ webserver đang chạy.
  Ta  cũng đã bao gồm một tùy chọn command định một lệnh con để chạy với lệnh certbot mặc định của containers . Lệnh con certonly sẽ nhận được certificate  với các tùy chọn sau:
-  --webroot: Điều này yêu cầu Certbot sử dụng plugin webroot để đặt các file trong folder webroot để xác thực. Plugin này phụ thuộc vào phương thức xác thực HTTP-01 , phương thức này sử dụng yêu cầu HTTP để chứng minh rằng Certbot có thể truy cập tài nguyên từ server phản hồi với một domain nhất định.
-  --webroot-path: Điều này chỉ định đường dẫn của folder webroot.
-  --email: Email bạn muốn để đăng ký và khôi phục.
-  --agree-tos: Điều này chỉ rõ rằng bạn đồng ý với Thỏa thuận người đăng ký của ACME .
-  --no-eff-email: Điều này cho Certbot biết rằng bạn không muốn chia sẻ email của bạn với Electronic Frontier Foundation (EFF). Hãy bỏ qua điều này nếu bạn muốn.
-  --staging: Điều này cho Certbot biết rằng bạn muốn sử dụng môi trường staging của Let's Encrypt để lấy certificate thử nghiệm. Sử dụng tùy chọn này cho phép bạn kiểm tra các tùy chọn cấu hình của bạn và tránh các giới hạn yêu cầu domain có thể xảy ra. Để biết thêm thông tin về các giới hạn này, vui lòng xem tài liệu giới hạn tỷ lệ của Let's Encrypt.
-  -d: Điều này cho phép bạn chỉ định domain mà bạn muốn áp dụng cho yêu cầu của bạn . Trong trường hợp này, ta đã bao gồmexample.comvàwww. example.com. Đảm bảo thay thế các domain này bằng domain của bạn .
 Bên dưới định nghĩa dịch vụ certbot , hãy thêm định nghĩa mạng và  dung lượng  của bạn:
... volumes:   certbot-etc:   wordpress:   dbdata:  networks:   app-network:     driver: bridge   Khóa volumes cấp cao nhất của  ta  xác định các  dung lượng  certbot-etc , wordpress và dbdata . Khi Docker tạo tập, nội dung của tập được lưu trữ trong một folder  trên hệ thống file   server , /var/lib/docker/volumes/ , được quản lý bởi Docker. Nội dung của mỗi tập sau đó được  mount  từ folder  này vào bất kỳ containers  nào sử dụng tập. Bằng cách này, có thể chia sẻ mã và dữ liệu giữa các containers .
 Mạng app-network mạng cầu nối do  user  xác định cho phép giao tiếp giữa các containers  của  ta  vì chúng nằm trên cùng một  server  Docker daemon. Điều này hợp lý hóa lưu lượng truy cập và giao tiếp trong ứng dụng, vì nó mở tất cả các cổng giữa các container trên cùng một mạng cầu nối mà không để lộ bất kỳ cổng nào ra thế giới bên ngoài. Do đó, các containers  db , wordpress và webserver của  ta  có thể giao tiếp với nhau và  ta  chỉ cần để lộ cổng 80 để truy cập front-end vào ứng dụng.
 Tệp docker-compose.yml đã hoàn thành sẽ giống như sau:
version: '3'  services:   db:     image: mysql:8.0     container_name: db     restart: unless-stopped     env_file: .env     environment:       - MYSQL_DATABASE=wordpress     volumes:        - dbdata:/var/lib/mysql     command: '--default-authentication-plugin=mysql_native_password'     networks:       - app-network    wordpress:     depends_on:        - db     image: wordpress:5.1.1-fpm-alpine     container_name: wordpress     restart: unless-stopped     env_file: .env     environment:       - WORDPRESS_DB_HOST=db:3306       - WORDPRESS_DB_USER=$MYSQL_USER       - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD       - WORDPRESS_DB_NAME=wordpress     volumes:       - wordpress:/var/www/html     networks:       - app-network    webserver:     depends_on:       - wordpress     image: nginx:1.15.12-alpine     container_name: webserver     restart: unless-stopped     ports:       - "80:80"     volumes:       - wordpress:/var/www/html       - ./nginx-conf:/etc/nginx/conf.d       - certbot-etc:/etc/letsencrypt     networks:       - app-network    certbot:     depends_on:       - webserver     image: certbot/certbot     container_name: certbot     volumes:       - certbot-etc:/etc/letsencrypt       - wordpress:/var/www/html     command: certonly --webroot --webroot-path=/var/www/html --email sammy@example.com --agree-tos --no-eff-email --staging -d example.com -d www.example.com  volumes:   certbot-etc:   wordpress:   dbdata:  networks:   app-network:     driver: bridge   Lưu file khi bạn hoàn tất chỉnh sửa.
Với các định nghĩa dịch vụ của bạn, bạn đã sẵn sàng khởi động các containers và kiểm tra các certificate request của bạn .
Bước 4 - Lấy certificate SSL và thông tin đăng nhập
  Ta  có thể bắt đầu các containers   của bạn  bằng lệnh docker-compose up , lệnh này sẽ tạo và chạy các containers  của  ta  theo thứ tự mà  ta  đã chỉ định. Nếu yêu cầu domain  của  ta  thành công,  ta  sẽ thấy trạng thái thoát chính xác trong  kết quả  của  ta  và các certificate  phù hợp được gắn trong folder  /etc/letsencrypt/live trên containers  webserver .
 Tạo các containers  với docker-compose up và cờ -d , sẽ chạy các containers  db , wordpress và webserver trong nền:
- docker-compose up -d 
Bạn sẽ thấy kết quả xác nhận các dịch vụ của bạn đã được tạo:
OutputCreating db ... done Creating wordpress ... done Creating webserver ... done Creating certbot   ... done Sử dụng docker-compose ps , kiểm tra trạng thái dịch vụ của bạn:
- docker-compose ps 
Nếu mọi thứ thành công, các dịch vụ db , wordpress và webserver bạn sẽ được Up và containers  certbot sẽ thoát với thông báo trạng thái 0 :
Output  Name                 Command               State           Ports        ------------------------------------------------------------------------- certbot     certbot certonly --webroot ...   Exit 0                       db          docker-entrypoint.sh --def ...   Up       3306/tcp, 33060/tcp webserver   nginx -g daemon off;             Up       0.0.0.0:80->80/tcp  wordpress   docker-entrypoint.sh php-fpm     Up       9000/tcp            Nếu bạn thấy bất cứ điều gì khác hơn Up trong State cột cho db , wordpress , hoặc webserver dịch vụ, hoặc một trạng thái thoát khác hơn 0 cho certbot container, hãy chắc chắn để kiểm tra các bản ghi dịch vụ với các docker-compose logs lệnh:
- docker-compose logs service_name 
Bây giờ, bạn có thể kiểm tra xem các certificate   của bạn  đã được gắn vào containers  webserver bằng docker-compose exec :
- docker-compose exec webserver ls -la /etc/letsencrypt/live 
Nếu certificate request của bạn thành công, bạn sẽ thấy kết quả như sau:
Outputtotal 16 drwx------    3 root     root          4096 May 10 15:45 . drwxr-xr-x    9 root     root          4096 May 10 15:45 .. -rw-r--r--    1 root     root           740 May 10 15:45 README drwxr-xr-x    2 root     root          4096 May 10 15:45 example.com  Đến đây bạn  biết rằng yêu cầu  của bạn  sẽ thành công, bạn có thể chỉnh sửa định nghĩa dịch vụ certbot để xóa cờ --staging .
 Mở docker-compose.yml :
- nano docker-compose.yml 
Tìm phần của file  có định nghĩa dịch vụ certbot và thay thế cờ --staging trong tùy chọn command bằng cờ --force-renewal , cờ này sẽ cho Certbot biết rằng bạn muốn certificate request  mới với các domain  giống như một certificate  hiện có. Định nghĩa dịch vụ certbot bây giờ sẽ giống như sau:
...   certbot:     depends_on:       - webserver     image: certbot/certbot     container_name: certbot     volumes:       - certbot-etc:/etc/letsencrypt       - certbot-var:/var/lib/letsencrypt       - wordpress:/var/www/html     command: certonly --webroot --webroot-path=/var/www/html --email sammy@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com ...  Đến đây bạn  có thể chạy certbot docker-compose up để tạo lại containers  certbot .  Ta  cũng sẽ bao gồm tùy chọn --no-deps để cho Soạn biết rằng nó có thể bỏ qua việc khởi động dịch vụ webserver , vì nó đã chạy:
- docker-compose up --force-recreate --no-deps certbot 
Bạn sẽ thấy kết quả cho biết rằng certificate request của bạn đã thành công:
OutputRecreating certbot ... done Attaching to certbot certbot      | Saving debug log to /var/log/letsencrypt/letsencrypt.log certbot      | Plugins selected: Authenticator webroot, Installer None certbot      | Renewing an existing certificate certbot      | Performing the following challenges: certbot      | http-01 challenge for example.com certbot      | http-01 challenge for www.example.com certbot      | Using the webroot path /var/www/html for all unmatched domains. certbot      | Waiting for verification... certbot      | Cleaning up challenges certbot      | IMPORTANT NOTES: certbot      |  - Congratulations! Your certificate and chain have been saved at: certbot      |    /etc/letsencrypt/live/example.com/fullchain.pem certbot      |    Your key file has been saved at: certbot      |    /etc/letsencrypt/live/example.com/privkey.pem certbot      |    Your cert will expire on 2019-08-08. To obtain a new or tweaked certbot      |    version of this certificate in the future, simply run certbot certbot      |    again. To non-interactively renew *all* of your certificates, run certbot      |    "certbot renew" certbot      |  - Your account credentials have been saved in your Certbot certbot      |    configuration directory at /etc/letsencrypt. You should make a certbot      |    secure backup of this folder now. This configuration directory will certbot      |    also contain certificates and private keys obtained by Certbot so certbot      |    making regular backups of this folder is ideal. certbot      |  - If you like Certbot, please consider supporting our work by: certbot      |  certbot      |    Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate certbot      |    Donating to EFF:                    https://eff.org/donate-le certbot      |  certbot exited with code 0 Với các certificate của bạn, bạn có thể chuyển sang sửa đổi cấu hình Nginx của bạn để bao gồm SSL.
Bước 5 - Sửa đổi cấu hình web server và định nghĩa dịch vụ
Bật SSL trong cấu hình Nginx của ta sẽ liên quan đến việc thêm chuyển hướng HTTP đến HTTPS, chỉ định certificate SSL và các vị trí chính của ta , đồng thời thêm các thông số bảo mật và tiêu đề.
 Vì bạn sẽ tạo lại dịch vụ webserver để bao gồm những bổ sung này, bạn có thể dừng nó ngay bây giờ:
- docker-compose stop webserver 
Trước khi  ta  sửa đổi chính file  cấu hình, trước tiên hãy lấy các thông số bảo mật Nginx được đề xuất từ Certbot bằng cách sử dụng curl :
- curl -sSLo nginx-conf/options-ssl-nginx.conf https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf 
Lệnh này sẽ lưu các tham số này trong một file  có tên là options-ssl-nginx.conf , nằm trong folder  nginx-conf .
Tiếp theo, xóa file cấu hình Nginx bạn đã tạo trước đó:
- rm nginx-conf/nginx.conf 
Mở một version khác của file :
- nano nginx-conf/nginx.conf 
Thêm mã sau vào file  để chuyển hướng HTTP sang HTTPS và thêm thông tin đăng nhập SSL, giao thức và tiêu đề bảo mật. Hãy nhớ thay thế example.com bằng domain   của bạn :
server {         listen 80;         listen [::]:80;          server_name example.com www.example.com;          location ~ /.well-known/acme-challenge {                 allow all;                 root /var/www/html;         }          location / {                 rewrite ^ https://$host$request_uri? permanent;         } }  server {         listen 443 ssl http2;         listen [::]:443 ssl http2;         server_name example.com www.example.com;          index index.php index.html index.htm;          root /var/www/html;          server_tokens off;          ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;         ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;          include /etc/nginx/conf.d/options-ssl-nginx.conf;          add_header X-Frame-Options "SAMEORIGIN" always;         add_header X-XSS-Protection "1; mode=block" always;         add_header X-Content-Type-Options "nosniff" always;         add_header Referrer-Policy "no-referrer-when-downgrade" always;         add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;         # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;         # enable strict transport security only if you understand the implications          location / {                 try_files $uri $uri/ /index.php$is_args$args;         }          location ~ \.php$ {                 try_files $uri =404;                 fastcgi_split_path_info ^(.+\.php)(/.+)$;                 fastcgi_pass wordpress:9000;                 fastcgi_index index.php;                 include fastcgi_params;                 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;                 fastcgi_param PATH_INFO $fastcgi_path_info;         }          location ~ /\.ht {                 deny all;         }          location = /favicon.ico {                  log_not_found off; access_log off;          }         location = /robots.txt {                  log_not_found off; access_log off; allow all;          }         location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {                 expires max;                 log_not_found off;         } } Khối  server  HTTP chỉ định webroot cho các yêu cầu gia hạn Certbot tới folder  .well .well-known/acme-challenge . Nó cũng bao gồm một chỉ thị viết lại hướng các yêu cầu HTTP đến folder  root  tới HTTPS.
 Khối  server  HTTPS cho phép ssl và http2 . Để đọc thêm về cách HTTP / 2 lặp lại trên các giao thức HTTP và những lợi ích mà nó có thể có đối với hiệu suất trang web, vui lòng xem phần giới thiệu về Cách  Cài đặt  Nginx với Hỗ trợ HTTP / 2 trên Ubuntu 18.04 .
 Khối này cũng bao gồm certificate  SSL và các vị trí chính của  ta , cùng với các thông số bảo mật Certbot được đề xuất mà  ta  đã lưu vào nginx-conf/options-ssl-nginx.conf .
 Ngoài ra,  ta  đã bao gồm một số tiêu đề bảo mật sẽ cho phép  ta  nhận được xếp hạng A trên những thứ như Phòng thí nghiệm SSL và các trang web kiểm tra  server  Tiêu đề bảo mật . Các tiêu đề này bao gồm X-Frame-Options , X-Content-Type-Options , Referrer Policy , Content-Security-Policy và X-XSS-Protection . Tiêu đề Strict Transport Security HTTP (HSTS) được  comment  - chỉ bật tính năng này nếu bạn hiểu ý nghĩa và đã đánh giá chức năng “tải trước” của nó .
 Các index thị root và index của  ta  cũng nằm trong khối này, cũng như phần còn lại của các khối vị trí dành riêng cho WordPress được thảo luận trong Bước 1 .
Khi bạn đã chỉnh sửa xong, hãy lưu file .
 Trước khi tạo lại dịch vụ webserver , bạn cần thêm ánh xạ cổng 443 vào định nghĩa dịch vụ webserver  của bạn .
 Mở file  docker-compose.yml của bạn:
- nano docker-compose.yml 
Trong định nghĩa dịch vụ webserver , hãy thêm ánh xạ cổng sau:
...   webserver:     depends_on:       - wordpress     image: nginx:1.15.12-alpine     container_name: webserver     restart: unless-stopped     ports:       - "80:80"       - "443:443"     volumes:       - wordpress:/var/www/html       - ./nginx-conf:/etc/nginx/conf.d       - certbot-etc:/etc/letsencrypt     networks:       - app-network Tệp docker-compose.yml sẽ trông như thế này khi hoàn tất:
version: '3'  services:   db:     image: mysql:8.0     container_name: db     restart: unless-stopped     env_file: .env     environment:       - MYSQL_DATABASE=wordpress     volumes:        - dbdata:/var/lib/mysql     command: '--default-authentication-plugin=mysql_native_password'     networks:       - app-network    wordpress:     depends_on:        - db     image: wordpress:5.1.1-fpm-alpine     container_name: wordpress     restart: unless-stopped     env_file: .env     environment:       - WORDPRESS_DB_HOST=db:3306       - WORDPRESS_DB_USER=$MYSQL_USER       - WORDPRESS_DB_PASSWORD=$MYSQL_PASSWORD       - WORDPRESS_DB_NAME=wordpress     volumes:       - wordpress:/var/www/html     networks:       - app-network    webserver:     depends_on:       - wordpress     image: nginx:1.15.12-alpine     container_name: webserver     restart: unless-stopped     ports:       - "80:80"       - "443:443"     volumes:       - wordpress:/var/www/html       - ./nginx-conf:/etc/nginx/conf.d       - certbot-etc:/etc/letsencrypt     networks:       - app-network    certbot:     depends_on:       - webserver     image: certbot/certbot     container_name: certbot     volumes:       - certbot-etc:/etc/letsencrypt       - wordpress:/var/www/html     command: certonly --webroot --webroot-path=/var/www/html --email sammy@example.com --agree-tos --no-eff-email --force-renewal -d example.com -d www.example.com  volumes:   certbot-etc:   wordpress:   dbdata:  networks:   app-network:     driver: bridge   Lưu file khi bạn hoàn tất chỉnh sửa.
 Tạo lại dịch vụ webserver :
- docker-compose up -d --force-recreate --no-deps webserver 
Kiểm tra các dịch vụ của bạn bằng docker-compose ps :
- docker-compose ps 
Bạn sẽ thấy  kết quả  cho biết rằng các dịch vụ db , wordpress và webserver đang chạy:
Output  Name                 Command               State                     Ports                   ---------------------------------------------------------------------------------------------- certbot     certbot certonly --webroot ...   Exit 0                                            db          docker-entrypoint.sh --def ...   Up       3306/tcp, 33060/tcp                      webserver   nginx -g daemon off;             Up       0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp wordpress   docker-entrypoint.sh php-fpm     Up       9000/tcp     Với các containers của bạn đang chạy, bây giờ bạn có thể hoàn tất cài đặt WordPress của bạn thông qua giao diện web.
Bước 6 - Hoàn tất cài đặt thông qua giao diện web
Với các containers của ta đang chạy, ta có thể hoàn tất cài đặt thông qua giao diện web WordPress.
 Trong  trình duyệt web ,  chuyển  đến domain   server  của bạn. Hãy nhớ thay thế example.com tại đây bằng domain   của bạn :
https://example.com Chọn ngôn ngữ bạn muốn sử dụng:
Sau khi nhấp vào Tiếp tục , bạn sẽ đến trang cài đặt chính, nơi bạn cần chọn tên cho trang web của bạn và tên user . Bạn nên chọn một tên user dễ nhớ ở đây (thay vì "admin" ) và một password mạnh. Bạn có thể sử dụng password mà WordPress tạo tự động hoặc tạo password của bạn .
Cuối cùng, bạn cần nhập địa chỉ email của bạn và quyết định xem bạn có muốn ngăn cản các công cụ tìm kiếm lập index trang web hay không:
Nhấp vào Cài đặt WordPress ở cuối trang sẽ đưa bạn đến dấu nhắc đăng nhập:
Sau khi đăng nhập, bạn sẽ có quyền truy cập vào console quản trị WordPress:
Với việc cài đặt WordPress của bạn hoàn tất, bây giờ bạn có thể thực hiện các bước đảm bảo rằng certificate SSL của bạn sẽ tự động gia hạn.
Bước 7 - Gia hạn certificate
 Chứng chỉ Let's Encrypt có giá trị trong 90 ngày, vì vậy  bạn cần   cài đặt  quy trình gia hạn tự động  đảm bảo  rằng chúng không mất hiệu lực. Một cách để làm điều này là tạo một công việc với tiện ích lập lịch cron . Trong trường hợp này,  ta  sẽ tạo một cron việc cron để chạy định kỳ một tập lệnh sẽ gia hạn certificate  của  ta  và  reload  cấu hình Nginx của  ta .
 Đầu tiên, hãy mở một tập lệnh có tên ssl_renew.sh :
- nano ssl_renew.sh 
Thêm mã sau vào tập lệnh để gia hạn certificate và reload cấu hình web server của bạn. Hãy nhớ thay thế tên user mẫu ở đây bằng tên user không phải root của bạn :
#!/bin/bash  COMPOSE="/usr/local/bin/docker-compose --no-ansi" DOCKER="/usr/bin/docker"  cd /home/sammy/wordpress/ $COMPOSE run certbot renew --dry-run && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af Đầu tiên, tập lệnh này sẽ gán mã binary  docker-compose cho một biến có tên là COMPOSE và chỉ định tùy chọn --no-ansi , tùy chọn này sẽ chạy các lệnh docker-compose mà không có ký tự điều khiển ANSI . Sau đó, nó thực hiện tương tự với mã binary  docker . Cuối cùng, nó thay đổi thành folder  dự án ~/wordpress và chạy các lệnh docker-compose sau:
-  certbotdocker-compose run: Thao tác này sẽ khởi độngcertbotchứacertbotvà overridescommandđược cung cấp trong định nghĩa dịch vụcertbotcủa ta . Thay vì sử dụng lệnhcertonly, ta đang sử dụng lệnh conrenewở đây, lệnh này sẽ gia hạn các certificate sắp hết hạn. Ta đã bao gồm tùy chọn--dry-runở đây để kiểm tra tập lệnh của ta .
-  docker-compose kill: Thao tác này sẽ gửiSIGHUPhiệuSIGHUPtới containerswebserverđể reload cấu hình Nginx. Để biết thêm thông tin về cách sử dụng quy trình này để reload cấu hình Nginx của bạn, vui lòng xem bài đăng trên blog Docker này về việc triển khai hình ảnh Nginx chính thức với Docker .
 Sau đó, nó chạy sơ lược docker system prune để loại bỏ tất cả các containers  và hình ảnh không sử dụng.
Đóng file khi bạn hoàn tất chỉnh sửa. Làm cho nó có thể thực thi:
- chmod +x ssl_renew.sh 
Tiếp theo, mở file  crontab gốc của bạn để chạy tập lệnh gia hạn tại một khoảng thời gian cụ thể:
- sudo crontab -e  
Nếu đây là lần đầu tiên bạn chỉnh sửa file này, bạn cần chọn một editor :
Outputno crontab for root - using an empty one  Select an editor.  To change later, run 'select-editor'.   1. /bin/nano        <---- easiest   2. /usr/bin/vim.basic   3. /usr/bin/vim.tiny   4. /bin/ed  Choose 1-4 [1]: ... Ở cuối file , thêm dòng sau:
... */5 * * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1 Điều này sẽ đặt khoảng thời gian công việc thành năm phút một lần, vì vậy bạn có thể kiểm tra xem yêu cầu gia hạn  của bạn  có hoạt động như dự định hay không.  Ta  cũng đã tạo một file  log , cron.log , để ghi lại kết quả có liên quan từ công việc.
 Sau năm phút, hãy kiểm tra cron.log để xem liệu yêu cầu gia hạn đã thành công hay chưa:
- tail -f /var/log/cron.log 
Bạn sẽ thấy kết quả xác nhận gia hạn thành công:
Output- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ** DRY RUN: simulating 'certbot renew' close to cert expiry **          (The test certificates below have not been saved.)  Congratulations, all renewals succeeded. The following certs have been renewed:   /etc/letsencrypt/live/example.com/fullchain.pem (success) ** DRY RUN: simulating 'certbot renew' close to cert expiry **          (The test certificates above have not been saved.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  Đến đây bạn  có thể sửa đổi file  crontab để đặt khoảng thời gian hàng ngày. Ví dụ: để chạy tập lệnh hàng ngày vào buổi trưa, bạn sẽ sửa đổi dòng cuối cùng của file  để trông giống như sau:
... 0 12 * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1 Bạn  cũng cần  xóa tùy chọn --dry-run khỏi tập lệnh ssl_renew.sh  của bạn :
#!/bin/bash  COMPOSE="/usr/local/bin/docker-compose --no-ansi" DOCKER="/usr/bin/docker"  cd /home/sammy/wordpress/ $COMPOSE run certbot renew && $COMPOSE kill -s SIGHUP webserver $DOCKER system prune -af Công việc cron của bạn sẽ  đảm bảo  các certificate  Let's Encrypt của bạn không mất hiệu lực bằng cách gia hạn chúng khi chúng đủ điều kiện. Bạn cũng có thể  cài đặt  xoay log  với tiện ích Logrotate để xoay và nén các file  log   của bạn .
Kết luận
 Trong hướng dẫn này, bạn đã sử dụng Docker Compose để tạo cài đặt WordPress với  web server  Nginx. Là một phần của quy trình làm việc này, bạn đã nhận được certificate  TLS / SSL cho domain  bạn muốn liên kết với trang web WordPress  của bạn . Ngoài ra, bạn đã tạo một cron việc cron để gia hạn các certificate  này khi cần thiết.
Là các bước bổ sung để cải thiện hiệu suất và dự phòng của trang web, bạn có thể tham khảo các bài viết sau về phân phối và backup nội dung WordPress:
- Cách tăng tốc độ phân phối tài sản WordPress bằng CDN DigitalOcean Spaces .
- Cách backup trang web WordPress lên không gian .
- Cách lưu trữ tài sản WordPress trên DigitalOcean .
Nếu bạn quan tâm đến việc khám phá quy trình làm việc được tích hợp với Kubernetes, bạn cũng có thể xem:
Các tin liên quan
Cách di chuyển Docker compose workflow sang Kubernetes2019-04-03
Cách tối ưu hóa image Docker cho sản xuất
2019-03-25
Giữ lại một ứng dụng Node.js để phát triển với Docker Compose
2019-03-05
Cách cài đặt và sử dụng Docker Compose trên CentOS 7
2019-01-23
Cách sử dụng Traefik làm reverse-proxy cho container Docker trên Debian 9
2019-01-08
Cách thiết lập registry Docker riêng trên Ubuntu 18.04
2019-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
 

