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

Node.js+MySQL后端应用Docker容器化后无法建立数据库连接

Node.js+MySQL容器化后连接失败问题解决

问题

本地运行正常的Node.js+MySQL后端应用,容器化部署后Node应用容器无法与MySQL容器建立连接。

相关配置文件

文件夹结构

项目根目录包含dbinit、src文件夹,以及database.js、Dockerfile、docker-compose.yml、.env、app.js等核心文件

database.js

const mysql = require('mysql2');
const dotenv = require('dotenv');

dotenv.config();
// Create a MySQL connection
const connection = mysql.createConnection({
host: process.env.MYSQLDB_HOST,
user: process.env.MYSQLDB_USER,
password: process.env.MYSQLDB_ROOT_PASSWORD,
port: process.env.NODE_LOCAL_PORT,
database: process.env.MYSQLDB_DATABASE
});

connection.connect((err) => {
if (err) {
console.error('Error connecting to MySQL: ' + err.stack);
return;
}
console.log('Connected to MySQL as id ' + connection.threadId);
});

module.exports = connection;

docker-compose.yml

version: '3.8'
services:
  mysqldb:
    image: mysql
    container_name: mysql_container
    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:
      - $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
    environment:
      MYSQL_ROOT_PASSWORD: $MYSQLDB_ROOT_PASSWORD
      MYSQL_DATABASE: $MYSQLDB_DATABASE
    networks:
      - internalnet

  nodeapp:
    depends_on:
      - mysqldb
    build:
      context: .
      dockerfile: Dockerfile
    container_name: nodeapp_container
    restart: unless-stopped
    env_file: .env
    image: nodeapp_backend
    ports:
      - $NODE_LOCAL_PORT:$NODE_DOCKER_PORT
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules
    environment:
      - DB_HOST=mysqldb
      - DB_USER=$MYSQLDB_USER
      - DB_PASSWORD=$MYSQLDB_ROOT_PASSWORD
      - DB_NAME=$MYSQLDB_DATABASE
      - DB_PORT=$MYSQLDB_DOCKER_PORT
    networks:
      - internalnet

networks:
  internalnet:
    driver: bridge

Dockerfile

FROM node:alpine3.11
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD [ "node", "app.js" ]

.env文件

MYSQLDB_USER=root
MYSQLDB_ROOT_PASSWORD=hiru
MYSQLDB_DATABASE=assignments_db
MYSQLDB_LOCAL_PORT=3306
MYSQLDB_DOCKER_PORT=3306
NODE_LOCAL_PORT=3000
NODE_DOCKER_PORT=3000
MYSQLDB_HOST=mysqldb

app.js文件

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const authenticationRoutes = require('./src/routes/authentication');
const assignmentsRoutes = require('./src/routes/assignments');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.use('/auth', authenticationRoutes);
app.use('/assignments', assignmentsRoutes);


app.get("/", (req, res) => {
    res.send("Welcome to the Assignments API");
});

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

运行日志问题

执行docker-compose up后,Node容器日志显示无法连接MySQL,报错连接超时或连接被拒绝。

问题分析

  1. 端口配置错误:database.js中MySQL连接端口使用了NODE_LOCAL_PORT(3000),但MySQL容器内部服务端口为3306,应使用MYSQLDB_DOCKER_PORT。
  2. 环境变量冗余混淆:docker-compose.yml中node服务重复定义了DB_*前缀的环境变量,但database.js实际读取的是MYSQLDB_*前缀的变量,配置冗余易引发错误。
  3. 服务就绪不同步:depends_on仅保证MySQL容器启动,不代表MySQL服务已完成初始化并可接受连接,Node应用启动时可能MySQL尚未就绪。

解决方案

1. 修正database.js端口配置并添加重试逻辑

const mysql = require('mysql2');
const dotenv = require('dotenv');

dotenv.config();
// Create a MySQL connection
const connection = mysql.createConnection({
  host: process.env.MYSQLDB_HOST,
  user: process.env.MYSQLDB_USER,
  password: process.env.MYSQLDB_ROOT_PASSWORD,
  port: process.env.MYSQLDB_DOCKER_PORT, // 修正为MySQL容器端口
  database: process.env.MYSQLDB_DATABASE
});

// 添加重试逻辑,解决MySQL未就绪问题
function connectWithRetry() {
  connection.connect((err) => {
    if (err) {
      console.error('Error connecting to MySQL: ' + err.stack);
      console.log('Retrying connection in 3 seconds...');
      setTimeout(connectWithRetry, 3000);
      return;
    }
    console.log('Connected to MySQL as id ' + connection.threadId);
  });
}

connectWithRetry();

module.exports = connection;

2. 清理docker-compose冗余环境变量

node服务已通过env_file: .env加载所有环境变量,删除重复定义的DB_*变量,修改后的node服务配置:

nodeapp:
  depends_on:
    - mysqldb
  build:
    context: .
    dockerfile: Dockerfile
  container_name: nodeapp_container
  restart: unless-stopped
  env_file: .env
  image: nodeapp_backend
  ports:
    - $NODE_LOCAL_PORT:$NODE_DOCKER_PORT
  volumes:
    - .:/usr/src/app
    - /usr/src/app/node_modules
  networks:
    - internalnet

3. (可选)使用工具检测MySQL就绪状态

若需要更可靠的启动顺序,可在Dockerfile中安装wait-for-it脚本,等待MySQL服务就绪后再启动Node应用:

  • 在Dockerfile中添加安装命令:
RUN wget -O /usr/src/app/wait-for-it.sh https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && chmod +x /usr/src/app/wait-for-it.sh
  • 修改启动命令:
CMD [ "./wait-for-it.sh", "mysqldb:3306", "--", "node", "app.js" ]

验证步骤

  1. 停止当前容器:docker-compose down
  2. 重新构建镜像:docker-compose build
  3. 启动容器:docker-compose up
  4. 查看日志,确认Node应用成功连接MySQL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 23:07:03