Laravel Docker生产最小可行配置关键在于控制变量:PHP-FPM用www-data非root用户;Nginx与PHP-FPM必须同自定义网络且fastcgi_pass指向php-fpm:9000;数据库healthcheck需带timeout和service_healthy依赖;.env严禁COPY进镜像,必须运行时注入;storage等目录须用命名卷或预设UID 82权限。

直接上生产环境能跑通的最小可行配置,不绕弯、不炫技。Laravel + Docker 能稳住的关键不是堆功能,而是控制变量:PHP-FPM 用非 root 用户、Nginx 和 PHP-FPM 网络互通、数据库健康检查必须生效、.env 不进镜像。
docker-compose.prod.yaml 里 database 的 healthcheck 为什么总失败
PostgreSQL 容器启动快,但 pg_isready 检查失败,常见于未等数据库初始化完成就执行检查。
- 确保
POSTGRES_DB、POSTGRES_USER、POSTGRES_PASSWORD全部通过environment注入,不能只靠默认值 -
healthcheck.test改成带超时和重试的写法:["CMD-SHELL", "timeout 5s pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE} || exit 1"] - 在
app服务加depends_on.database.condition: service_healthy,别只写service_started - 如果用 MySQL,对应换成
mysqladmin ping -h localhost -u ${DB_USERNAME} -p${DB_PASSWORD} --silent
PHP-FPM 镜像体积大、启动慢,怎么精简
基础镜像 php:8.4-fpm 默认含大量构建工具和调试组件,生产环境不需要。
- 必须用多阶段构建:第一阶段装
composer和扩展,第二阶段只 COPY/var/www和配置 - 禁用 dev-only 扩展,比如
opcache在生产必须开,但xdebug或pcov必须删掉 -
composer install加--no-dev --optimize-autoloader --classmap-authoritative - 最终镜像里运行用户设为
www-data,且WORKDIR和storage目录权限提前 chown,避免容器启动时改权限失败
Nginx 报 502 Bad Gateway,但 php-fpm 容器显示 running
这不是 PHP 挂了,是 Nginx 根本连不上 PHP-FPM 进程 —— 网络或路径错位。
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- 确认 Nginx 配置里
fastcgi_pass指向的是php-fpm:9000(不是localhost:9000或127.0.0.1:9000) - 确认两个服务在同一个自定义网络(
networks下声明并共用),不要依赖默认 bridge - 检查 PHP-FPM 的
www.conf:必须有listen = 9000(TCP)或listen = /run/php/php-fpm.sock(Unix socket);若用 socket,Nginx 的fastcgi_pass得配unix:/run/php/php-fpm.sock,且 volume 要同步挂载该路径 - 进 Nginx 容器执行
telnet php-fpm 9000,不通就说明网络或端口没暴露对
storage/logs 和 storage/framework/cache 权限被拒绝
容器内 www-data 用户无法写宿主机挂载卷,尤其在 macOS 或 Windows 上更明显。
- 不要用
./storage:/var/www/html/storage这种相对路径挂载,改用命名卷:storage-volume:/var/www/html/storage,并在volumes下声明 - 若必须绑定宿主机目录,先在宿主机运行:
mkdir -p storage && sudo chown -R 82:82 storage(82 是 www-data UID,可通过docker exec app id -u www-data查) - 在 PHP-FPM Dockerfile 末尾加:
RUN mkdir -p /var/www/html/storage/logs /var/www/html/storage/framework/{cache,views,sessions} && chown -R www-data:www-data /var/www/html/storage - 避免在容器启动后用
artisan storage:link修改权限,它不解决挂载卷的 UID/GID 映射问题
最常被跳过的点:.env 文件必须由宿主机提供,不能 COPY 进镜像;APP_KEY 必须在第一次启动前生成并写入,否则 artisan migrate 会卡住;所有敏感配置走 environment + .env,别硬编码进 YAML 或 Dockerfile。










