Docker 搭建 LNMP(Nginx+PHP+MySQL)完整踩坑实录

📝 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% 人中招)

  1. Nginx 配置里容器名写错
    php:9000 → 应该是 my-php:9000
  2. PHP-FPM 没真正启动
  3. 启动时序问题(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

六、关键理解(新手必看)

  1. 容器之间互相访问用容器名
    my-nginx → my-php:9000
  2. 宿主机端口 和 容器内端口是两回事
    3307(外部) → 3306(容器内部)
  3. 502 一律排查:
    • PHP 是否真的启动
    • Nginx 配置容器名是否正确
    • 文件路径是否挂载正确

七、总结(一句话记住)

服务器 + 宝塔环境跑 Docker:

  • 别自己构建 PHP 镜像
  • 端口冲突就换端口
  • 502 先看容器名 + PHP 日志
  • 容器之间靠名字通信

按这套流程,100% 能跑通!

相关推荐
灰阳阳2 小时前
Spring Boot+Nginx+MySQL容器化实战
spring boot·mysql·nginx
人生匆匆2 小时前
配置nginx ssl反向代理tcp端口
tcp/ip·nginx·ssl
zzh0812 小时前
Nginx性能优化与监控笔记
笔记·nginx·性能优化
吾诺2 小时前
springboot整合libreoffice(两种方式,使用本地和远程的libreoffice);docker中同时部署应用和libreoffice
spring boot·后端·docker
weixin_397578022 小时前
Docker 完整介绍
运维·docker·容器
中科三方2 小时前
域名管理常见问题:添加域名解析多久生效?为什么不能马上生效?
开发语言·php
the_fat_bird2 小时前
自存 | VSCode+SSH+Docker远程Python Debugger
vscode·docker·ssh
小璐资源网3 小时前
《Nginx缓存配置:浏览器缓存与服务器缓存实战》
服务器·nginx·缓存
炸炸鱼.3 小时前
Nginx 性能调优与深度监控实战指南
运维·nginx