主机可连接MySQL Docker容器,Node容器无法连接的问题排查
Docker容器间MySQL连接ETIMEDOUT问题排查
问题详情
主机可正常连接Docker容器内的MySQL服务,但同网络下的Node容器无法连接,持续出现ETIMEDOUT错误。单独运行MySQL容器时,主机本地执行Node代码(host设为127.0.0.1)可成功连接。
相关配置
docker-compose.yml
version: '3.9' services: mysql: image: mysql:8.0 command: --default-authentication-plugin=mysql_native_password restart: always environment: MYSQL_DATABASE: 'admindb' MYSQL_USER: 'admin' MYSQL_PASSWORD: 'secretpassword' MYSQL_ROOT_PASSWORD: 'someverysecretpassword' ports: - '3306:3306' - '33060:33060' volumes: - ./db:/var/lib/mysql networks: - adminnet app: image: "node:latest" depends_on: - mysql user: "node" restart: unless-stopped working_dir: /home/app environment: NODE_ENV: production volumes: - ${PWD}/../:/home/app ports: - '8081:8081' command: "npm start" networks: - adminnet volumes: db: data: networks: adminnet:
app.js
const { Sequelize } = require('sequelize'); const sequelize = new Sequelize('admindb', 'admin', 'secretpassword', { host: 'mysql', port: 3306, dialect: 'mysql', }); sequelize .authenticate() .then(() => { console.log('Connection has been established successfully.'); }) .catch(err => { console.error('Unable to connect to the database:', err); });
错误日志
containers-app-1 | Unable to connect to the database: ConnectionError [SequelizeConnectionError]: connect ETIMEDOUT containers-app-1 | at ConnectionManager.connect (/home/app/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:102:17) containers-app-1 | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) containers-app-1 | at async ConnectionManager._connect (/home/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:220:24) containers-app-1 | at async /home/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:174:32 containers-app-1 | at async ConnectionManager.getConnection (/home/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:197:7) containers-app-1 | at async /home/app/node_modules/sequelize/lib/sequelize.js:301:26 containers-app-1 | at async Sequelize.authenticate (/home/app/node_modules/sequelize/lib/sequelize.js:453:5) { containers-app-1 | parent: Error: connect ETIMEDOUT containers-app-1 | at Connection._handleTimeoutError (/home/app/node_modules/mysql2/lib/connection.js:189:17) containers-app-1 | at listOnTimeout (node:internal/timers:564:17) containers-app-1 | at process.processTimers (node:internal/timers:507:7) { containers-app-1 | errorno: 'ETIMEDOUT', containers-app-1 | code: 'ETIMEDOUT', containers-app-1 | syscall: 'connect', containers-app-1 | fatal: true containers-app-1 | }, containers-app-1 | original: Error: connect ETIMEDOUT containers-app-1 | at Connection._handleTimeoutError (/home/app/node_modules/mysql2/lib/connection.js:189:17) containers-app-1 | at listOnTimeout (node:internal/timers:564:17) containers-app-1 | at process.processTimers (node:internal/timers:507:7) { containers-app-1 | errorno: 'ETIMEDOUT', containers-app-1 | code: 'ETIMEDOUT', containers-app-1 | syscall: 'connect', containers-app-1 | fatal: true containers-app-1 | } containers-app-1 | }
排查方案
- 确保MySQL服务完全就绪:
depends_on仅保证容器启动顺序,不代表MySQL服务已可用。可在Node服务中添加连接重试逻辑,或使用wait-for-it等工具等待3306端口开放后再启动应用。 - 验证网络连通性:进入Node容器安装测试工具,执行
apt update && apt install -y telnet,然后运行telnet mysql 3306,若无法连接则说明网络存在问题。 - 检查MySQL绑定地址:MySQL默认可能仅绑定127.0.0.1,需修改为允许所有地址连接。在docker-compose的mysql服务command中添加
--bind-address=0.0.0.0,修改后重启容器。 - 确认数据库用户权限:登录MySQL容器,执行
GRANT ALL ON admindb.* TO 'admin'@'%'; FLUSH PRIVILEGES;,确保admin用户允许从任意主机(包括容器网络)连接。 - 排查卷挂载干扰:若本地
./db目录存在旧的MySQL数据,可能残留旧配置。临时注释掉volumes中的- ./db:/var/lib/mysql,重新创建容器测试是否恢复正常。
内容的提问来源于stack exchange,提问作者Erik van de Ven
相关产品推荐
相关产品推荐

