Symfony 6 Docker部署需三步:选php:8.1-apache并装全intl、xml、zip等扩展,启用mod_rewrite,配置APP_ENV=dev时关闭OPCache与时区校准;DATABASE_URL主机名须用服务名db而非localhost;Web服务器仅挂载public目录。

Symfony 6 默认要求 PHP 8.1+,且弃用了 symfony/website-skeleton(已合并进 symfony/skeleton),Docker 配置必须适配新版本的依赖、扩展和运行时约束。直接套用旧教程里的 php:7.4 或未启用 ext-intl/ext-ctype 的镜像会启动失败或报错。
docker-compose.yml 中 php 服务不能直接用 php:8.1-apache
官方 php:8.1-apache 镜像不包含 ext-intl、ext-xml、ext-zip 等 Symfony 6 强制依赖的扩展,容器启动后访问会直接 500,日志里出现类似 Class "Symfony\Component\Intl\Intl" not found 或 Call to undefined function mb_strlen()。
- 必须基于
php:8.1-apache自定义构建,或改用社区维护的带全扩展的镜像(如thecodingmachine/php:8.1-v4-apache) - 若自己构建,
Dockerfile中至少要补全:docker-php-ext-install intl opcache xml zip pdo pdo_mysql -
php:8.1-apache默认禁用mod_rewrite,需显式执行a2enmod rewrite,否则 Symfony 路由 404
APP_ENV=dev 下容器内时区和 OPCache 必须关闭
开发环境若开启 OPCache,会导致 Twig 模板修改不生效、配置变更不热更新;时区不一致则 DateTime 行为异常,尤其在 Doctrine 时间字段处理中易出错。
- 在
php服务的environment下加:PHP_INI_SCAN_DIR=/usr/local/etc/php/conf.d - 挂载自定义
php.ini文件,内容包含:date.timezone = "UTC"、opcache.enable=0、opcache.enable_cli=0 - 不要依赖
docker-compose.yml里写死APP_ENV=dev就万事大吉——Symfony还会读取.env和容器内环境变量,三者冲突时以.env为准,建议删掉.env里的APP_ENV=prod并统一用 compose 控制
数据库主机名不能写 localhost
常见错误:在 .env 里写 DATABASE_URL="mysql://user:pass@localhost:3306/app",结果容器内连不上——因为 localhost 指向容器自身,不是 db 服务。
-
DATABASE_URL中的 host 必须与docker-compose.yml里db服务的 service name 一致,例如:mysql://user:pass@db:3306/app - 如果使用 PostgreSQL,同样写成
postgresql://user:pass@db:5432/app - 确保
db服务暴露了端口(3306或5432),且php服务通过depends_on声明依赖,但注意:这仅控制启动顺序,不保证 DB 已 ready,首次doctrine:migrations:migrate可能失败,需加重试逻辑或用wait-for-it.sh
public/ 目录挂载路径容易错位
新版 Symfony 6 推荐 Web 服务器只暴露 public/ 子目录,而非整个项目根目录。若把 ./myproject:/var/www/html 这样挂载,Nginx/Apache 会直接列出所有源码,存在泄露风险。
- Apache 场景:挂载点应为
./myproject/public:/var/www/html,并确认/var/www/html/.htaccess存在且启用AllowOverride All - Nginx 场景:挂载点同上,并在 Nginx 配置中设置
root /var/www/html;+try_files $uri /index.php?$query_string; - 别漏掉
composer install --no-dev --optimize-autoloader在构建阶段执行,否则vendor/autoload.php找不到
bin/console 命令时,它默认走宿主机 PHP 环境,而数据库 URL 若指向 @db,宿主机根本解析不了这个域名——要么进容器执行 docker-compose exec php bin/console ...,要么把 db 映射到本地 /etc/hosts。后者治标不治本,推荐前者。


















