You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony多容器项目执行Makefile初始化时MySQL连接被拒绝

解决Docker环境下Symfony初始化数据库连接拒绝问题

问题描述

我有一个包含React、PHP-Apache、MySQL数据库和PHPMyAdmin四个容器的Symfony项目,为简化部署流程编写了Makefile。执行make init命令时,其他步骤均正常,但创建数据库环节出现「SQLSTATE[HY000] [2002] Connection refused」错误。不过手动执行数据库创建命令时则无此问题,曾尝试通过循环等待确保MySQL容器端口开放,但并未解决问题。

可行解决方案

1. 替换端口等待为MySQL服务就绪检测

容器启动完成不代表MySQL服务已经可以处理连接请求,需要等待MySQL完全初始化完成。在Makefile中新增一个等待数据库就绪的目标,并在database-init前调用:

修改后的Makefile关键部分:

## —— 🐳 Docker ——
docker-start: 
    $(DOCKER_COMPOSE) up -d
    $(MAKE) wait-for-db

wait-for-db: ## Wait for MySQL to be ready
    @echo "Waiting for MySQL database to be ready..."
    @until docker exec db_resrel mysqladmin ping -h "localhost" --silent; do \
        sleep 2; \
    done
    @echo "MySQL is ready!"

2. 为MySQL容器添加健康检查(可选但推荐)

在docker-compose.yml的db服务中添加健康检查,让Docker自动检测MySQL服务状态,确保后续服务只在数据库就绪后才执行操作:

修改后的docker-compose.yml关键部分:

services:
  db:
    image: mysql
    container_name: db_resrel
    restart: always
    volumes:
      - db-data:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
    networks:
      - dev
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

同时,在www服务中添加depends_on的健康检查依赖:

www:
    build: docker
    container_name: www_resrel
    ports:
      - "8000:80"
    volumes:
      - ./docker/vhosts:/etc/apache2/sites-enabled
      - ./api:/var/www
    networks:
      - dev
    depends_on:
      db:
        condition: service_healthy

3. 验证.env文件的数据库配置

确保.env(从.env.example复制而来)中的数据库连接URL使用容器服务名作为主机:

DATABASE_URL="mysql://root:@db:3306/your_database_name?serverVersion=8.0&charset=utf8mb4"

完整修改后的代码示例

修改后的Makefile

# Variables
DOCKER_COMPOSE = docker-compose
EXEC =  docker exec -it www_resrel bash
NPM = $(EXEC) npm
SYMFONY_CONSOLE = bin/console

# Colors
GREEN = /bin/echo -e "\x1b[32m\#\# $1\x1b[0m"
RED = /bin/echo -e "\x1b[31m\#\# $1\x1b[0m"

## —— 🔥 App ——
init: ## Init the project
    $(MAKE) docker-start
    cp .env.example .env
    $(MAKE) composer-install
    $(MAKE) database-init
    $(MAKE) jwt-keys

    @$(call GREEN,"Symfony is available at: http://127.0.0.1:8000/.")
    @$(call GREEN,"React is available at: http://127.0.0.1:3000/.")
    @$(call GREEN,"PhpMyAdmin is available at: http://127.0.0.1:8080/.")

cache-clear: ## Clear cache
    $(EXEC) -c "bin/console cache:clear; exit"

## —— 🐳 Docker ——
docker-start: 
    $(DOCKER_COMPOSE) up -d
    $(MAKE) wait-for-db

wait-for-db: ## Wait for MySQL to be ready
    @echo "Waiting for MySQL database to be ready..."
    @until docker exec db_resrel mysqladmin ping -h "localhost" --silent; do \
        sleep 2; \
    done
    @echo "MySQL is ready!"

jwt-keys: ## Generate JWT keys
    $(EXEC) -c "bin/console lexik:jwt:generate-keypair"

## —— 🎻 Composer ——
composer-install: ## Install dependencies
    composer install

composer-update: ## Update dependencies
    $(COMPOSER) update

## —— 📊 Database ——
database-init: ## Init database
    $(MAKE) database-drop
    $(MAKE) database-create
    $(MAKE) database-migrate
    $(MAKE) database-fixtures-load
    $(MAKE) database-drop-test
    $(MAKE) database-create-test
    $(MAKE) database-migrate-test
    $(MAKE) database-fixtures-load-test
    @$(call GREEN,"Database and test database have been initialized.")

database-drop: ## Drop database
    $(EXEC) -c "bin/console d:d:d --force --if-exists"

database-create: ## Create database
    $(EXEC) -c "bin/console d:d:c --if-not-exists"

database-migration: ## Make migration
    $(EXEC) -c "bin/console make:migration"

migration: ## Alias : database-migration
    $(EXEC) -c "bin/console database-migration"

database-migrate: ## Migrate migrations
    $(EXEC) -c "bin/console d:m:m --no-interaction"

migrate: ## Alias : database-migrate
    $(EXEC) -c "bin/console database-migrate"

database-fixtures-load: ## Load fixtures
    $(EXEC) -c "bin/console d:f:l --no-interaction"

fixtures: ## Alias : database-fixtures-load
    $(EXEC) -c "bin/console database-fixtures-load"

## —— 📊 Database test ——
database-drop-test: ## Drop database
    $(EXEC) -c "bin/console d:d:d --env=test --force --if-exists"

database-create-test: ## Create test database
    $(EXEC) -c "bin/console d:d:c --env=test --if-not-exists"

database-migrate-test: ## Migrate migrations
    $(EXEC) -c "bin/console d:m:m --env=test --no-interaction"

database-fixtures-load-test: ## Load test fixtures
    $(EXEC) -c "bin/console d:f:l --env=test --no-interaction"

## —— 🛠️  Others ——
help: ## List of commands
    @grep -E '(^[a-zA-Z0-9_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'

修改后的docker-compose.yml

version: '3'

services:
  db:
    image: mysql
    container_name: db_resrel
    restart: always
    volumes:
      - db-data:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
    networks:
      - dev
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  phpmyadmin:
    image: phpmyadmin
    container_name: phpmyadmin_resrel
    depends_on:
      - db
    ports:
      - 8080:80
    environment:
      PMA_HOST: db
    networks:
      - dev

  www:
    build: docker
    container_name: www_resrel
    ports:
      - "8000:80"
    volumes:
      - ./docker/vhosts:/etc/apache2/sites-enabled
      - ./api:/var/www
    networks:
      - dev
    depends_on:
      db:
        condition: service_healthy
  
  app:
    build: app
    container_name: app_resrel
    command: npm run dev
    ports:
      - "3000:3000"
    volumes:
      - ./app:/usr/src/app
      - /usr/src/app/node_modules

networks:
  dev:

volumes:
  db-data:

内容的提问来源于stack exchange,提问作者Halchimiste

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:17:32