docker nginx php mysql搭建网站
上周帮朋友迁移一个老项目,建网服务器上跑着十几个容器,建网其中nginx和php-fpm分居两个容器,建网mysql单独一个。建网折腾到凌晨两点,建网我突然意识到,建网这套组合拳的建网难点从来不在安装,而在让三个进程互相找到对方。建网
先别急着敲命令。建网你得想清楚一件事:nginx不认php文件,建网它只认fastcgi协议。建网php-fpm才是建网真正执行代码的人。mysql则是建网那个把数据锁在保险柜里的守财奴。三者通过unix socket或tcp端口通信,建网docker compose就是建网那个牵线搭桥的媒婆。
写docker-compose.yml时,我习惯把mysql单独放一个服务,数据卷挂载到宿主机目录。这步偷懒的话,容器一删数据全没,哭都来不及。php-fpm镜像选带扩展的版本,比如php:8.2-fpm,记得把pdo_mysql装进去,否则连不上数据库。nginx配置里最关键的是fastcgi_pass那一行,要指向php-fpm的服务名加端口,比如php-fpm:9000,而不是localhost——在容器网络里,localhost指自己,等于让nginx去敲自家房门找隔壁老王。
有个坑我必须提。很多人把nginx的conf文件直接写在镜像里,改一次要重新build。正确做法是用volume挂载宿主机配置文件,热加载只需docker exec nginx nginx -s reload。php代码同理,挂载到容器里的/var/www/html,改完刷新浏览器就能看到变化,省去打包上传的功夫。
mysql初始化会慢半拍。容器起来后php连不上数据库,别急着改代码,先docker logs mysql看看是否还在跑初始化脚本。我踩过最蠢的坑是忘记设置MYSQL_ROOT_PASSWORD环境变量,结果容器启动失败,日志里报错"Database is uninitialized"。密码别用root,至少换个强点的,毕竟暴露在公网的话,扫描机器人五分钟就能爆破。
调试时用docker compose ps看状态,用docker compose exec进容器里curl一下。nginx报502多半是php-fpm没起来或者端口不通,报504则是php执行超时。有一次我排查半天,最后发现是php-fpm容器里时区没设置,date函数返回UTC时间,导致session验证逻辑全乱。
这套架构跑起来之后,性能瓶颈通常不在docker本身。php-fpm的pm.max_children默认值只适合玩具项目,线上得根据内存调整。nginx的worker_processes设为auto即可,别手贱填数字。mysql的innodb_buffer_pool_size要占物理内存的70%左右,这些调优参数写在配置文件里,比docker run时一堆-e参数干净得多。
最后说个反直觉的事:docker compose up -d之后,别急着测业务。先看日志,等三个容器都进入healthy状态再操作。我用healthcheck指令给mysql加了ping检测,给php加了脚本探测,nginx就检查端口。这套组合拳一旦跑顺,部署新环境就是复制粘贴的事。但记住,docker解决的是环境一致性问题,代码质量还得自己扛。
(责任编辑:百科)














