选php:8.2-fpm镜像最稳妥,需配nginx;装扩展后必须docker-php-ext-enable并确认conf.d路径,挂载代码时注意www-data用户uid匹配,容器间通信用服务名而非localhost。

php:8.2-fpm 容器再补细节。
怎么选 PHP 基础镜像才不踩坑
官方镜像分三类,选错会导致扩展装不上、命令找不到、甚至容器启动就退出:
-
php:8.2-cli:适合命令行脚本(如 cron、artisan),但没内置 web 服务,php -S可临时用,别用于生产 -
php:8.2-fpm:FPM 模式,必须配 Nginx/Apache 才能处理 HTTP 请求;扩展安装最稳定,推荐大多数 Web 项目 -
php:8.2-apache:自带 Apache,开箱即用,但镜像体积大、调试难、不易对接外部 Nginx - Alpine 镜像(如
php:8.2-fpm-alpine):体积小,但很多扩展要手动编译(比如gd需装libpng-dev和jpeg-dev),新手慎用
验证是否选对:运行容器后执行 docker exec -it my-php php -v 看版本,再跑 php -m | grep pdo 确认扩展真加载了——光 RUN 安装不等于启用。
为什么 docker-php-ext-install 装完扩展却没生效
常见现象是 phpinfo() 里看不到扩展,或报 Class 'PDO' not found。根本原因不是命令写错,而是漏了两步:
- 扩展源码安装后需显式启用:有些扩展(如
opcache)要额外执行docker-php-ext-enable opcache - FPM 模式下,扩展配置文件得放在
/usr/local/etc/php/conf.d/目录,否则 FPM 进程不读;CLI 模式下路径可能不同 - 装扩展前没装系统依赖:比如
pdo_mysql需libmysqlclient-dev,gd需libpng-dev,缺一个就静默失败 - 构建缓存干扰:改了
RUN docker-php-ext-install后没加--no-cache,Docker 复用旧层,实际没重装
实操建议:每次装扩展后,在 Dockerfile 末尾加一行 RUN php -m,构建日志里能看到真实加载列表,比猜强得多。
如何让本地 PHP 代码实时进容器又不搞乱权限
开发时想改代码立刻生效,但用 COPY . . 构建镜像会打断热更新;用 -v 挂载又常遇到 Permission denied 或 502 Bad Gateway(Nginx 连不上 PHP-FPM)。核心解法是分场景:
- 本地调试:用绑定挂载 + 显式指定用户:
docker run -v $(pwd):/var/www/html -u www-data php:8.2-fpm,避免容器内进程以 root 写文件导致宿主机权限混乱 - CI/CD 构建:坚持
COPY . .+composer install --no-dev,禁用挂载,确保镜像自包含 - 上传目录特殊处理:不要挂载整个
/var/www/html,单独挂载uploads/目录,并在 PHP 中用is_writable()显式检查 - 注意 .env 文件:绝不能 COPY 进镜像,必须用
docker run --env-file .env或docker-compose.yml的env_file字段传入
一个容易被忽略的点:PHP-FPM 容器默认以 www-data 用户运行,而挂载的本地目录在 macOS/Linux 上往往属于当前用户,UID 不匹配就会 403 —— 此时要么改宿主目录 UID,要么在容器里用 usermod 改 www-data UID,后者更安全。
docker-compose.yml 里 PHP 服务连不上 MySQL 怎么快速定位
典型错误是 PHP 报 Connection refused 或超时,不是代码问题,而是网络或启动顺序没对齐:
- 别用
localhost当 MySQL 主机名:在 compose 网络里,服务名就是 DNS 名,PHP 里该写host: mysql(对应services.mysql名) - MySQL 容器启动慢,PHP 容器先启就崩:加
depends_on只控制启动顺序,不等 MySQL ready;必须配合健康检查或启动脚本重试 - 端口暴露误区:MySQL 容器只需
expose: ["3306"],不用ports:;ports是给宿主机连的,内部服务通信走 Docker 网络 - PHP 连接时指定 socket 更可靠:如果 MySQL 也跑在容器里,用
host: mysql+port: 3306,别尝试用/var/run/mysqld/mysqld.sock(路径跨容器无效)
调试命令:进 PHP 容器执行 nc -zv mysql 3306,通了再查 PHP 连接参数;不通就看 MySQL 容器日志 docker logs my-mysql,大概率是初始化没完成或 bind-address 没放开。
php-fpm 就不肯好好干活。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











