
本文教你如何在 20 分钟内用一份 docker-compose.yml 把 Apache、MySQL、PHP 三件套部署成可一键启停的容器栈,并保证数据持久、网络隔离、版本可控。读完本文你会得到三件可直接落地的产出:第一,一份适配 PHP 8.2 与 MySQL 8.0 的最小可用模板,能在 Ubuntu 22.04 与 Debian 12 上原样运行;第二,覆盖目录挂载、网络隔离、数据持久化的完整解释,让团队成员理解每一行配置存在的理由;第三,一组针对端口冲突、权限错误、字符集乱码的排错清单,让团队在新机器上 5 分钟完成环境复刻并节省大量重复沟通成本。
一、为什么用 Docker Compose LAMP 跑开发环境
如何在多台开发机与生产服务器之间保持 PHP 版本一致,并把 MySQL 数据目录与 Apache 站点配置都纳入版本管理,是很多团队迈向容器化时面对的第一个问题。传统的 apt 安装方式存在三个痛点:版本漂移、环境耦合、回滚困难。一台机器装 PHP 8.1,另一台装 PHP 8.2,跨版本的语法差异会让线上出现莫名其妙的 500 错误。Docker Compose LAMP 模式把这三件套封装成可声明的 YAML 文件,解决了一致性与可移植性,整套环境进入 Git 仓库后就具备了完整的版本历史。
在做技术选型时建议先评估两件事:一是宿主机内核版本是否支持当前 Docker 引擎(建议 Linux 内核 4.x 以上),二是磁盘 I/O 是否足够支撑 MySQL 容器化运行。如果你正在评估底层云资源,可以参考云服务器选购指南中的 IOPS 与带宽(指网络出口的数据传输速率,单位 Mbps)部分。云服务器(即通过虚拟化技术从物理服务器集群中切分出来的弹性计算资源)的选型直接决定容器栈的运行体验,尤其是数据库容器在高并发写入时对随机 I/O 的依赖很高,机械盘与 SSD 之间的差距会在压测阶段被放大数十倍。
二、最小可用 docker-compose.yml 模板
下面这份模板覆盖三个服务:Apache + PHP 合并镜像、MySQL 8.0、phpMyAdmin。核心配置项要点:
- image:固定到精确小版本,避免 latest 漂移
- volumes:把 PHP 代码、Apache 配置、MySQL 数据三类目录挂出到宿主机
- networks:用一个内部 bridge 网络隔离三个服务
- environment:MySQL 密码、字符集、时区写进 .env 文件
- restart:生产环境建议 unless-stopped
将文件保存为 docker-compose.yml,与之同级建立 src 目录放 PHP 代码、conf 目录放 Apache 配置、db_data 目录留给 MySQL 持久化。执行 docker compose up -d 后,宿主机 8080 端口即可访问站点,8081 端口访问 phpMyAdmin。如果需要把这套环境部署到 VPS(Virtual Private Server,虚拟专用服务器,在物理机上通过虚拟化划分的独立实例)上,可以参考美国 VPS 部署教程里的 SSH 与端口放行步骤。建议把 .env 文件加入 .gitignore,避免数据库密码意外提交到代码仓库。Hostease 美国 VPS 在内核版本与磁盘配置上都满足这类容器场景的要求。
三、目录映射与数据持久化要点
容器一旦销毁,内部文件系统会一并消失,这是初次接触 Docker 的开发者最容易踩的坑。正确做法是把三类需要长期保存的目录挂出到宿主机:
- 源码目录:宿主机 ./src 映射到容器 /var/www/html,编辑器直接改宿主机文件即可热更新
- 数据库数据:宿主机 ./db_data 映射到容器 /var/lib/mysql,重启容器不丢数据
- 配置文件:宿主机 ./conf/apache.conf 映射到容器 /etc/apache2/sites-enabled/000-default.conf
- 日志目录:宿主机 ./logs 映射到容器 /var/log/apache2,便于排错
- 上传目录:单独挂载到独立 volume,避免和源码混淆
字符集是另一个常见踩坑点。MySQL 8.0 默认 utf8mb4 与 utf8mb4_0900_ai_ci,但应用层如果显式声明了旧版 utf8 会出现部分中文写入异常。建议在 my.cnf 中显式声明 collation_server 与 character_set_server,并在 PHP 连接串里加 charset=utf8mb4,从源头消除编码不一致。备份策略也要尽早规划,可以用 docker exec 调 mysqldump 把数据库导出到宿主机的 backup 目录,再配合宿主机层面的定时任务做异地复制。
四、常见排错清单与下一步建议
在新机器上跑这套模板时,最常见的失败有四类。第一类是端口冲突,宿主机 80 或 3306 已被占用,解决方案是把 ports 映射改为 8080:80 与 3307:3306。第二类是 MySQL 数据目录权限错误,提示 chown 失败,处理方式是删掉 db_data 后让首次启动重建。第三类是 PHP 缺少 mysqli 扩展,使用 php:8.2-apache 官方镜像时需要在 Dockerfile 里 docker-php-ext-install mysqli,并重新构建镜像。第四类是跨容器解析失败,要确保 PHP 容器与 MySQL 容器在同一个 networks 下,PHP 连接串 host 写 MySQL 服务名而不是 localhost,否则 DNS 解析会指向自己造成连接被拒。
接下来可以考虑三条延伸路径:第一,把 Apache 换成 Nginx + PHP-FPM 拆分镜像,获得更细粒度的资源控制;第二,加入 Redis 容器做对象缓存与 session 共享,提升高并发下的响应速度;第三,把整套 compose 文件接入 CI/CD,每次合并自动构建镜像并推送到私有 registry,做到环境与代码同步演进。如果你需要把开发机的 LAMP 栈无缝迁移到 WordPress 生产环境,建议先看WordPress 香港主机购买指南与WordPress 性能调优实战来对齐生产侧的运行参数。总结来说,Docker Compose 让 LAMP 从”装一遍记一次”变成”一份 YAML 跑到底”,团队协作与版本回滚成本会显著下降,建议你今天就用本文模板在本地复刻一次完整流程,再把可复用的 YAML 沉淀到团队仓库。运维侧也可以围绕这套模板搭建日志聚合与监控告警,例如挂载 Loki 收集 Apache 访问日志,再把 MySQL 的慢查询日志接入统一面板,逐步从能跑起来过渡到出问题能定位。当团队规模超过五个人,建议把镜像构建从开发机迁到 CI 环境,由流水线统一打包并推送,避免每个人本地构建出现的镜像差异问题,让生产部署的可重复性进一步提升。