Docker一键搭建Nginx+PHP+MySQL建站环境

为什么用 Docker 搭 Nginx+PHP+MySQL

如果你需要在服务器上快速跑起一个 PHP 网站,Docker 一键搭建 Nginx+PHP+MySQL 建站环境是目前比较省事的方式。
它把三个服务拆进独立容器,通过 docker-compose 统一管理,不用在宿主机反复装扩展、调版本。
本文面向零基础用户,从零开始给出完整命令和配置文件,照着做就能在浏览器看到 PHP 页面连接 MySQL 的结果。

适合场景:新服务器初始化、本地开发环境复刻、临时测试站点。
最终你会得到一个可通过 http://服务器IP:8080 访问的 PHP 环境,并且 PHP 能正常连接 MySQL。

开始前的准备条件

动手前先确认几件事,避免中途卡住。

  • 一台 Linux 服务器(Ubuntu 20.04+/Debian 11+/CentOS 7+ 均可),建议 2GB 内存以上。
  • 已安装 Docker 和 Docker Compose 插件。检查命令:docker -vdocker compose version
  • 服务器安全组或防火墙放行 8080 端口(本文用 8080 映射 Nginx,避免和宿主机已有 80 端口冲突)。
  • 一个用来存放配置和网站文件的目录,例如 /opt/web

如果 Docker 未安装,可参考官方文档安装,安装后执行 docker run hello-world 能输出欢迎信息即表示正常。

创建目录结构与配置文件

先建好目录,再写 docker-compose.yml。
下面所有操作在 /opt/web 下完成。

mkdir -p /opt/web/{nginx/conf.d,php,www,mysql/data}
cd /opt/web

创建 docker-compose.yml,内容如下:

services:
  nginx:
    image: nginx:stable
    container_name: web-nginx
    ports:
      - "8080:80"
    volumes:
      - ./www:/var/www/html
      - ./nginx/conf.d:/etc/nginx/conf.d
    depends_on:
      - php
    restart: always

  php:
    image: php:8.2-fpm
    container_name: web-php
    volumes:
      - ./www:/var/www/html
    restart: always

  mysql:
    image: mysql:8.0
    container_name: web-mysql
    environment:
      MYSQL_ROOT_PASSWORD: root123456
      MYSQL_DATABASE: testdb
    volumes:
      - ./mysql/data:/var/lib/mysql
    restart: always

注意MYSQL_ROOT_PASSWORD 请改成你自己的强密码,不要直接用于生产。

接着写 Nginx 站点配置 nginx/conf.d/default.conf

server {
    listen 80;
    server_name localhost;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

这里 fastcgi_pass php:9000 中的 php 是 compose 里的服务名,Docker 内部网络会自动解析,不需要写 IP。

启动服务并验证连通性

配置写好后,在 /opt/web 目录执行:

docker compose up -d

查看容器状态:

docker compose ps

三个容器都显示 Up 即表示启动成功。
如果某个容器反复重启,用 docker compose logs 服务名 查看日志,常见原因是端口被占用或 MySQL 数据目录权限问题。

写一个测试文件 www/index.php

connect_error) {
    die('MySQL连接失败: ' . $conn->connect_error);
}
echo 'PHP环境正常,MySQL连接成功';

浏览器访问 http://服务器IP:8080,看到“PHP环境正常,MySQL连接成功”就说明整套环境已经跑通。
如果只显示 PHP 源码,说明 Nginx 没有把请求转给 PHP,重点检查 fastcgi_pass 和 PHP 容器是否在运行。

常见报错与避坑说明

端口 8080 被占用docker compose up -d 会报 bind: address already in use
改 docker-compose.yml 里的端口映射,例如改成 8081:80,再重新执行 docker compose up -d

MySQL 容器启动后马上退出:多半是 ./mysql/data 目录权限或已有旧数据不兼容。
可以先 docker compose down,备份后清空该目录再启动。
官方镜像对数据目录权限有要求,不建议手动改所有权为 root 以外的用户。

PHP 报 “Connection refused”:检查 PHP 代码里连接 MySQL 的主机名是否写成 mysql,不要写 127.0.0.1
在容器网络里,127.0.0.1 指向 PHP 容器自己,不是 MySQL 容器。

修改配置后不生效:Nginx 配置改动后执行 docker compose restart nginx
PHP 代码改动一般即时生效,无需重启。

安全提醒:本文示例暴露了 8080 端口且使用 root 连接数据库,仅适合学习和内网测试。
正式上线建议限制访问来源、单独创建低权限数据库用户,并定期备份 mysql/data 目录。

几个实际使用中的疑问

这套环境能直接用来跑 WordPress 吗? 可以。
把 WordPress 程序放进 www 目录,数据库连接信息填 mysqlroot、你设置的密码即可。
但建议为 WordPress 单独建库和用户,不要长期用 root。

如何进入容器排查问题?docker exec -it web-php bash 进入 PHP 容器,docker exec -it web-mysql mysql -uroot -p 进入 MySQL 命令行。
退出用 exit

数据会丢吗? MySQL 数据通过 ./mysql/data 挂载到宿主机,删除容器不会丢数据。
但执行 docker compose down -v 会删除卷,操作前确认清楚。

宿主机已有 Nginx 怎么办? 两种做法:把 compose 里的端口改成其他端口,或者让宿主机 Nginx 反代到 127.0.0.1:8080
后者更适合已经有域名和证书的场景。

整套 Docker 一键搭建 Nginx+PHP+MySQL 建站环境的核心就是三件事:目录挂载、容器网络服务名互通、端口映射。
把这三处理解清楚,后续加 Redis、改 PHP 版本、配 HTTPS 都只是在这个基础上扩展。

分享到:
上一篇
Docker容器部署CMS网站,环境隔离更省心
下一篇
Docker容器迁移,网站快速搬家到新服务器
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意