Docker化Symfony 4.2项目无法连接MySQL容器问题求助
问题现象
将Symfony 4.2项目迁移至Docker容器,搭配MySQL 8.0(因Mac M1不支持5.4/5.7版本),但项目始终无法连接数据库。php-apache容器日志及浏览器均抛出相同错误:
Uncaught PHP Exception Doctrine\DBAL\Exception\ConnectionException: "An exception occurred in driver: SQLSTATE[HY000] [2002] Connection refused"
已执行的部署操作
- 拉取php-apache-7.4镜像
- 拉取MySQL 8.0镜像
- 在docker-compose.yml中配置
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' - 在php-apache容器中安装pdo、mysqli、pdo_mysql和zip扩展
- 生成并安装自签名SSL证书至php-apache容器
- 暴露端口:3306(MySQL)、80(Web)、443(SSL)
- 在docker-compose.yml中创建自定义网络
abc-network - 本地/etc/hosts添加测试域名并重启Apache
配置文件内容
docker-compose.yml
version: "3.8" networks: abc-network: services: #mysql mysql-service: image: mysql networks: - abc-network container_name: abc_db_container ports: - "3306:3306" environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' volumes: - ./mysql:/var/lib/mysql restart: always #php php-service: build: context: . dockerfile: ./symfony/Dockerfile container_name: abc_php_container networks: - abc-network ports: - "80:80" - "443:443" volumes: - ./symfony/docker/ssl/mycert.crt:/etc/ssl/certs/mycert.crt - ./symfony/docker/ssl/mycert.key:/etc/ssl/private/mycert.key - ./symfony:/var/www/symfony depends_on: - mysql-service
Dockerfile
# PHP + Apache FROM php:7.4-apache #Enable apache module and ssl self sign installation RUN a2enmod rewrite RUN a2enmod ssl && a2enmod socache_shmcb RUN sed -i '/SSLCertificateFile.*snakeoil\.pem/c\SSLCertificateFile \/etc\/ssl\/certs\/mycert.crt' /etc/apache2/sites-available/default-ssl.conf && sed -i '/SSLCertificateKeyFile.*snakeoil\.key/cSSLCertificateKeyFile /etc/ssl/private/mycert.key\' /etc/apache2/sites-available/default-ssl.conf RUN a2ensite default-ssl RUN apt-get update && apt-get upgrade -y #updates apt get and install essential php libraries RUN apt-get update \ && apt-get install -y libzip-dev git wget --no-install-recommends \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* #Install mysql driver for php and zip RUN docker-php-ext-install pdo mysqli pdo_mysql zip; #Installs composer RUN wget https://getcomposer.org/download/2.0.9/composer.phar \ && mv composer.phar /usr/bin/composer && chmod +x /usr/bin/composer RUN chmod 777 /var/lib #Copies ABC's virtual host conf file to the docker container COPY ./symfony/docker/apache.conf /etc/apache2/sites-enabled/000-default.conf COPY ./symfony/docker/ssl-conf.conf /etc/apache2/sites-available/default-ssl.conf #Copies ABC CMS Symfony project COPY ./symfony /var/www/symfony/ #Points the working directory WORKDIR /var/www/symfony CMD ["apache2-foreground"]
解决方法
1. 修正Symfony数据库主机配置
Docker容器间通过服务名通信,Symfony的.env或config/packages/doctrine.yaml中,数据库主机不能填localhost或127.0.0.1,需替换为docker-compose中MySQL的服务名mysql-service:
# .env文件示例 DATABASE_URL=mysql://root@mysql-service:3306/你的数据库名?serverVersion=8.0
2. 确保MySQL服务就绪后启动PHP容器
depends_on仅保证容器启动顺序,不确保MySQL服务完全就绪。可添加健康检查解决:
在docker-compose.yml的mysql-service中加入健康检查配置:
healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10
然后修改php-service的depends_on:
depends_on: mysql-service: condition: service_healthy
3. 兼容MySQL 8.0认证机制
MySQL 8.0默认使用caching_sha2_password认证,部分旧PHP客户端不兼容。在mysql-service的环境变量中添加:
environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' MYSQL_DEFAULT_AUTH: mysql_native_password
4. 检查端口冲突
确认本地3306端口未被其他MySQL服务占用,若有冲突可修改docker-compose中MySQL的端口映射为3304:3306,容器内部仍使用3306端口。
5. 验证容器网络连通性
进入php-apache容器,测试能否ping通MySQL服务:
docker exec -it abc_php_container ping mysql-service
若不通,检查两个容器是否都加入了abc-network网络。
内容的提问来源于stack exchange,提问作者Olayinka Sagoe

