
用一串 docker run 搭 LNMP,参数散在终端历史里,换机器得重敲。Docker Compose 把参数固化成一份 YAML,一条命令拉起全套服务。下面给出可直接运行的 compose.yaml,并说明依赖顺序、网络互访与持久化三个易踩的坑。
一、为什么用 Compose 而不是一串 docker run
1. 手动命令的三个问题
用 docker run 逐个启动 nginx、PHP 与 MySQL,网络、端口、挂载参数全写在命令行里,无法版本管理。同事复现只能照抄,漏掉 --network 就因容器名解析失败连不上库;容器重建后 IP 变化,写死的地址会失效。
2. Compose 解决什么
Compose 用一份 YAML 描述所有服务,up -d 按依赖依次创建网络、卷与容器。它自动建立 bridge 网络,服务之间用服务名互访,无需关心 IP,启动前可用 config 校验语法。
二、compose.yaml 的编写要点
1. 服务定义与依赖顺序
四个服务放在同一份文件里。depends_on 只保证启动顺序,不保证 MySQL 已能接受连接,PHP 侧仍需重试;配合 healthcheck 与 service_healthy 才能等到数据库就绪。
services:
mysql:
image: mysql:8.0
environment: {MYSQL_ROOT_PASSWORD: root123, MYSQL_DATABASE: blog}
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
interval: 10s
volumes: [mysql-data:/var/lib/mysql]
php:
image: php:8.2-fpm
depends_on: {mysql: {condition: service_healthy}}
nginx:
image: nginx:1.25
ports: ["8080:80"]
volumes:
mysql-data:
2. 网络与端口暴露
Compose 默认创建 {项目名}_default 网络,容器之间用服务名当主机名,PHP 连库把 host 写成 mysql、连缓存写 redis。只有 nginx 需要 ports 映射到宿主机,MySQL 用 expose 或不暴露以减少攻击面;确需本机连库时,映射绑到回环地址。
三、数据与配置的持久化
1. 命名卷与绑定挂载的选择
容器删除后写入层数据一并丢失,MySQL 数据必须落到命名卷 mysql-data,由 Docker 管理路径与权限。源码与配置属频繁改动的内容,适合绑定挂载到 ./www、./nginx.conf,改完立即生效,无需重建镜像。
2. Nginx 与 PHP 的对接
Nginx 转发 PHP 请求要指向 php 容器的 9000 端口,SCRIPT_FILENAME 必须与容器内路径一致,否则报 File not found。两边都把代码挂到 /var/www/html 最省事。
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include fastcgi_params;
}
关键配置提示
- MySQL 不要直接映射到 0.0.0.0,需要时绑到 127.0.0.1。
- 挂载的 nginx.conf 加
:ro,避免容器内误改宿主机文件。 - 启动后先
docker compose logs mysql确认初始化完成。

快来评论,快来抢沙发吧~