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

使用Docker/Docker-Compose连接Node.js与MySQL时遇连接拒绝问题

Node.js + MySQL Docker连接问题排查

配置文件

Dockerfile

FROM node:latest  
WORKDIR /app 
COPY . /app 
RUN npm update 
RUN npm install 
RUN npm rebuild bcrypt 
ENV SERVER_PORT 3000 
EXPOSE $SERVER_PORT 
CMD ["npm", "start"]

docker-compose.yml

services:
  mysqldb:
    image: mysql:8.0
    container_name: mysqlcontainer
    command: --default-authentication-plugin=mysql_native_password
    restart: unless-stopped
    volumes:
      - ./dbinit/init.sql:/docker-entrypoint-initdb.d/0_init.sql
      - $HOME/database:/var/lib/mysql
    ports:
      - 3306:3306
    expose:
      - 3306
    environment:
      MYSQL_DATABASE: hotel_managment
      MYSQL_USER: admin
      MYSQL_PASSWORD: letmein
      MYSQL_ROOT_PASSWORD: letmein
      SERVICE_TAGS: prod
      SERVICE_NAM: mysqldb 
    networks:
      - internalnet

  nodeapp:
    container_name: nodeappcontainer
    build: .
    image: nodeapp:v1
    ports:
      - 3000:3000
    expose:
      - 3000
    depends_on:
      - mysqldb
    environment:
      DB_HOST: mysqldb
      DB_USER : 'root'
      DB_PASSWORD: 'letmein'
      DB_NAME : hotel_managment
      DB_PORT : 3306
      DB_CONNECTION_LIMIT : 10
      SERVER_PORT : 3000
      SERVICE_TAGS: prod
      SERVICE_NAME: nodeappservice
    networks:
      - internalnet

networks:
  internalnet:
    driver: bridge

.env文件

DB_HOST = localhost 
DB_USER = root 
DB_PASSWORD = letmein 
DB_NAME = hotel_managment 
DB_PORT = 3306 
DB_CONNECTION_LIMIT = 10 
SERVER_PORT = 5000

Node.js数据库连接代码

let connection = mysql.createConnection({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
});

操作与错误信息

执行命令:

docker-compose up -d --build

出现错误:

> nodejs@1.0.0 start
> node -r dotenv/config app.js
server is listening on port: 3000
nodejs@1.0.0 start
> node -r dotenv/config app.js
server is listening on port: 3000
Error connecting to database: Error: connect ECONNREFUSED 172.22.0.2:3306
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1606:16) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '172.22.0.2',
port: 3306,
fatal: true
}

排查与解决步骤

1. 解决环境变量冲突

你的docker-compose.yml给nodeapp设置了DB_HOST: mysqldb,但本地.env文件设置的DB_HOST = localhost。由于启动命令用了node -r dotenv/config app.js,dotenv会优先加载本地.env变量,覆盖docker-compose的配置,导致Node.js尝试连接容器内的localhost(而非mysqldb服务)。

解决方式三选一:

  • 删除项目根目录的.env文件,让容器使用docker-compose定义的环境变量;
  • 修改.env文件的DB_HOST为mysqldb,保持与docker-compose一致;
  • 修改npm start脚本为node app.js,不加载dotenv。

2. 处理MySQL初始化延迟

depends_on仅保证mysqldb容器先启动,但不保证MySQL服务完成初始化。如果MySQL初始化较慢,Node.js启动后立即连接会失败。

解决方式二选一:

  • 在Node.js连接代码中添加重试逻辑:
function connectDB() {
  connection.connect((err) => {
    if (err) {
      console.error('连接失败,3秒后重试:', err);
      setTimeout(connectDB, 3000);
      return;
    }
    console.log('数据库连接成功');
  });
}
connectDB();
  • 在docker-compose中添加健康检查,让nodeapp等待MySQL就绪后启动:
    在mysqldb配置中添加:
healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pletmein"]
  interval: 5s
  timeout: 5s
  retries: 5

修改nodeapp的depends_on:

depends_on:
  mysqldb:
    condition: service_healthy

3. 验证MySQL容器状态

  • 进入MySQL容器检查服务状态:
docker exec -it mysqlcontainer mysql -uroot -pletmein
# 进入后执行命令确认数据库存在
SHOW DATABASES;
  • 确认MySQL容器在指定网络内:
docker inspect mysqlcontainer | grep Networks
  • 检查root用户是否允许远程连接:
    在MySQL中执行:
SELECT user, host FROM mysql.user;

如果root用户的host不是%,执行:

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'letmein';
FLUSH PRIVILEGES;

4. 检查网络连通性

在nodeapp容器内ping MySQL容器的内网IP(错误信息中的172.22.0.2):

docker exec -it nodeappcontainer ping 172.22.0.2

如果ping不通,检查docker-compose的networks配置,确保两个服务都加入了internalnet网络。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:11:14