Docker环境下Laravel出现SQLSTATE[HY000][2002]连接拒绝错误求助
Docker搭建Laravel环境时
php artisan migrate连接MySQL失败的排查与解决 首次使用Docker搭建Laravel开发环境,配置了Dockerfile、docker-compose.yaml及.env文件,但执行php artisan migrate时出现SQLSTATE[HY000] [2002] Connection refused错误,尝试相关方案仍未解决,以下是配置文件及错误详情,附排查与修正方法:
相关配置文件
Dockerfile
FROM php:8-fpm COPY . /app WORKDIR /app COPY composer.lock composer.json ./ RUN apt-get update -y && apt-get install -y sendmail libpng-dev RUN apt-get update && apt-get install -y \ build-essential \ curl RUN curl -sSL https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions -o - | sh -s \ gd \ zip RUN docker-php-ext-install mysqli pdo pdo_mysql RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer update RUN composer install
docker-compose.yaml
version: '3.9' name: caas-portal services: front: build: context: ./webapp target: builder ports: - 4200:4200 volumes: - ./webapp:/project - /project/node_modules mysql: container_name: mysql image: mysql:latest environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_DATABASE=db ports: - 3307:3306/tcp networks: - laravel elasticsearch: container_name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.17.7 environment: - discovery.type=single-node ports: - 9200:9200/tcp - 9300:9300/tcp volumes: - 'elasticsearch:/usr/share/elasticsearch/data' networks: - laravel app: container_name: back build: . ports: - 8000:80 networks: - laravel networks: laravel: driver: bridge volumes: elasticsearch: driver: local
.env相关配置
DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3307 DB_DATABASE=db DB_USERNAME=root DB_PASSWORD=password
错误信息
执行docker exec -it <container> sh进入容器后运行php artisan migrate,报错:
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = db and table_name = migrations and table_type = 'BASE TABLE')
排查与修正方法
1. 修正.env中的数据库端口
Docker容器间通信使用容器内部端口,而非宿主机映射的端口。你的MySQL容器内部端口是3306,因此.env里的DB_PORT需改为3306:
DB_PORT=3306
2. 确保MySQL容器完全初始化后再执行migrate
MySQL容器启动需要时间完成初始化,直接执行migrate会因服务未就绪导致连接拒绝。两种解决方式:
- 手动等待:启动容器后等待1-2分钟再执行migrate命令
- 配置健康检查自动等待:修改docker-compose.yaml,给MySQL添加健康检查,让app服务等待MySQL就绪后再启动
# mysql服务添加健康检查 mysql: container_name: mysql image: mysql:latest environment: - MYSQL_ROOT_PASSWORD=password - MYSQL_DATABASE=db ports: - 3307:3306/tcp networks: - laravel healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-ppassword"] timeout: 20s retries: 10 # app服务添加依赖等待 app: container_name: back build: . ports: - 8000:80 networks: - laravel depends_on: mysql: condition: service_healthy
3. 优化Dockerfile构建顺序(可选,但提升开发效率)
当前Dockerfile先复制整个项目目录,会导致代码修改后需重新安装依赖。调整顺序,先处理依赖再复制代码,利用Docker缓存加速构建:
FROM php:8-fpm WORKDIR /app # 先复制composer文件,缓存依赖安装层 COPY composer.lock composer.json ./ RUN apt-get update -y && apt-get install -y sendmail libpng-dev build-essential curl RUN curl -sSL https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions -o - | sh -s \ gd \ zip RUN docker-php-ext-install mysqli pdo pdo_mysql RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer install --no-dev # 开发环境可移除--no-dev参数 # 最后复制项目代码 COPY . /app
4. 验证容器间网络连通性
进入app容器,测试与MySQL容器的网络连通:
docker exec -it back ping mysql
若ping不通,执行docker-compose down -v清理旧容器和网络,再重新启动:docker-compose up -d
内容的提问来源于stack exchange,提问作者Julia Olcese
相关产品推荐
相关产品推荐

