目录
用 Docker Compose 搭建 WordPress 教程(含 MySQL)
本节用 Docker Compose 搭建一个完整的 WordPress 网站。完成后,你将拥有:
- WordPress(PHP + Apache,官方镜像
wordpress:7-apache) - MySQL 8.4 数据库,并配置健康检查;数据库准备就绪后才启动 WordPress
- 数据保存在 Volume 中,即使删除并重建容器也不会丢失
- 上传文件大小上限调整为 64 MB
- 可按需启动的 phpMyAdmin 管理界面
本节用到的 Compose 语法(depends_on、healthcheck、profiles、.env)已在 Compose 入门 和 docker compose 命令 中介绍过。
创建项目
创建一个名为 wordpress 的文件夹,放入三个文件:
wordpress/
├── compose.yaml
├── .env
└── uploads.ini
.env:密码
MYSQL_ROOT_PASSWORD=change-this-root-password
MYSQL_PASSWORD=change-this-wp-password
请换成你自己的密码。Compose 会自动读取同一文件夹中的 .env,并将 compose.yaml 中的 ${MYSQL_PASSWORD} 等变量替换为这里的值。不要将 .env 提交到 Git。
uploads.ini:上传大小
WordPress 镜像默认的 PHP 上传上限只有 2 MB,上传较大的图片或主题就会失败。可以用一个 ini 文件覆盖该设置:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
官方 PHP 镜像会读取 /usr/local/etc/php/conf.d/ 下的所有 .ini 文件,因此只需将这个文件挂载进去即可。
compose.yaml
services:
db:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
restart: unless-stopped
wordpress:
image: wordpress:7-apache
depends_on:
db:
condition: service_healthy
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- wp_data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
restart: unless-stopped
phpmyadmin:
image: phpmyadmin
depends_on:
- db
ports:
- "127.0.0.1:8081:80"
environment:
PMA_HOST: db
profiles: [tools]
volumes:
db_data:
wp_data:
设置说明:
| 设置 | 作用 |
|---|---|
MYSQL_DATABASE / MYSQL_USER / MYSQL_PASSWORD | MySQL 镜像首次启动(文件夹为空)时,自动创建数据库和账号 |
healthcheck | 每 10 秒用 mysqladmin ping 检查 MySQL 是否可以连接。要写 -h 127.0.0.1,而不是 localhost,否则初始化尚未完成就会被判定为 healthy,原因见 MySQL |
condition: service_healthy | 等 db 变为 healthy 后再启动 WordPress,避免 WordPress 先启动却连不上数据库 |
WORDPRESS_DB_HOST: db | 使用服务名 db 连接,Compose 网络会自动将其解析为 MySQL 容器的 IP |
db_data:/var/lib/mysql | MySQL 数据保存在 Volume 中 |
wp_data:/var/www/html | WordPress 程序、插件、主题和上传的媒体文件保存在 Volume 中 |
profiles: [tools] | phpMyAdmin 默认不启动,只有添加 --profile tools 才会启动 |
127.0.0.1:8081:80 | phpMyAdmin 只绑定本机,外部无法连接 |
WordPress 只会通过 Compose 内部网络访问 MySQL,因此 db 没有设置 ports,不会对外开放。
启动
在 wordpress 文件夹中运行:
$ docker compose up -d
[+] up 32/32
✔ Image wordpress:7-apache Pulled 28.0s
✔ Network wordpress_default Created 0.1s
✔ Volume wordpress_db_data Created 0.0s
✔ Volume wordpress_wp_data Created 0.0s
✔ Container wordpress-db-1 Healthy 11.1s
✔ Container wordpress-wordpress-1 Started 11.3s
注意启动顺序:Compose 先创建网络和两个 Volume,wordpress-db-1 等了 11 秒变为 Healthy 后,wordpress-wordpress-1 才变为 Started,这就是 condition: service_healthy 的效果。首次运行需要下载镜像,因此耗时会更久。
确认状态:
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
wordpress-db-1 mysql:8.4 "docker-entrypoint.s…" db 16 seconds ago Up 16 seconds (healthy) 3306/tcp, 33060/tcp
wordpress-wordpress-1 wordpress:7-apache "docker-entrypoint.s…" wordpress 16 seconds ago Up 5 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
db 的 STATUS 显示 (healthy),而且 PORTS 只有容器内部的 3306/tcp,没有映射到主机;wordpress 则将主机的 8080 端口映射到容器的 80 端口。
两个 Volume 也已创建,名称格式为“项目名称_Volume 名称”,项目名称默认就是文件夹名称:
$ docker volume ls
DRIVER VOLUME NAME
local wordpress_db_data
local wordpress_wp_data
在浏览器中完成安装
打开 http://localhost:8080,第一个界面用于选择语言。在列表中选择你需要的后台语言(例如“简体中文”),然后点击 Continue。为方便与其他语言版本共用截图,本教程选择的是 English (United States)。
接下来填写网站信息:

| 字段 | 说明 |
|---|---|
| Site Title | 网站标题,之后可以在后台修改 |
| Username | 管理员账号。不要使用 admin,这个名称容易被猜到(本示例仅用于演示) |
| Password | 管理员密码,WordPress 会显示密码强度 |
| Your Email | 管理员 Email,用于接收通知和重置密码 |
| Search engine visibility | 勾选后会要求搜索引擎不要收录网站;网站仍在测试时可以勾选 |
这里不会出现数据库设置界面,因为 WORDPRESS_DB_* 环境变量已经提供了连接信息,镜像启动时会自动生成 wp-config.php。
点击 Install WordPress 后,看到 Success 界面就表示安装完成:


http://localhost:8080/wp-login.php使用刚才设置的账号和密码登录,就会进入管理后台。欢迎区域显示的版本是 7.1.3,也就是 wordpress:7-apache 镜像当前包含的版本:

打开前台 http://localhost:8080,现在可以看到默认的 Hello world! 文章:

确认上传大小限制
在后台进入 Media → Add Media File,上传区域下方会显示当前上限。显示 Maximum upload file size: 64 MB,说明 uploads.ini 已生效:

如果仍然显示 2 MB,请检查 uploads.ini 的挂载路径是否正确。修改后需要运行 docker compose up -d 重建容器(restart 不会应用新设置)。
使用 phpMyAdmin 管理数据库(可选)
phpMyAdmin 配置了 profiles: [tools],平常运行 docker compose up -d 不会启动它。需要时添加 --profile tools:
$ docker compose --profile tools up -d phpmyadmin
[+] up 25/25
✔ Image phpmyadmin Pulled 6.3s
✔ Container wordpress-db-1 Running 0.0s
✔ Container wordpress-phpmyadmin-1 Started 0.6s
命令末尾指定了 phpmyadmin,因此只会启动它(以及它依赖的 db,该服务已经在运行)。
打开 http://localhost:8081,Username 填 root,Password 填 .env 中的 MYSQL_ROOT_PASSWORD:

登录后点击左侧的 wordpress 数据库,就能看到 WordPress 创建的 12 张数据表(wp_posts、wp_options、wp_users…):

phpMyAdmin 的端口绑定到 127.0.0.1,只有本机可以连接。如果使用远程服务器,请通过 SSH 通道(ssh -L 8081:127.0.0.1:8081 用户名@服务器)连接,不要将它开放到公网。用完后可以只停止它:
docker compose --profile tools stop phpmyadmin
数据存放在哪里
| Volume | 内容 |
|---|---|
wordpress_db_data | MySQL 数据库:文章、页面、设置、用户、评论 |
wordpress_wp_data | WordPress 程序、主题、插件、上传的媒体文件(wp-content/uploads) |
两个都需要备份,缺少任何一个都无法完整恢复网站。
备份
在项目文件夹中运行。第一步用 mysqldump 导出数据库,第二步用临时的 alpine 容器将 wp_data Volume 打包成 tar.gz:
$ docker compose exec -T db sh -c 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" wordpress' > wordpress.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
$ ls -lh wordpress.sql && head -n 5 wordpress.sql
-rw-r--r-- 1 root root 880.8K Oct 13 00:22 wordpress.sql
-- MySQL dump 10.13 Distrib 8.4.11, for Linux (x86_64)
--
-- Host: localhost Database: wordpress
-- ------------------------------------------------------
-- Server version 8.4.11
$ docker run --rm -v "$(basename "$PWD")_wp_data:/data:ro" -v "$PWD:/backup" alpine:3.23 tar czf /backup/wp_data.tar.gz -C /data .
$ ls -lh wp_data.tar.gz
-rw-r--r-- 1 root root 33.9M Oct 13 00:22 wp_data.tar.gz
说明:
exec -T:关闭 TTY,这样输出才能正确地用>重定向到文件。sh -c '... -p"$MYSQL_ROOT_PASSWORD"':使用单引号,让变量在容器内展开(MySQL 容器有这个环境变量),主机无需知道密码。[Warning] Using a password on the command line interface can be insecure.是 MySQL 的提示,写入 stderr,不会混入wordpress.sql,可以忽略。wordpress.sql开头是MySQL dump … Distrib 8.4.11,表示导出成功。$(basename "$PWD")_wp_data会组成 Volume 名称wordpress_wp_data。如果你的文件夹名称不同,请用docker volume ls确认。:ro表示只读挂载,备份过程不会修改数据。
将 wordpress.sql 和 wp_data.tar.gz 复制到其他机器或云存储中,才算完成真正的备份。
Windows 用户备份
PowerShell 不支持 <,Windows PowerShell 5.1 的 > 会将 SQL 文件存为 UTF-16。可以改为在容器内生成文件,再用 docker compose cp 复制出来;打包 wp_data 时直接写出 Volume 名称(默认是 文件夹名称_wp_data):
docker compose exec db sh -c 'mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --result-file=/tmp/wordpress.sql wordpress'
docker compose cp db:/tmp/wordpress.sql wordpress.sql
docker run --rm -v wordpress_wp_data:/data:ro -v "$(pwd):/backup" alpine:3.23 tar czf /backup/wp_data.tar.gz -C /data .
docker compose exec db sh -c 'mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --result-file=/tmp/wordpress.sql wordpress'
docker compose cp db:/tmp/wordpress.sql wordpress.sql
docker run --rm -v wordpress_wp_data:/data:ro -v "${PWD}:/backup" alpine:3.23 tar czf /backup/wp_data.tar.gz -C /data .
docker compose exec db sh -c "mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --result-file=/tmp/wordpress.sql wordpress"
docker compose cp db:/tmp/wordpress.sql wordpress.sql
docker run --rm -v wordpress_wp_data:/data:ro -v "%cd%:/backup" alpine:3.23 tar czf /backup/wp_data.tar.gz -C /data .
恢复时反向操作:docker compose cp wordpress.sql db:/tmp/restore.sql,然后运行 docker compose exec db sh -c 'mysql -uroot -p$MYSQL_ROOT_PASSWORD wordpress < /tmp/restore.sql'。tar 的打包和解压都在 alpine 容器内进行,不受 Windows 影响。
恢复
在新机器上(或清空后)放好 compose.yaml、.env、uploads.ini 和两个备份文件,然后:
# 1. 只启动数据库,等它 healthy
docker compose up -d --wait db
# 2. 导入数据库
docker compose exec -T db sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" wordpress' < wordpress.sql
# 3. 将 WordPress 文件恢复到 Volume
docker run --rm \
-v "$(basename "$PWD")_wp_data:/data" \
-v "$PWD:/backup" \
alpine:3.23 sh -c "cd /data && tar xzf /backup/wp_data.tar.gz"
# 4. 启动所有服务
docker compose up -d
--wait 会等待服务变为 healthy 后再返回,避免数据库尚未准备好就开始导入。.env 中的密码必须和备份时相同,因为 wp-config.php(位于 wp_data 中)记录的是旧数据库密码。
更新
可以直接在后台更新 WordPress 核心、主题和插件,文件会写入 wp_data Volume。
要更新镜像本身(PHP、Apache、MySQL 小版本):
$ docker compose pull
[+] pull 2/2
✔ Image wordpress:7-apache Pulled 0.6s
✔ Image mysql:8.4 Pulled 0.7s
$ docker compose up -d
[+] up 2/2
✔ Container wordpress-wordpress-1 Running 0.0s
✔ Container wordpress-db-1 Healthy 0.5s
pull 会下载新版镜像;up -d 只会重建镜像发生变化的容器。上面的示例中镜像没有新版本,因此容器保持 Running 状态。
注意事项:
- 更新前先备份。
wordpress:7-apache会随 7.x 版本更新;如果要固定版本,可以填写完整版本号,例如wordpress:7.1.3-apache。wp_data中已有 WordPress 文件时,镜像不会覆盖这些文件,因此 WordPress 核心版本以后台更新为准。- MySQL 跨大版本升级(例如 8.0 → 8.4)前,请先阅读 MySQL 官方升级说明,不要直接修改标签。
删除整个环境
练习完成后要清理环境,添加 --profile tools 才会连 phpMyAdmin 一并删除;-v 会删除 Volume,网站数据会全部丢失:
$ docker compose --profile tools down -v
[+] down 6/6
✔ Container wordpress-wordpress-1 Removed 1.5s
✔ Container wordpress-phpmyadmin-1 Removed 1.5s
✔ Container wordpress-db-1 Removed 2.3s
✔ Volume wordpress_wp_data Removed 0.3s
✔ Network wordpress_default Removed 0.2s
✔ Volume wordpress_db_data Removed 0.3s
正式上线注意事项
- 在前面加一个反向代理来处理 HTTPS,例如 Nginx、Caddy 或 Traefik,参见 Nginx 静态网站与反向代理。
- 不要用
ports对外开放数据库,也不要将 phpMyAdmin 开放到公网。 - 管理员账号不要使用
admin,密码要足够强。 - 定期自动备份(例如用 cron 运行上面的备份命令),并将备份存到其他机器。
- 不要将
.env提交到 Git。
重点回顾
- 使用 Compose 管理 WordPress 和 MySQL,数据分别保存在
db_data和wp_data两个 Volume 中。 - MySQL 健康检查要使用
-h 127.0.0.1,避免它在初始化期间就被判定为 healthy。 - 将 phpMyAdmin 放在 profile 中,并且只绑定到 127.0.0.1。
- 备份需要同时包含数据库和网站文件,并存放到其他机器。
动手练习
练习 1:用一条命令确认 PHP 的上传上限已经是 64M。
答案
docker compose exec wordpress php -r "echo ini_get('upload_max_filesize');"
输出 64M。
练习 2:要将网站迁移到另一台主机,需要带走哪些文件?
答案
compose.yaml、.env、uploads.ini,以及两份备份:wordpress.sql(数据库)和 wp_data.tar.gz(网站文件)。在新主机上按照本章“恢复”部分的步骤操作。
常见问题
安装界面为什么没有让我填写数据库设置?
WORDPRESS_DB_* 环境变量已经提供了连接信息,镜像启动时会自动生成 wp-config.php。
上传文件时提示超过大小上限怎么办?
WordPress 镜像默认的 PHP 上传上限是 2 MB,可以用本章的 uploads.ini 调整,修改后运行 docker compose up -d 重建容器。
如何在 Windows 上备份?
PowerShell 不支持 <,而且 Windows PowerShell 5.1 的 > 会改变文件编码。本章“备份”一节介绍了在容器内导出,再用 docker cp 复制出来的写法。
更新于 2026年10月14日