Docker构建PHP容器阶段无法连接MySQL,如何实现构建时数据库连接?
解决Docker构建阶段无法连接MySQL的问题
你遇到的核心问题是Docker镜像构建阶段与Compose服务网络完全隔离——当Docker构建PHP镜像时,Compose中定义的MySQL服务还没启动,而且构建环境根本无法访问Compose创建的内部网络,所以PHP容器在构建时找不到mysql主机名,才会抛出getaddrinfo failed错误。
要在容器启动时自动完成Magento安装(而不是构建阶段),可以按以下步骤调整配置:
1. 修改Dockerfile,将安装逻辑移到启动脚本
把构建阶段的setup:install步骤移除,换成自定义启动脚本,让安装在容器启动时执行:
FROM php:7.2-fpm RUN apt-get update && apt-get install -y \ curl \ wget \ git \ vim \ libfreetype6-dev \ libjpeg62-turbo-dev \ libxslt-dev \ libicu-dev \ libmcrypt-dev \ libpng-dev \ libxml2-dev \ netcat-traditional # 新增:用于检测MySQL服务是否就绪 RUN docker-php-ext-install bcmath \ gd \ intl \ soap \ xsl \ zip \ pdo_mysql WORKDIR /var/www/html RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer config -g http-basic.repo.magento.com -a 5310458a34d580de1700dfe826ff19a1 255059b03eb9d30604d5ef52fca7465d RUN composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition . # 复制自定义启动脚本并赋予执行权限 COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] CMD ["php-fpm"]
2. 创建启动脚本entrypoint.sh
这个脚本会先等待MySQL服务就绪,再检查Magento是否已安装,未安装则自动执行安装:
#!/bin/bash # 等待MySQL服务完全就绪(避免连接时数据库还没初始化完成) until nc -z mysql 3306; do echo "Waiting for MySQL to be ready..." sleep 2 done # 检查Magento是否已安装(通过env.php文件判断) if [ ! -f app/etc/env.php ]; then echo "Starting Magento installation..." php bin/magento setup:install \ --base-url="http://localhost:8080/" \ --db-host="mysql" \ --db-name="magento" \ --db-user="manager" \ --db-password="1111" \ --backend-frontname="admin" \ --admin-firstname="admin" \ --admin-lastname="admin" \ --admin-email="admin@admin.com" \ --admin-user="admin" \ --admin-password="admin123" \ --language="en_US" \ --currency="USD" \ --timezone="America/New_York" \ --use-rewrites="1" # 可选:生成静态文件(第一次安装后需要执行) php bin/magento setup:static-content:deploy -f en_US fi # 执行容器原本的启动命令(保持php-fpm正常运行) exec "$@"
3. 调整docker-compose.yml,添加依赖关系
确保PHP容器依赖MySQL服务,让Compose先启动MySQL再启动PHP:
version: '3.0' services: nginx: image: nginx:1.15 container_name: nginx ports: - 8080:80 volumes: - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf depends_on: - php php: build: ./ container_name: php depends_on: - mysql # 可选:挂载本地目录,方便开发时修改代码 # volumes: # - ./magento:/var/www/html mysql: image: mysql:5.7 container_name: mysql ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: 1111 MYSQL_DATABASE: magento MYSQL_USER: manager MYSQL_PASSWORD: 1111 volumes: - ./mysql:/var/lib/mysql adminer: image: adminer restart: always ports: - 8000:8080 depends_on: - mysql
为什么这个方案可行?
- 构建与运行分离:构建阶段只准备PHP环境和Magento代码,运行阶段才执行数据库相关的初始化,此时Compose的服务网络已经创建,MySQL服务也已启动。
- 避免重复执行:通过检查
app/etc/env.php文件,确保只有第一次启动时才会执行安装,后续启动直接跳过。 - 服务就绪检测:用
nc等待MySQL端口开放,避免在数据库还没初始化完成时就执行安装命令。
内容的提问来源于stack exchange,提问作者Petro Chaikivskyi
相关产品推荐
相关产品推荐

