手动部署 WordPress 那一套 LAMP/LEMP 的流程,想必大家都不陌生,但说实话,挺繁琐的。环境配置、软件依赖、权限管理,任何一个环节出错都可能让你折腾半天。
今天我们换个玩法,用 Docker Compose 把 WordPress、Nginx、MySQL 和 SSL 证书一条龙搞定。这套方案不仅部署速度快,而且环境隔离做得好,方便迁移和维护,非常适合现代化的工作流。
整个流程下来,你会得到一个包含以下组件的、生产就绪的 WordPress 网站:
- Nginx 作为 Web 服务器
- MySQL 8.0 数据库
- WordPress (PHP-FPM) 应用本身
- Certbot 用于自动获取和续期 Let’s Encrypt 的免费 SSL 证书
准备工作
在开始之前,你需要准备好以下几样东西:
- 一台装有 Docker 和 Docker Compose 的服务器(建议 Ubuntu)。
- 一个注册好的域名,并且已经将 DNS A 记录指向你服务器的公网 IP。
- 具备
sudo权限的非 root 用户。
第一步:初始化项目结构
首先,我们需要为项目创建一个目录,并规划好文件结构。
# 创建并进入项目目录
mkdir wordpress_site && cd wordpress_site
# 创建用于存放 Nginx 配置的子目录
mkdir nginx-conf
接下来,创建一个 .env 文件,用于存放敏感的环境变量。
nano .env
在这个文件里,我们定义数据库的密码等信息。请务必使用你自己的强密码替换掉占位符。
# ~/wordpress_site/.env
MYSQL_ROOT_PASSWORD=your_strong_root_password
MYSQL_USER=wp_user
MYSQL_PASSWORD=your_strong_user_password
这个文件专门用来存放敏感信息,比如数据库密码,这样就不会意外地把它提交到 Git 仓库里,非常安全的地道。为了确保这一点,最好再创建一个 .gitignore 和 .dockerignore 文件,把 .env 加进去。
第二步:定义服务编排 docker-compose.yml
这是整个部署的核心。docker-compose.yml 文件定义了我们需要的所有服务(容器)、它们之间的关系、网络以及数据卷。
在项目根目录 ~/wordpress_site/下创建 docker-compose.yml 文件:
nano 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:latest-fpm-alpine # 使用 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:latest-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 your_email@example.com --agree-tos --no-eff-email --staging -d your_domain.com -d www.your_domain.com
volumes:
certbot-etc:
wordpress:
dbdata:
networks:
app-network:
driver: bridge
配置解析:
services: 定义了四个服务:db,wordpress,webserver,certbot。db服务 (MySQL):image: mysql:8.0: 锁定 MySQL 8.0 版本,避免未来因镜像更新导致兼容性问题。env_file: .env: 从.env文件加载环境变量。volumes: - dbdata:/var/lib/mysql: 将数据库文件持久化到名为dbdata的 Docker 数据卷中,这样即使容器被删除,数据也不会丢失。command: '--default-authentication-plugin=mysql_native_password': 这是一个关键点。MySQL 8.0 默认的认证插件 PHP 不支持,所以我们强制它使用旧的兼容插件。networks: - app-network: 将其连接到我们自定义的网络中。
wordpress服务:depends_on: - db: 因为 WordPress 应用依赖数据库,这个depends_on确保了db容器会比wordpress容器先启来。image: wordpress:latest-fpm-alpine: 我们用的是fpm-alpine版本的镜像。FPM (FastCGI Process Manager) 是 Nginx 连接 PHP 所需的处理器,alpine版本则体积更小。environment: 这里设置了 WordPress 连接数据库所需的各种凭证,注意它引用了.env文件中的变量。volumes: - wordpress:/var/www/html: 将 WordPress 的所有文件(核心、主题、插件、上传内容)都存放在wordpress数据卷中。
webserver服务 (Nginx):ports: - "80:80" - "443:443": 将容器的 80 和 443 端口映射到主机的对应端口,这样外部流量才能访问。volumes: 这里挂载了三个卷:wordpress:/var/www/html: 共享 WordPress 的文件,以便 Nginx 可以提供服务。./nginx-conf:/etc/nginx/conf.d: 将我们本地的 Nginx 配置文件目录挂载到容器中。certbot-etc:/etc/letsencrypt: 共享 SSL 证书文件。
certbot服务:- 这个服务专门用来和 Let’s Encrypt 打交道。
volumes: 它也挂载了证书目录和 WordPress 文件目录(用于webroot验证)。command: 这是核心。它告诉 Certbot:certonly: 只获取证书,不安装。--webroot: 使用 webroot 插件进行验证,即在网站根目录下放置一个临时文件。--staging: 非常重要! 初始阶段我们使用 Let’s Encrypt 的测试环境,避免因为配置错误而触发请求频率限制。-d your_domain.com: 替换成你自己的域名。
volumes和networks:- 在文件底部,我们声明了所有用到的命名数据卷 (
dbdata,wordpress,certbot-etc) 和自定义桥接网络app-network。这个网络让所有服务能通过容器名互相通信,同时保持了与外部网络的隔离。
- 在文件底部,我们声明了所有用到的命名数据卷 (
第三步:配置 Nginx 并获取 SSL 证书
现在,我们需要先创建一个简单的 Nginx 配置,仅用于通过 Let’s Encrypt 的 HTTP-01 质询。
在 nginx-conf 目录下创建 nginx.conf 文件:
nano nginx-conf/nginx.conf
填入以下内容,记得替换域名:
# ~/wordpress_site/nginx-conf/nginx.conf
server {
listen 80;
server_name your_domain.com www.your_domain.com;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
}
这个配置非常简单,它只监听 80 端口,并正确处理 Certbot 验证所需的请求。
启动容器并获取测试证书
万事俱备,我们来启动除了 certbot 之外的所有服务:
docker-compose up -d --build db wordpress webserver
然后,单独运行 certbot 服务来获取测试证书:
docker-compose run --rm certbot
如果一切顺利,你应该能看到成功获取证书的提示。你可以通过查看 certbot-etc 数据卷的内容来确认:
sudo ls -l /var/lib/docker/volumes/wordpress_site_certbot-etc/_data/live
看到你的域名文件夹就代表成功了。
获取生产证书
测试成功后,我们来获取正式的生产证书。修改 docker-compose.yml 文件,把 certbot 服务里的 command 中的 --staging 标志去掉。
# ... (部分配置)
certbot:
# ...
command: certonly --webroot --webroot-path=/var/www/html --email your_email@example.com --agree-tos --no-eff-email -d your_domain.com -d www.your_domain.com
然后再次运行 certbot 服务:
docker-compose run --rm certbot
现在,你就拥有了正式的 SSL 证书。
第四步:启用 HTTPS 并强化安全
有了证书,我们就可以更新 Nginx 配置,全面启用 HTTPS。
用下面的内容覆盖 nginx-conf/nginx.conf 文件:
# ~/wordpress_site/nginx-conf/nginx.conf
server {
listen 80;
server_name your_domain.com www.your_domain.com;
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/html;
}
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
server {
listen 443 ssl http2;
server_name your_domain.com www.your_domain.com;
root /var/www/html;
index index.php;
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
# 推荐的安全配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
location / {
try_files $uri $uri/ /index.php?$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;
}
}
这个配置做了几件事:
- 保留了 80 端口的
server块,但将所有普通 HTTP 请求永久重定向到 HTTPS。 - 新增了一个监听 443 端口的
server块,启用了 SSL 和 HTTP/2。 - 指定了 SSL 证书和私钥的路径。
- 配置了 PHP-FPM 的处理逻辑,将
.php请求转发给wordpress服务的 9000 端口。
保存配置后,重新加载 Nginx 服务使之生效:
docker-compose restart webserver
第五步:完成 WordPress 网页安装
现在,在你的浏览器中访问 https://your_domain.com。你应该能看到 WordPress 的安装界面了。按照提示选择语言、设置站点标题、管理员用户名和密码,即可完成安装。
第六步:设置证书自动续期
Let’s Encrypt 证书有效期为 90 天,我们需要让它自动续期。最简单的方法是创建一个 cron 任务。
先创建一个续期脚本 ssl_renew.sh:
nano ssl_renew.sh
写入以下内容:
#!/bin/bash
# 切换到你的项目目录
cd /home/your_user/wordpress_site/
# 运行 certbot renew 命令
docker-compose run --rm certbot renew
# 重启 webserver 以加载新证书
docker-compose restart webserver
给它执行权限:
chmod +x ssl_renew.sh
然后编辑 root 用户的 crontab:
sudo crontab -e
在文件末尾添加一行,让脚本在每个月的 1 号凌晨 3:30 运行:
30 3 1 * * /home/your_user/wordpress_site/ssl_renew.sh > /var/log/cron.log 2>&1
这个脚本会定期运行,检查你的证书是否快要过期,如果是,就自动续期,然后从新加载 Nginx 配置。这样就一劳永逸了。
总结
至此,你已经成功地用 Docker Compose 搭建了一个功能完善、安全可靠且易于维护的 WordPress 网站。这套配置不仅能跑 WordPress,稍作修改就能用于部署其他任何基于 PHP 和 MySQL 的应用。
Docker Compose 的强大之处就在于这种声明式的、可复用的部署方式,希望这次实践能给你在未来的项目中带来一些启发。
关于
关注我获取更多资讯