Ngày đăng: 21 tháng 6 năm 2023
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), có thể tốn 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 thiết lập ngăn xếp ưa thích của mình và cài đặt WordPress. Thay vì cài đặt thủ công các thành phần riêng lẻ, bạn có thể sử dụng images để chuẩn hóa những thứ như thư viện, tệp cấu hình và biến môi trường. Sau đó, chạy những hình ảnh này trong containers, các quy trình biệt lập chạy trên một hệ điều hành dùng chung. Ngoài ra, bằng cách sử dụng Compose, bạn có thể phối hợp nhiều containers — ví dụ: ứng dụng và cơ sở dữ liệu — để giao tiếp với nhau.
Trong hướng dẫn này, bạn sẽ xây dựng cài đặt multi-container WordPress. Containers của bạn sẽ bao gồm cơ sở dữ liệu MySQL, máy chủ web Nginx và chính WordPress. Bạn cũng sẽ bảo mật cài đặt của mình bằng cách lấy chứng chỉ TLS/SSL với Let's Encrypt cho miền bạn muốn liên kết với trang web của mình. Cuối cùng, bạn sẽ thiết lập một cron
job để gia hạn chứng chỉ của mình để miền của bạn vẫn an toàn.
Để làm theo hướng dẫn này, bạn sẽ cần:
sudo
và tường lửa đang hoạt động. Để được hướng dẫn về cách thiết lập những thứ này, vui lòng đọc hướng dẫn Thiết lập Máy chủ Ban đầu của chúng tôi.your_domain
trỏ đến địa chỉ IP công cộng của máy chủ của bạn.www.your_domain
trỏ đến địa chỉ IP công cộng của máy chủ của bạn.Khi bạn đã thiết lập xong mọi thứ, bạn đã sẵn sàng bắt đầu bước đầu tiên.
Trước khi chạy bất kỳ vùng chứa nào, bước đầu tiên của bạn là xác định cấu hình cho máy chủ web Nginx của mình. Tệp cấu hình của bạn 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í để chuyển các yêu cầu xác minh Let's Encrypt tới ứng dụng khách Certbot để gia hạn chứng chỉ tự động.
Đầu tiên, tạo một thư mục dự án để thiết lập WordPress của bạn. Trong ví dụ này, nó được gọi là wordpress
. Bạn có thể đặt tên khác cho thư mục này nếu muốn:
- mkdir wordpress
Sau đó điều hướng đến thư mục:
- cd wordpress
Tiếp theo, tạo một thư mục cho tệp cấu hình:
- mkdir nginx-conf
Mở tệp bằng nano
hoặc trình chỉnh sửa yêu thích của bạn:
- nano nginx-conf/nginx.conf
Trong tệp này, hãy thêm một khối máy chủ với các chỉ thị cho tên máy chủ và thư mục gốc của tài liệu cũng như các khối vị trí để chỉ đạo yêu cầu của ứng dụng khách Certbot về chứng chỉ, xử lý PHP và yêu cầu nội dung tĩnh.
Thêm đoạn mã sau vào tệp. Đảm bảo thay thế your_domain
bằng tên miền của riêng bạn:
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
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 máy chủ của chúng tôi bao gồm các thông tin sau:
listen
: Điều này yêu cầu Nginx lắng nghe trên cổng 80
, điều này sẽ cho phép bạn sử dụng webroot plugin của Certbot cho các yêu cầu chứng chỉ của bạn. Lưu ý rằng bạn chưa bao gồm cổng 443
— bạn sẽ cập nhật cấu hình của mình để bao gồm SSL sau khi nhận được chứng chỉ thành công.server_name
: Tên này xác định tên máy chủ của bạn và khối máy chủ sẽ được sử dụng cho các yêu cầu đến máy chủ của bạn. Đảm bảo thay thế your_domain
trong dòng này bằng tên miền của riêng bạn.index
: Lệnh này xác định các tệp sẽ được sử dụng làm chỉ mục khi xử lý các yêu cầu đến máy chủ của bạn. Bạn đã sửa đổi thứ tự ưu tiên mặc định ở đây, di chuyển index.php
lên trước index.html
để Nginx ưu tiên các tệp có tên index.php
khi có thể.root
: Chỉ thị này đặt tên cho thư mục gốc cho các yêu cầu tới máy chủ của bạn. Thư mục này, /var/www/html
, được tạo làm điểm gắn kết tại thời điểm xây dựng theo hướng dẫn trong Dockerfile WordPress của bạn. Các hướng dẫn Dockerfile này cũng đảm bảo rằng các tệp từ bản phát hành WordPress được gắn vào ổ đĩa này.location ~ /.well-known/acme-challenge
: Khối vị trí này sẽ xử lý các yêu cầu tới thư mục .well-known
, nơi Certbot sẽ đặt một tệp tạm thời để xác thực rằng DNS cho miền của bạn phân giải thành máy chủ của bạn. Với cấu hình này, bạn sẽ có thể sử dụng webroot plugin của Certbot để lấy chứng chỉ cho miền của mình.location /
: Trong khối vị trí này, lệnh try_files
được sử dụng để kiểm tra các tệp khớp với các yêu cầu URI riêng lẻ. Tuy nhiên, thay vì trả về trạng thái 404 Not Found làm mặc định, bạn sẽ chuyển quyền kiểm soát tới tệp index.php
củ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 xử lý PHP và ủy quyền các yêu cầu này tới wordpress
container của bạn. Vì WordPress Docker image của bạn sẽ dựa trên php:fpm
image, nên bạn 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 bộ xử lý PHP độc lập cho các yêu cầu PHP. Trong trường hợp này, các yêu cầu này sẽ được xử lý bởi bộ xử lý php-fpm
đi kèm với php:fpm
image. 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 tới ứng dụng WordPress đang chạy trong wordpress
container của bạn, đặt chỉ mục ưa thích cho URI yêu cầu được phân tích cú pháp và phân tích các yêu cầu URI.location ~ /\.ht
: Khối này sẽ xử lý các tệp .htaccess
vì Nginx sẽ không phục vụ chúng. Chỉ thị deny_all
đảm bảo rằng các tệp .htaccess
sẽ không bao giờ được cung cấp cho người dùng.location = /favicon.ico
, location = /robots.txt
: Các khối này đảm bảo rằng các yêu cầu tới /favicon.ico
và /robots.txt
sẽ không được ghi lại.location ~* \.(css|gif|ico|jpeg|jpg|js|png)$
: Khối này tắt ghi nhật ký cho các yêu cầu nội dung tĩnh và đảm bảo rằng các nội dung này có khả năng lưu vào bộ nhớ cache cao vì chúng thường tốn kém để phân phối.Để biết thêm thông tin về ủy quyền FastCGI, hãy đọc Hiểu và triển khai ủy quyền FastCGI trong Nginx. Để biết thông tin về các khối máy chủ và vị trí, hãy xem Tìm hiểu các thuật toán lựa chọn khối máy chủ và vị trí của Nginx.
Lưu và đóng tệp khi bạn chỉnh sửa xong. Nếu bạn đã sử dụng nano
, hãy làm như vậy bằng cách nhấn CTRL+X
, Y
, rồi ENTER
.
Với cấu hình Nginx của bạn, bạn có thể chuyển sang tạo các biến môi trường để chuyển đến containers ứng dụng và cơ sở dữ liệu của mình khi chạy.
Containers cơ sở dữ liệu và ứng dụng WordPress của bạn sẽ 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à ứng dụng của bạn có thể truy cập được. Các biến này bao gồm cả thông tin nhạy cảm và không nhạy cảm: các giá trị nhạy cảm cho mật khẩu, người dùng cơ sở dữ liệu ứng dụng và mật khẩu gốc MySQL của bạn, và thông tin không nhạy cảm cho tên và máy chủ cơ sở dữ liệu ứng dụng của bạn.
Thay vì đặt tất cả các giá trị này trong tệp Docker Compose của bạn — tệp chính chứa thông tin về cách containers của bạn sẽ chạy — hãy đặt các giá trị nhạy cảm trong tệp .env
và hạn chế lưu thông tệp đó. Điều này sẽ ngăn các giá trị này sao chép vào kho lưu trữ dự án của bạn và được hiển thị công khai.
Trong thư mục dự án chính của bạn, ~/wordpress
, hãy mở tệp có tên .env
:
- nano .env
Các giá trị bí mật mà bạn đặt trong tệp này bao gồm mật khẩu cho MySQL root user, tên người dùng và mật khẩu mà WordPress sẽ sử dụng để truy cập cơ sở dữ liệu.
Thêm các tên và giá trị biến sau vào tệp. Hãy nhớ cung cấp các giá trị của riêng bạn ở đây cho mỗi biến:
MYSQL_ROOT_PASSWORD=your_root_password
MYSQL_USER=your_wordpress_database_user
MYSQL_PASSWORD=your_wordpress_database_password
Bao gồm là mật khẩu cho tài khoản quản trị gốc, cũng như tên người dùng và mật khẩu ưa thích của bạn cho cơ sở dữ liệu ứng dụng của bạn.
Lưu và đóng tệp khi bạn chỉnh sửa xong.
Vì tệp .env
của bạn chứa thông tin nhạy cảm nên bạn muốn đảm bảo rằng thông tin đó được đưa vào tệp .gitignore
và .dockerignore
của dự án của bạn. Điều này cho Git và Docker biết những tệp nào không được sao chép vào kho lưu trữ Git và Docker image của bạn, tương ứng.
Nếu bạn dự định làm việc với Git để kiểm soát phiên bản, hãy khởi tạo thư mục làm việc hiện tại của bạn dưới dạng kho lưu trữ với git init
:
- git init
Sau đó tạo và mở tệp .gitignore
:
- nano .gitignore
Thêm .env
vào tệp:
.env
Lưu và đóng tệp khi bạn chỉnh sửa xong.
Tương tự như vậy, bạn nên thêm .env
vào tệp .dockerignore
để nó không nằm trong containers của bạn khi bạn đang sử dụng thư mục này làm build context của mình.
Mở tập tin:
- nano .dockerignore
Thêm .env
vào tệp:
.env
Dưới đây, bạn có thể tùy chọn thêm các tệp và thư mục được liên kết với quá trình phát triển ứng dụng của mình:
.env
.git
docker-compose.yml
.dockerignore
Lưu và đóng tệp khi bạn hoàn tất.
Với thông tin nhạy cảm của bạn, giờ đây bạn có thể chuyển sang xác định dịch vụ của mình trong tệp docker-compose.yml
.
Tệp docker-compose.yml
của bạn sẽ chứa các định nghĩa dịch vụ cho thiết lập của bạn. Một dịch vụ trong Compose là một container đang chạy và định nghĩa dịch vụ chỉ định thông tin về cách mỗi container sẽ chạy.
Sử dụng Compose, bạn có thể xác định các dịch vụ khác nhau để chạy các ứng dụng multi-container vì Compose cho phép bạn liên kết các dịch vụ này cùng với các mạng và khối lượng được chia sẻ. Điều này sẽ hữu ích cho thiết lập hiện tại của bạn vì bạn sẽ tạo các container khác nhau cho cơ sở dữ liệu, ứng dụng WordPress và máy chủ web của mình. Bạn cũng sẽ tạo container để chạy ứng dụng khách Certbot nhằm lấy chứng chỉ cho máy chủ web của mình.
Để bắt đầu, hãy tạo và mở tệp docker-compose.yml
:
- nano docker-compose.yml
Thêm đoạn mã sau để xác định phiên bản tệp Soạn thảo và dịch vụ cơ sở dữ liệu db
của bạn:
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 Compose biết hình ảnh cần kéo để tạo container. Bạn đang ghim mysql:8.0
image tại đây để tránh xung đột trong tương lai vì mysql:latest
image tiếp tục được cập nhật. Để biết thêm thông tin về cách ghim phiên bản và tránh xung đột phụ thuộc, hãy đọc tài liệu Docker về các phương pháp hay nhất về Dockerfile.container_name
: Tên này chỉ định tên cho container.restart
: Điều này xác định chính sách khởi động lại container. Mặc định là no
, nhưng bạn phải đặt container khởi động lại trừ khi container bị dừng theo cách thủ công.env_file
: Tùy chọn này cho Compose biết rằng bạn muốn thêm các biến môi trường từ một tệp có tên .env
, nằm trong build context của bạn. Trong trường hợp này, build context là thư mục hiện tại của bạn.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 được xác định trong tệp .env
của bạn. Bạn sẽ đặt biến MYSQL_DATABASE
bằng wordpress
để cung cấp tên cho cơ sở dữ liệu ứng dụng của mình. Vì đây là thông tin không nhạy cảm nên bạn có thể đưa trực tiếp vào tệp docker-compose.yml
.volumes
: Tại đây, bạn đang gắn một ổ đĩa có tên là dbdata
vào thư mục /var/lib/mysql
trên container. Đây là thư mục 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 lệnh ghi đè hướng dẫn CMD mặc định cho image. Trong trường hợp cụ thể này, bạn sẽ thêm một tùy chọn vào lệnh mysqld
tiêu chuẩn của Docker image, lệnh này sẽ khởi động máy chủ MySQL trên vùng chứa. Tùy chọn này, --default-authentication-plugin=mysql_native_password
, đặt biến hệ thống --default-authentication-plugin
thành mysql_native_password
, chỉ định cơ chế xác thực nào sẽ quản lý các yêu cầu xác thực mới đối với máy chủ. Vì PHP và do đó, WordPress image của bạn sẽ không hỗ trợ mặc định xác thực mới hơn của MySQL, nên bạn phải thực hiện điều chỉnh này để xác thực người dùng cơ sở dữ liệu ứng dụng của mình.networks
: Điều này chỉ định rằng dịch vụ ứng dụng của bạn sẽ tham gia mạng app-network
mà bạn sẽ xác định ở cuối tệp.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, bạn đang đặt tên cho container của mình và xác định chính sách khởi động lại, như bạn đã làm với dịch vụ db
. Bạn cũng đang thêm một số tùy chọn dành riêng cho vùng chứa này:
depends_on
: Tùy chọn này đảm bảo rằng các container của bạn sẽ bắt đầu theo thứ tự phụ thuộc, với container wordpress
bắt đầu sau container db
. Ứng dụng WordPress của bạn phụ thuộc vào sự tồn tại của cơ sở dữ liệu ứng dụng và người dùng của bạn, do đó, việc thể hiện thứ tự phụ thuộc này sẽ cho phép ứng dụng của bạn bắt đầu đúng cách.image
: Đối với thiết lập này, bạn đang sử dụng WordPress image 5.1.1-fpm-alpine
. Như đã thảo luận ở Bước 1, việc sử dụng image này đảm bảo rằng ứng dụng của bạn sẽ có bộ xử lý php-fpm
mà Nginx yêu cầu để xử lý quá trình xử lý PHP. Đây cũng là một alpine
image, bắt nguồn từ dự án Alpine Linux, sẽ giúp giảm kích thước hình ảnh tổng thể của bạn. Để biết thêm thông tin về những lợi ích và hạn chế của việc sử dụng alpine
image và 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 lại toàn bộ cuộc thảo luận trong phần Image Variants của trang Docker Hub WordPress image.env_file
: Một lần nữa, bạn chỉ định rằng bạn muốn lấy các giá trị từ tệp .env
của mình, vì đây là nơi bạn đã xác định người dùng và mật khẩu cơ sở dữ liệu ứng dụng của mình.environment
: Tại đây, bạn đang sử dụng các giá trị bạn đã xác định trong tệp .env
của mình nhưng đang gán chúng cho các tên biến mà WordPress image yêu cầu: WORDPRESS_DB_USER
và WORDPRESS_DB_PASSWORD
. Bạn cũng đang xác định WORDPRESS_DB_HOST
, đây sẽ là máy chủ MySQL chạy trên db
container có thể truy cập được trên cổng mặc định của MySQL, 3306
. WORDPRESS_DB_NAME
của bạn sẽ có cùng giá trị mà bạn đã chỉ định trong định nghĩa dịch vụ MySQL cho MYSQL_DATABASE
của mình: wordpress
.volume
: Bạn đang gắn một volume có tên là wordpress
vào /var/www/html
mountpoint được tạo bởi WordPress image. Sử dụng một ổ đĩa được đặt tên theo cách này sẽ cho phép bạn chia sẻ mã ứng dụng của mình với các vùng chứa khác.networks
: Bạn cũng đang thêm wordpress
container vào mạng app-network
.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
Tại đây, bạn đang đặt tên cho container của mình và đặt nó phụ thuộc vào wordpress
container theo thứ tự bắt đầu. Bạn cũng đang sử dụng một alpine
image — Nginx image 1.15.12-alpine
.
Định nghĩa dịch vụ này cũng bao gồm các tùy chọn sau:
ports
: Thao tác này sẽ hiển thị cổng 80
để bật các tùy chọn cấu hình mà bạn đã xác định trong tệp nginx.conf
ở Bước 1.volume
: Tại đây, bạn đang xác định sự kết hợp giữa các volume đã đặt tên và mount liên kết:
wordpress:/var/www/html
: Thao tác này sẽ gắn mã ứng dụng WordPress của bạn vào thư mục /var/www/html
, thư mục bạn đặt làm thư mục root
trong khối máy chủ Nginx của mình../nginx-conf:/etc/nginx/conf.d
: Điều này sẽ liên kết mount thư mục cấu hình Nginx trên máy chủ với thư mục có liên quan trên container, đảm bảo rằng mọi thay đổi bạn thực hiện đối với các tệp trên máy chủ sẽ được phản ánh trong container.certbot-etc:/etc/letsencrypt
: Thao tác này sẽ gắn các khóa và chứng chỉ Let's Encrypt có liên quan cho miền của bạn vào thư mục thích hợp trên bộ chứa.Bạn cũng đã thêm container này vào mạng app-network
.
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à tên miền được liệt kê ở đây bằng thông tin của riêng 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@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
Định nghĩa này yêu cầu Compose lấy certbot/certbot
image từ Docker Hub. Nó cũng sử dụng các volume được đặt tên để chia sẻ tài nguyên với Nginx container, bao gồm chứng chỉ miền và khóa trong certbot-etc
và mã ứng dụng trong wordpress
.
Một lần nữa, bạn đã sử dụng depends_on
để chỉ định rằng certbot
container sẽ được bắt đầu khi dịch vụ webserver
đang chạy.
Bạn cũng đã bao gồm một tùy chọn command
chỉ định một lệnh phụ để chạy với lệnh certbot
mặc định của container. Lệnh phụ certonly
sẽ lấy chứng chỉ với các tùy chọn sau:
--webroot
: Điều này yêu cầu Certbot sử dụng webroot plugin để đặt các tệp trong thư mục webroot để xác thực. Plugin này phụ thuộc vào phương thức xác thực HTTP-01, sử dụng yêu cầu HTTP để chứng minh rằng Certbot có thể truy cập tài nguyên từ máy chủ phản hồi một tên miền nhất định.--webroot-path
: Điều này chỉ định đường dẫn của thư mục webroot.--email
: Email ưa thích của bạn để đăng ký và khôi phục.--agree-tos
: Điều này xác định rằng bạn đồng ý với Thỏa thuận người đăng ký của ACME (ACME’s Subscriber Agreement).--no-eff-email
: Điều này cho Certbot biết rằng bạn không muốn chia sẻ email của mình 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 chứng chỉ kiểm tra. 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 mình và tránh các giới hạn yêu cầu tên miền có thể xảy ra. Để biết thêm thông tin về các giới hạn này, vui lòng đọc tài liệu về giới hạn tốc độ của Let's Encrypt.-d
: Điều này cho phép bạn chỉ định tên miền mà bạn muốn áp dụng cho yêu cầu của mình. Trong trường hợp này, bạn đã bao gồm your_domain
và www.your_domain<^>
. Đảm bảo thay thế chúng bằng tên miền của riêng bạn.Bên dưới định nghĩa dịch vụ certbot
, thêm định nghĩa network và volume của bạn:
...
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge
Khóa volumes
cấp cao nhất (top-level volumes key) của bạn xác định các ổ đĩa certbot-etc
, wordpress
và dbdata
. Khi Docker tạo volumes, nội dung của ổ đĩa được lưu trữ trong một thư mục trên hệ thống tệp máy chủ, /var/lib/docker/volumes/
, do Docker quản lý. Sau đó, nội dung của mỗi volume sẽ được gắn từ thư mục này vào bất kỳ container nào sử dụng volume. Bằng cách này, có thể chia sẻ mã và dữ liệu giữa các container.
Mạng cầu nối user-defined app-network
cho phép giao tiếp giữa các container của bạn vì chúng nằm trên cùng một máy chủ Docker daemon. Điều này hợp lý hóa lưu lượng truy cập và liên lạc 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 đó, db
, wordpress
, và webserver
containers của bạn có thể giao tiếp với nhau và bạn chỉ cần hiển thị cổng 80
để có quyền truy cập giao diện người dùng vào ứng dụng.
Sau đây là toàn bộ tệp docker-compose.yml
:
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@your_domain --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge
Lưu và đóng tệp khi bạn chỉnh sửa xong.
Với các định nghĩa dịch vụ của bạn, bạn đã sẵn sàng bắt đầu các container và kiểm tra các yêu cầu chứng chỉ của mình.
Bắt đầu các container của bạn bằng lệnh docker-compose up
, lệnh này sẽ tạo và chạy các vùng chứa của bạn theo thứ tự bạn đã chỉ định. Bằng cách thêm cờ -d
, lệnh sẽ chạy db
, wordpress
, và webserver
containers trong nền:
- docker-compose up -d
Đầu ra sau đây xác nhận rằng 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
Sau khi hoàn tất, các dịch vụ db
, wordpress
và webserver
của bạn sẽ Up
và certbot
container 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
Bất cứ điều gì khác ngoài Up
trong cột State
đối với các dịch vụ db
, wordpress
hoặc webserver
hoặc trạng thái thoát khác 0
đối với certbot
container có nghĩa là bạn có thể cần kiểm tra nhật ký dịch vụ bằng lệnh docker-compose logs
:
- docker-compose logs service_name
Bây giờ bạn có thể kiểm tra xem chứng chỉ của mình đã được gắn vào webserver
container với docker-compose exec
chưa:
- docker-compose exec webserver ls -la /etc/letsencrypt/live
Khi các yêu cầu chứng chỉ của bạn thành công, đây là đầu ra:
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 your_domain
Bây giờ bạn đã biết yêu cầu của mình 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 tệp có định nghĩa dịch vụ certbot
và thay cờ --staging
trong tùy chọn command
bằng cờ --force-newal
, cờ này sẽ cho Certbot biết rằng bạn muốn yêu cầu chứng chỉ mới có cùng tên miền với chứng chỉ chứng chỉ hiện có. Sau đây là định nghĩa dịch vụ certbot
với cờ được cập nhật:
...
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@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
...
Bây giờ bạn có thể chạy docker-compose up
để tạo lại certbot
container. Bạn cũng sẽ bao gồm tùy chọn --no-deps
để cho Compose biết rằng nó có thể bỏ qua việc khởi động dịch vụ webserver
vì nó đang chạy:
- docker-compose up --force-recreate --no-deps certbot
Đầu ra sau đây cho biết rằng yêu cầu chứng chỉ 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 your_domain
certbot | http-01 challenge for www.your_domain
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/your_domain/fullchain.pem
certbot | Your key file has been saved at:
certbot | /etc/letsencrypt/live/your_domain/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 chứng chỉ của bạn, bạn có thể chuyển sang sửa đổi cấu hình Nginx của mình để bao gồm SSL.
Kích hoạt SSL trong cấu hình Nginx của bạn sẽ liên quan đến việc thêm chuyển hướng HTTP sang HTTPS, chỉ định chứng chỉ SSL và các vị trí chính, đồng thời thêm các tiêu đề và tham số bảo mật.
Vì bạn sẽ tạo lại dịch vụ webserver
để bao gồm các phần bổ sung này, nên bạn có thể dừng dịch vụ đó ngay bây giờ:
- docker-compose stop webserver
Trước khi sửa đổi tệp cấu hình, hãy lấy tham 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 tệp có tên là options-ssl-nginx.conf
, nằm trong thư mục nginx-conf
.
Tiếp theo, xóa tệp cấu hình Nginx mà bạn đã tạo trước đó:
- rm nginx-conf/nginx.conf
Tạo và mở một phiên bản khác của tệp:
- nano nginx-conf/nginx.conf
Thêm mã sau vào tệp để 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ế your_domain
bằng tên miền của riêng bạn:
server {
listen 80;
listen [::]:80;
server_name your_domain www.your_domain;
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 your_domain www.your_domain;
index index.php index.html index.htm;
root /var/www/html;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain/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 máy chủ HTTP chỉ định webroot cho các yêu cầu gia hạn Certbot vào thư mục .well-known/acme-challenge
. Nó cũng bao gồm một lệnh viết lại hướng các yêu cầu HTTP tới thư mục gốc tới HTTPS.
Khối máy chủ 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ể mang lại cho hiệu suất trang web, vui lòng đọc phần giới thiệu về Cách thiết lập Nginx với hỗ trợ HTTP/2 trên Ubuntu 18.04.
Khối này cũng bao gồm chứng chỉ SSL và các vị trí quan trọng của bạn, cùng với các tham số bảo mật Certbot được đề xuất mà bạn đã lưu vào nginx-conf/options-ssl-nginx.conf
.
Ngoài ra, bao gồm một số tiêu đề bảo mật sẽ cho phép bạn nhận được xếp hạng A trên những thứ như trang web thử nghiệm máy chủ SSL Labs và Security Headers. 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 đề HTTP Strict Transport Security
(HSTS) bị loại bỏ — 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ó.
Chỉ thị root
và index
của bạn cũng được đặt trong khối này, cũng như phần còn lại của 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 và đóng tệp.
Trước khi tạo lại dịch vụ webserver
, bạn sẽ cần thêm cổng 443
map vào định nghĩa dịch vụ webserver
của mình.
Mở tệp 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
Đây là tệp docker-compose.yml
hoàn chỉnh sau khi chỉnh sửa:
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@your_domain --agree-tos --no-eff-email --force-renewal -d your_domain -d www.your_domain
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge
Lưu và đóng tệp khi bạn chỉnh sửa xong.
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 với docker-compose ps
:
- docker-compose ps
Đầu ra sẽ chỉ ra rằng các dịch vụ db
, wordpress
và webserver
của bạn đ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
Khi các container của bạn đang chạy, bạn có thể hoàn tất quá trình cài đặt WordPress của mình thông qua giao diện web.
Khi các container của bạn đang chạy, hãy hoàn tất quá trình cài đặt thông qua giao diện web WordPress.
Trong trình duyệt web của bạn, hãy điều hướng đến miền máy chủ của bạn. Hãy nhớ thay thế your_domain
bằng tên miền của riêng bạn:
https://your_domain
Chọn ngôn ngữ bạn muốn sử dụng:
Sau khi nhấp vào Continue, bạn sẽ đến trang thiết lập chính, nơi bạn sẽ cần chọn tên cho trang web của mình và tên người dùng. Bạn nên chọn một tên người dùng dễ nhớ ở đây (thay vì “admin”) và một mật khẩu mạnh. Bạn có thể sử dụng mật khẩu mà WordPress tạo tự động hoặc tạo mật khẩu của riêng bạn.
Cuối cùng, bạn sẽ cần nhập địa chỉ email của mình và quyết định xem bạn có muốn ngăn các công cụ tìm kiếm lập chỉ mục trang web của mình hay không:
Nhấp vào Install WordPress ở cuối trang sẽ đưa bạn đến lời nhắc đăng nhập:
Sau khi đăng nhập, bạn sẽ có quyền truy cập vào bảng điều khiển quản trị WordPress:
Khi quá trình cài đặt WordPress của bạn hoàn tất, bạn có thể thực hiện các bước để đảm bảo rằng chứng chỉ SSL của bạn sẽ tự động gia hạn.
Chứng chỉ Let's Encrypt có hiệu lực trong 90 ngày. Bạn có thể thiết lập quy trình gia hạn tự động để đảm bảo rằng chúng không bị 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 ví dụ sau, bạn sẽ tạo một cron
job để chạy định kỳ tập lệnh sẽ gia hạn chứng chỉ và tải lại cấu hình Nginx của bạn.
Đầu tiên, hãy mở 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 chứng chỉ của bạn và tải lại cấu hình máy chủ web của bạn. Hãy nhớ thay thế tên người dùng ví dụ ở đây bằng non-root username của riêng 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
Tập lệnh này trước tiên gán nhị phân 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 tệp nhị phân docker
. Cuối cùng, nó chuyển sang thư mục dự án ~/wordpress
và chạy các lệnh docker-compose
sau:
docker-compose run
: Thao tác này sẽ khởi động certbot
container và ghi đè command
được cung cấp trong định nghĩa dịch vụ certbot
của bạn. Thay vì chỉ sử dụng lệnh phụ certonly
, lệnh phụ renew
được sử dụng, nó sẽ gia hạn các chứng chỉ sắp hết hạn. Ngoài ra còn có tùy chọn --dry-run
để kiểm tra tập lệnh của bạn.docker-compose kill
: Thao tác này sẽ gửi tín hiệu SIGHUP
đến webserver
container để tải lại cấu hình Nginx.Sau đó, nó chạy docker system prune
để xóa tất cả các container và image không sử dụng.
Đóng tệp khi bạn chỉnh sửa xong. Làm cho nó có thể thực thi được bằng lệnh sau:
- chmod +x ssl_renew.sh
Tiếp theo, hãy mở tệp crontab
gốc của bạn để chạy tập lệnh gia hạn trong một khoảng thời gian xác định:
sudo crontab -e
Nếu đây là lần đầu tiên bạn chỉnh sửa tệp này, bạn sẽ được yêu cầu chọn một trình chỉnh sửa:
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]:
...
Ở dưới cùng của tệp này, thêm dòng sau:
...
*/5 * * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1
Thao tác này sẽ đặt khoảng thời gian công việc thành 5 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 mình có hoạt động như dự kiến hay không. Tệp nhật ký, cron.log
, được tạo để ghi lại đầu ra có liên quan từ công việc.
Sau năm phút, hãy kiểm tra cron.log
để xác nhận xem yêu cầu gia hạn có thành công hay không:
- tail -f /var/log/cron.log
Đầu ra sau 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/your_domain/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
** (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Thoát ra bằng cách nhập CTRL+C
trong thiết bị đầu cuối của bạn.
Bạn có thể sửa đổi tệp 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 tệp như sau:
...
0 12 * * * /home/sammy/wordpress/ssl_renew.sh >> /var/log/cron.log 2>&1
Bạn cũng sẽ muốn xóa tùy chọn --dry-run
khỏi tập lệnh ssl_renew.sh
của mình:
#!/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
cron
job của bạn sẽ đảm bảo rằng chứng chỉ 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ể thiết lập xoay vòng nhật ký bằng tiện ích Logrotate để xoay và nén các tệp nhật ký của mình.
Trong hướng dẫn này, bạn đã sử dụng Docker Compose để tạo cài đặt WordPress với máy chủ web Nginx. Là một phần của quy trình công việc này, bạn đã nhận được chứng chỉ TLS/SSL cho miền mà bạn muốn liên kết với trang web WordPress của mình. Ngoài ra, bạn đã tạo một cron
job để gia hạn các chứng chỉ này khi cần thiết.