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% 能跑通!

相关推荐
Csvn13 小时前
Nginx 配置语法与上下文:一次搞懂继承、变量与用 map 替掉 if
后端·nginx
笑容掩饰我的失落13 小时前
区块链从小白到精通(八):从零实现一个标准 ERC-20 代币(完整可运行代码)
算法·区块链·php·智能合约·哈希算法
wz975417 小时前
Docker 从 systemd 托管容器、overlay2 存储驱动到 Compose 多容器实战
spring cloud·docker·eureka
新*18 小时前
ES 7.17 三节点 Docker 集群接入 IK 自定义词典:一次从丢插件到热更新的完整排障
运维·elasticsearch·docker·中文分词·ik分词
小白的码BUG之路19 小时前
Jenkins -- gitee+docker+harbor+k8s 部署项目
docker·gitee·jenkins
AlfredZhao19 小时前
Docker Compose 平滑切换环境变量文件,容器配置不残留
docker
duansamve1 天前
Python3+Flask+PostgreSQL18+Vue3项目生产环境用docker如何部署?
python·docker·flask
xbzb2 天前
从零容器化部署 ECShop:Harbor 私有仓库 + 自定义 PHP 镜像 + LNMP 三容器
容器·php·harbor·镜像·仓库·ecshop
那明眸似水2 天前
云原生项目三:Docker秒级启动NextCloud个人网盘存储办公系统
linux·运维·docker·云原生·容器
知已难寻2 天前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器