如何解决PHP Consumer中MySQL连接错误SQLSTATE[HY000][2002]
处理App\Message\Tmdb\MovieRequestedMessage消息时,PHP消费者容器抛出数据库连接错误:
02:46:24 WARNING [messenger] Error thrown while handling message App\Message\Tmdb\MovieRequestedMessage. Sending for retry #1 using 1000 ms delay. Error: "Handling "App\Message\Tmdb\MovieRequestedMessage" failed: An exception occurred in the driver: SQLSTATE[HY000] [2002] No such file or directory" ["class" => "App\Message\Tmdb\MovieRequestedMessage","retryCount" => 1,"delay" => 1000,"error" => "Handling "App\Message\Tmdb\MovieRequestedMessage" failed: An exception occurred in the driver: SQLSTATE[HY000] [2002] No such file or directory","exception" => Symfony\Component\Messenger\Exception\HandlerFailedException { …}]
已尝试将数据库连接地址改为MySQL容器IP,但问题仍存在。以下是相关配置文件:
Dockerfile (php-consumer)
FROM node:latest as node FROM php:8.0-fpm COPY --from=mlocati/php-extension-installer:1.2 /usr/bin/install-php-extensions /usr/local/bin/ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules COPY --from=node /usr/local/bin/node /usr/local/bin/node RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm RUN apt-get update && apt-get install -y \ libpq-dev \ wget \ zlib1g-dev \ libmcrypt-dev \ libzip-dev \ git \ php7.*-xml \ pkg-config \ libcurl4-openssl-dev \ librabbitmq-dev \ libpng-dev \ libjpeg-dev \ libfreetype6-dev RUN apt-get update && apt-get install -y zlib1g-dev libicu-dev g++ RUN docker-php-ext-configure intl RUN docker-php-ext-install intl ENV CFLAGS="$CFLAGS -D_GNU_SOURCE" RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ && \ docker-php-ext-install mysqli pdo pdo_mysql zip curl sockets pcntl RUN install-php-extensions \ decimal \ pdo_mysql \ intl \ amqp \ bcmath \ pcntl \ sockets \ xsl RUN pecl install -o -f redis \ && rm -rf /tmp/pear \ && docker-php-ext-enable redis RUN apt-get update && apt-get install libxslt1-dev -y && docker-php-ext-install xsl RUN curl -S https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer COPY consume.sh /consumer/consume.sh WORKDIR /workdir ENTRYPOINT ["bash", "/consumer/consume.sh"]
consume.sh 脚本
#!/bin/bash sleep 10; /workdir/bin/console messenger:consume >&1;
messenger.yaml 配置
framework: messenger: transports: movies: dsn: "%env(MESSENGER_TRANSPORT_DSN)%" options: vhost: "/" routing: App\Message\Tmdb\MovieRequestedMessage: movies
数据库连接配置 (.env)
DATABASE_URL="mysql://user_name:password@mysql/database_name?serverVersion=5.7"
docker-compose.yml 中 php-consumer 配置
php-consumer: container_name: php_consumer build: context: docker/php-consumer env_file: - .env volumes: - .:/project depends_on: - mysql - rabbitmq - php-cli - php-fpm environment: - "MESSENGER_TRANSPORT_DSN=${MESSENGER_TRANSPORT_DSN}" - "DATABASE_URL=${DATABASE_URL}" networks: - network
排查与解决方法
1. 确认网络连通性
- 检查
mysql容器是否和php-consumer在同一个Docker网络network中,确保docker-compose.yml里的mysql服务也配置了networks: - network。 - 进入
php-consumer容器执行ping mysql,确认能解析到MySQL容器的IP;如果无法解析,检查Docker网络配置是否正确。
2. 修正数据库连接字符串
SQLSTATE[2002]错误通常是PHP尝试通过Unix套接字连接,但Docker中默认使用TCP连接:
- 在
DATABASE_URL中明确指定端口:DATABASE_URL="mysql://user_name:password@mysql:3306/database_name?serverVersion=5.7" - 如果MySQL容器使用了自定义端口,替换3306为实际端口。
3. 确保MySQL服务完全就绪
depends_on仅保证容器启动顺序,不代表MySQL服务已初始化完成。即使sleep 10秒,服务可能仍未就绪:
- 使用
wait-for-it工具替代固定sleep,修改consume.sh:#!/bin/bash # 先在Dockerfile中安装wait-for-it:RUN apt-get update && apt-get install -y wait-for-it wait-for-it mysql:3306 -t 30 /workdir/bin/console messenger:consume >&1;
4. 验证PHP扩展状态
进入php-consumer容器执行php -m | grep pdo_mysql,确认pdo_mysql扩展已启用;如果没有输出,重新检查Dockerfile中的扩展安装步骤是否有错误。
5. 检查数据库权限
确保数据库用户允许从php-consumer所在网络访问:
GRANT ALL PRIVILEGES ON database_name.* TO 'user_name'@'%' IDENTIFIED BY 'password'; FLUSH PRIVILEGES;
(生产环境建议将%限制为具体IP段)
内容的提问来源于stack exchange,提问作者metacore

