📝 Docker 搭建 LNMP(Nginx+PHP+MySQL)完整踩坑实录
(从报错不断到彻底跑通,新手可直接复刻)
一、前言(我遇到的情况)
本地 Docker 环境一切正常,
放到服务器 + 宝塔面板环境后,疯狂报错:
- apt-get 安装依赖失败(exit code: 100)
- iptables 网络错误
- 3306 端口被占用
- 改了端口依然提示旧端口冲突
- 反复 502 Bad Gateway
- Nginx 连不上 PHP
最终全部解决,跑通 Nginx + PHP + MySQL。
二、最终成功架构(一定要先懂)
三个服务 = 三个独立容器
- my-nginx:负责网页访问、转发 PHP
- my-php:负责解析 PHP 代码
- my-mysql:负责数据库
容器之间通信:
靠 Docker 内网 + 容器名,不是靠宿主机端口。
三、全程遇到的坑 + 解决方案(按出现顺序)
🔴 坑1:构建 PHP 镜像时 apt-get install 失败
报错
Temporary failure resolving 'deb.debian.org'
exit code: 100
原因
服务器网络限制,容器内无法访问 Debian 软件源。
解决方案
不自己构建 PHP 镜像!
直接用官方预制镜像:php:8.2-fpm-alpine
🔴 坑2:Docker 网络创建失败(iptables 错误)
报错
Failed to Setup IP tables: Unable to enable SKIP DNAT rule
原因
宝塔防火墙 / 系统防火墙拦截 Docker 网络。
解决方案
bash
systemctl restart docker
🔴 坑3:3306 端口被宝塔 MySQL 占用
报错
bind: address already in use
原因
宝塔自带 MySQL 占用 3306。
解决方案
映射端口改成 3307:3306
yaml
ports:
- "3307:3306"
🔴 坑4:改了端口不生效,依然报 3306 占用
原因
Docker 复用旧容器配置,没有重建。
解决方案
先删旧容器,再启动:
bash
docker rm -f my-mysql
docker compose up -d
🔴 坑5:502 Bad Gateway(最折磨)
现象
Nginx 能访问,但 PHP 无法连接。
根本原因(99% 人中招)
- Nginx 配置里容器名写错
php:9000→ 应该是my-php:9000 - PHP-FPM 没真正启动
- 启动时序问题(Nginx 比 PHP 先启动)
最终正确 Nginx 配置
nginx
location ~ \.php$ {
fastcgi_pass my-php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
四、最终可直接跑通的 docker-compose.yml
yaml
services:
nginx:
image: nginx:latest
container_name: my-nginx
ports:
- "8081:80"
volumes:
- ./www:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
restart: always
php:
image: php:8.2-fpm-alpine
container_name: my-php
volumes:
- ./www:/var/www/html
depends_on:
- mysql
restart: always
command: >
sh -c "chmod -R 777 /var/www/html && php-fpm"
mysql:
image: mysql:8.0
container_name: my-mysql
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: my_demo_db
volumes:
- mysql-data:/var/lib/mysql
restart: always
volumes:
mysql-data:
五、最常用命令(必须收藏)
进入容器
bash
docker exec -it my-php sh
docker exec -it my-nginx sh
重启服务
bash
docker restart my-php
docker restart my-nginx
看日志(排查 502 神器)
bash
docker logs my-php
彻底重建环境
bash
docker compose down -v
docker compose up -d
六、关键理解(新手必看)
- 容器之间互相访问用容器名
my-nginx → my-php:9000 - 宿主机端口 和 容器内端口是两回事
3307(外部) → 3306(容器内部) - 502 一律排查:
- PHP 是否真的启动
- Nginx 配置容器名是否正确
- 文件路径是否挂载正确
七、总结(一句话记住)
服务器 + 宝塔环境跑 Docker:
- 别自己构建 PHP 镜像
- 端口冲突就换端口
- 502 先看容器名 + PHP 日志
- 容器之间靠名字通信
按这套流程,100% 能跑通!