从手动设置到一键部署:我的 Docker 化 WordPress 之旅

发布: (2025年12月26日 GMT+8 16:11)
14 分钟阅读
原文: Dev.to

Source: Dev.to

从手动搭建到一键部署:我的 WordPress Docker 化之旅

在这篇文章中,我想分享一下我把 WordPress 从传统的手动安装过程迁移到使用 Docker 的完整流程。通过一步步的实验,我最终实现了只需要一条命令就能启动完整的 WordPress 环境的目标。


目录

  1. 手动搭建的痛点
  2. Docker 基础概念回顾
  3. 构建 Docker 镜像
  4. 使用 docker-compose 编排服务
  5. 一键部署脚本
  6. 常见问题与调试技巧
  7. 结语

手动搭建的痛点

在本地或服务器上手动安装 WordPress 时,我经常会遇到以下几个问题:

  • 环境不一致:不同机器的 PHP、MySQL 版本不统一,导致代码在本地跑得好,在生产环境报错。
  • 依赖管理繁琐:每次升级插件或主题,都需要手动检查兼容性。
  • 迁移成本高:从开发环境迁移到生产环境,需要导出数据库、拷贝文件、重新配置 wp-config.php,过程容易出错。

这些痛点促使我去寻找一种更 可重复、可移植 的解决方案。


Docker 基础概念回顾

  • 镜像(Image):只读的模板,用来创建容器。
  • 容器(Container):镜像的运行实例,拥有自己的文件系统、网络和进程空间。
  • Dockerfile:定义如何构建镜像的脚本。
  • docker-compose:用 YAML 文件描述多容器应用的部署方式,能够一次性启动所有相关服务(如 WordPress、MySQL、phpMyAdmin 等)。

构建 Docker 镜像

下面的 Dockerfile 基于官方的 wordpress:php8.2-apache 镜像,加入了一些自定义插件和主题。

FROM wordpress:php8.2-apache

# 安装必要的系统依赖
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd

# 拷贝自定义插件和主题
COPY ./plugins /var/www/html/wp-content/plugins
COPY ./themes  /var/www/html/wp-content/themes

# 设置文件权限
RUN chown -R www-data:www-data /var/www/html/wp-content

EXPOSE 80

提示:如果你只想使用官方镜像的默认插件和主题,可以省略 COPY 步骤。

构建镜像的命令:

docker build -t my-wordpress:latest .

使用 docker-compose 编排服务

下面的 docker-compose.yml 定义了 WordPressMySQLphpMyAdmin 三个服务。所有服务都在同一个自定义网络 wpnet 中,便于相互通信。

version: "3.9"

services:
  wordpress:
    image: my-wordpress:latest
    container_name: wp_app
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wp_user
      WORDPRESS_DB_PASSWORD: secretpassword
      WORDPRESS_DB_NAME: wp_database
    volumes:
      - ./wp-data:/var/www/html
    depends_on:
      - db
    networks:
      - wpnet

  db:
    image: mysql:8.0
    container_name: wp_db
    environment:
      MYSQL_DATABASE: wp_database
      MYSQL_USER: wp_user
      MYSQL_PASSWORD: secretpassword
      MYSQL_ROOT_PASSWORD: rootsecret
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - wpnet

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: wp_phpmyadmin
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: rootsecret
    ports:
      - "8081:80"
    depends_on:
      - db
    networks:
      - wpnet

networks:
  wpnet:

volumes:
  db_data:

注意volumes 用于持久化数据,确保容器重启后数据库和 WordPress 文件仍然保留。

启动所有服务:

docker-compose up -d

此时,访问 http://localhost:8080 即可看到 WordPress 安装向导,http://localhost:8081 则是 phpMyAdmin 的登录页面。


一键部署脚本

为了进一步简化部署,我把构建镜像、拉取依赖、启动容器的步骤封装进了一个 Bash 脚本 deploy.sh

#!/usr/bin/env bash

set -e

# 1. 构建自定义 WordPress 镜像
echo "🔧 正在构建 WordPress 镜像..."
docker build -t my-wordpress:latest .

# 2. 拉取所需的官方镜像(如果本地不存在)
echo "📦 拉取 MySQL 与 phpMyAdmin 官方镜像..."
docker pull mysql:8.0
docker pull phpmyadmin/phpmyadmin

# 3. 启动 compose
echo "🚀 启动 Docker Compose..."
docker-compose up -d

# 4. 打印访问地址
echo "✅ 部署完成!"
echo "WordPress: http://localhost:8080"
echo "phpMyAdmin: http://localhost:8081"

使用方法:

chmod +x deploy.sh
./deploy.sh

只要运行一次脚本,整个 WordPress 环境就会在几秒钟内准备好。


常见问题与调试技巧

问题可能原因解决方案
容器启动后 502 错误WordPress 容器未能连接到 MySQL检查 WORDPRESS_DB_HOST 是否正确(应为 db),并确保 db 服务已健康启动(docker logs wp_db
数据库初始化失败MySQL 环境变量拼写错误或密码不匹配重新检查 MYSQL_DATABASEMYSQL_USERMYSQL_PASSWORDWORDPRESS_DB_* 系列变量
插件/主题未生效挂载卷覆盖了容器内的插件目录确认 ./plugins./themes 路径下的文件结构正确,且卷映射没有冲突
容器频繁重启端口冲突或资源不足使用 docker ps -a 查看容器状态,检查宿主机的端口占用情况,或在 docker-compose.yml 中添加 restart: unless-stopped

调试技巧

  • docker-compose logs -f 实时查看所有服务日志。
  • docker exec -it wp_app bash 进入 WordPress 容器内部,手动检查文件权限或运行 wp-cli
  • 使用 docker-compose down -v 完全清除卷后重新部署,确保没有残留的旧数据。

结语

通过 Docker,我成功把原本需要 手动配置、繁琐迁移 的 WordPress 开发流程,转变为 一键部署、环境一致 的现代化工作流。下面是我在实际项目中得到的几条体会:

  1. 镜像层次化:把公共依赖(如 PHP、Apache)放在基础镜像,业务代码放在上层,能够显著加快后续构建速度。
  2. 持久化卷:一定要为数据库和 WordPress 内容使用卷,否则容器重启会导致数据丢失。
  3. 版本锁定:在 docker-compose.yml 中明确指定镜像标签(如 mysql:8.0),防止意外升级导致兼容性问题。
  4. CI/CD 集成:将 docker builddocker-compose up 脚本写进 CI 流水线,能够实现自动化部署,进一步提升交付效率。

如果你也在考虑把传统的 WordPress 项目迁移到容器化环境,希望这篇文章能为你提供一个清晰的参考路径。祝你玩得开心,部署顺利!


本文版权归原作者所有,转载请注明出处。

项目背后的“原因”

作为一名正在转向 DevOps 的人,我很快意识到,真正的学习是通过动手构建实现的,而不是仅仅观看教程。虽然我之前已经使用手动 SSH 命令和 Ansible Playbook 搭建过 WordPress,但我一直听说容器化是 DevOps 的基础技能。于是,我决定通过完成 Project 1(在我的 30 项 DevOps 路线图中)来弥补这一差距:将完整的 WordPress LEMP 堆栈容器化。

本文记录了我的实战过程、遇到的挑战以及在此过程中学到的关键概念。

我构建的内容

我创建了一个类似生产环境的 WordPress 环境,只需一条命令即可启动:

docker-compose up -d

该命令会启动两个容器:

  • MySQL 8.4 – 数据库
  • WordPress(PHP 8.3)– 应用程序

整个基础设施都定义在 docker-compose.yml 文件中——实践中的基础设施即代码。

架构:简单但强大

用户浏览器 → localhost:8080 → WordPress 容器 → MySQL 容器 (db:3306)

docker-compose.yml

services:
  db:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql

  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    depends_on:
      - db
    volumes:
      - wp_data:/var/www/html

volumes:
  db_data:
  wp_data:

关键挑战与解决方案

挑战 1 – 数据库连接问题

  • 问题: WordPress 安装失败,出现 “database connection error”。
  • 解决方案: 容器之间通过 service names(服务名称)通信,而不是 localhost。使用 db(服务名称)作为数据库主机即可解决此问题。

挑战 2 – macOS 上的端口冲突

  • 问题: 端口 80 已被占用。
  • 解决方案: 在 compose 文件中将端口映射改为 "8080:80"

挑战 3 – GitHub 认证错误

  • 问题: 因密码认证已被弃用,无法推送代码。
  • 解决方案: 生成 GitHub 个人访问令牌(Personal Access Token),并在 CLI Git 操作中使用该令牌。

这个项目教会我的东西

  1. 基础设施即代码 (IaC) 不只是流行词
    在 YAML 文件中定义整个堆栈的感觉颇为革命性。这个单一文件可以:

    • 进行版本控制
    • 与团队成员共享
    • 在任何地方部署相同的环境
    • 充当文档
  2. 容器网络在你理解后就像魔法一样
    wordpress 容器可以通过使用服务名称(db:3306)直接连接到 db 容器。Docker 会创建一个虚拟网络,使容器能够通过名称相互发现。

  3. 开发‑生产环境的一致性是可以实现的
    相同的环境可以运行在:

    • 我的本地 MacBook
    • AWS EC2 实例
    • CI/CD 流水线
    • 任意开发者的机器

    再也没有 “在我机器上可以工作” 的问题!

  4. 公开学习有其好处
    在 GitHub 上记录这段旅程并撰写本文巩固了我的理解。完整代码可在此获取,供任何人参考或基于此构建。

对比:Docker 前后

方面手动/Ansible 设置Docker 化设置
设置时间15–20 分钟30 秒
可复现性环境依赖保证一致性
学习曲线初期较低较陡但更有价值
可移植性服务器特定在任何支持 Docker 的地方运行
扩展性手动干预添加更多容器

我遵循的核心命令

操作命令
启动所有服务docker-compose up -d
检查状态docker-compose ps
查看日志docker-compose logs -f
停止所有服务docker-compose down
停止并删除卷(全新环境)docker-compose down -v
访问 MySQL shelldocker-compose exec db mysql -u root -p

初学者指南:我推荐的学习路径

  • 从官方 Docker Getting Started 教程开始 – 增强信心。
  • 先将简单的东西容器化(例如,一个静态网站),再去处理数据库。
  • 尽早使用 Docker Compose – 它简化了多容器应用。
  • 不要害怕 docker-compose down -v – 重新开始常能解决问题。
  • 仔细阅读错误信息 – 它们通常很有帮助。

我的旅程下一步

  • 添加 Nginx 作为反向代理,以提升性能并实现 SSL 终止。
  • 正确实现 持久化存储,用于上传和主题。
  • 使用 Prometheus/Grafana 容器添加 监控
  • 创建 CI/CD 流水线,自动构建和部署镜像。
  • 将其转换为 Kubernetes 清单,学习编排。

最后感想

将 WordPress Docker 化从一项令人生畏的任务,变成了一项赋能的技能。最初对网络和配置的挫败感,随着我领悟到容器的强大而转为兴奋。

最有价值的经验并非关于 Docker 本身,而是关于 DevOps 思维方式:自动化一切,彻底记录,构建可复现的系统

给所有正在学习的朋友们:开始动手吧。你的第一个项目不必完美,只要完成即可。随后写下来,分享出去,然后继续下一个项目。

对我帮助最大的资源

与我联系

Back to Blog

相关文章

阅读更多 »