目录

用 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_PASSWORDMySQL 镜像首次启动(文件夹为空)时,自动创建数据库和账号
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/mysqlMySQL 数据保存在 Volume 中
wp_data:/var/www/htmlWordPress 程序、插件、主题和上传的媒体文件保存在 Volume 中
profiles: [tools]phpMyAdmin 默认不启动,只有添加 --profile tools 才会启动
127.0.0.1:8081:80phpMyAdmin 只绑定本机,外部无法连接

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)。

接下来填写网站信息:

WordPress 安装界面:填写网站标题、用户名、密码和 Email
安装界面:Site Title、Username、Password、Your Email,最后点击 Install WordPress
字段说明
Site Title网站标题,之后可以在后台修改
Username管理员账号。不要使用 admin,这个名称容易被猜到(本示例仅用于演示)
Password管理员密码,WordPress 会显示密码强度
Your Email管理员 Email,用于接收通知和重置密码
Search engine visibility勾选后会要求搜索引擎不要收录网站;网站仍在测试时可以勾选

这里不会出现数据库设置界面,因为 WORDPRESS_DB_* 环境变量已经提供了连接信息,镜像启动时会自动生成 wp-config.php。

点击 Install WordPress 后,看到 Success 界面就表示安装完成:

WordPress 安装成功界面
安装成功,点击 Log In 前往登录页面
WordPress 登录页面
登录页面 http://localhost:8080/wp-login.php

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

WordPress 7.1.3 管理后台
WordPress 管理后台(Dashboard)

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

WordPress 网站前台
网站前台(登录状态下,顶部会显示管理工具栏)

确认上传大小限制

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

WordPress 上传页面显示 Maximum upload file size: 64 MB
Upload Media 页面下方显示上限为 64 MB

如果仍然显示 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:

phpMyAdmin 登录界面
phpMyAdmin 登录界面,服务器已由 PMA_HOST 指定为 db

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

phpMyAdmin 显示 wordpress 数据库中的数据表
wordpress 数据库中的数据表

phpMyAdmin 的端口绑定到 127.0.0.1,只有本机可以连接。如果使用远程服务器,请通过 SSH 通道(ssh -L 8081:127.0.0.1:8081 用户名@服务器)连接,不要将它开放到公网。用完后可以只停止它:

docker compose --profile tools stop phpmyadmin

数据存放在哪里

Volume内容
wordpress_db_dataMySQL 数据库:文章、页面、设置、用户、评论
wordpress_wp_dataWordPress 程序、主题、插件、上传的媒体文件(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日