Docker容器中Node.js无法连接MySQL的问题求助
问题:Node.js容器无法连接MySQL容器(ECONNREFUSED)
错误信息
Express server is runnig at port no : 8000 backend-web-1 | DB connection failed backend-web-1 | Error : { backend-web-1 | "errno": -111, backend-web-1 | "code": "ECONNREFUSED", backend-web-1 | "syscall": "connect", backend-web-1 | "address": "127.0.0.1", backend-web-1 | "port": 3306, backend-web-1 | "fatal": true backend-web-1 | }
相关配置文件
MySQL Dockerfile(路径:./dbinit/Dockerfile)
FROM mysql WORKDIR /app COPY ./mysql.sql /docker-entrypoint-initdb.d/
Node.js Dockerfile(路径:./app/Dockerfile)
FROM node:18-alpine WORKDIR /app COPY *package.json /app RUN npm install EXPOSE 8000 COPY . /app CMD ["node" ,"index.js"]
docker-compose.yml
services: db: command: --default-authentication-plugin=mysql_native_password restart: always build: ./dbinit environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: timesheet restart: always ports: - "3305:3309" web: depends_on: - "db" build: ./app environment: MYSQL_HOST: db MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: timesheet ports: - "5000:8000"
Node.js数据库连接代码(index.js)
// Create Connection var mysqlConnection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'root', database: 'timesheet', multipleStatements: true }); // Connecting database mysqlConnection.connect((err) => { if (!err) console.log('DB connection succeded.'); else console.log('DB connection failed \n Error : ' + JSON.stringify(err, undefined, 2)); }); app.listen(8000, () => console.log('Express server is runnig at port no : 8000'));
问题分析与解决方案
1. 核心问题:数据库地址硬编码为localhost
Docker Compose环境中,每个容器是独立网络节点,localhost指向Node.js容器自身,而非MySQL容器。虽然web服务配置了MYSQL_HOST: db环境变量,但代码未读取该变量,仍使用localhost。
修复代码:
var mysqlConnection = mysql.createConnection({ host: process.env.MYSQL_HOST || 'localhost', // 优先读取环境变量 user: 'root', password: process.env.MYSQL_ROOT_PASSWORD || 'root', database: process.env.MYSQL_DATABASE || 'timesheet', multipleStatements: true });
2. 端口映射配置错误
MySQL默认端口为3306,但db服务的ports配置为"3305:3309",既不符合默认端口,也会干扰容器间通信(容器间通过服务名直接访问默认端口即可,无需映射)。
修复docker-compose.yml:
# 若需要宿主机访问MySQL,修正端口映射 ports: - "3305:3306" # 若不需要宿主机访问,可直接删除ports配置项
3. 额外问题:数据库未就绪时Node.js已启动
depends_on仅保证启动顺序,不保证MySQL完成初始化并接受连接,Node.js可能在数据库未就绪时发起连接导致失败。
可选修复方案:
- 添加重连逻辑:
function handleDisconnect() { mysqlConnection = mysql.createConnection({ host: process.env.MYSQL_HOST || 'localhost', user: 'root', password: process.env.MYSQL_ROOT_PASSWORD || 'root', database: process.env.MYSQL_DATABASE || 'timesheet', multipleStatements: true }); mysqlConnection.connect((err) => { if (err) { console.log('DB connection failed, retrying in 2 seconds...', err); setTimeout(handleDisconnect, 2000); } else { console.log('DB connection succeeded.'); } }); mysqlConnection.on('error', (err) => { console.log('DB error occurred, reconnecting...', err); if (err.code === 'PROTOCOL_CONNECTION_LOST') { handleDisconnect(); } else { throw err; } }); } handleDisconnect();
- 使用工具等待数据库就绪:
- 修改Node.js Dockerfile安装
wait-for-it:RUN apk add --no-cache bash COPY https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /usr/local/bin/wait-for-it.sh RUN chmod +x /usr/local/bin/wait-for-it.sh - 更新
web服务的启动命令:command: ["wait-for-it.sh", "db:3306", "--", "node", "index.js"]
- 修改Node.js Dockerfile安装
内容的提问来源于stack exchange,提问作者Sherwin
相关产品推荐
相关产品推荐

