Node TS API容器无法连接SQL Server,求助排查故障
问题:Docker容器中Node应用无法连接SQL Server(mssql)
本地运行Node应用可正常连接SQL Server,但部署为Docker容器后出现以下连接错误:
ConnectionError: Failed to connect to = 192.168.0.190:1433 - getaddrinfo ENOTFOUND = 192.168.0.190 at connectListener (/app/node_modules/mssql/lib/tedious/connection-pool.js:70:17) at Connection.onConnect (/app/node_modules/tedious/src/connection.ts:1725:9) at Object.onceWrapper (node:events:629:26) at Connection.emit (node:events:514:28) at Connection.emit (/app/node_modules/tedious/src/connection.ts:1868:18) at Connection.socketError (/app/node_modules/tedious/src/connection.ts:2189:12) at /app/node_modules/tedious/src/connection.ts:1992:37 at processTicksAndRejections (node:internal/process/task_queues:77:11) { code: ‘ESOCKET’, originalError: ConnectionError: Failed to connect to = 192.168.0.190:1433 - getaddrinfo ENOTFOUND = 192.168.0.190 at Connection.socketError (/app/node_modules/tedious/src/connection.ts:2189:28) at /app/node_modules/tedious/src/connection.ts:1992:37 at processTicksAndRejections (node:internal/process/task_queues:77:11) { code: ‘ESOCKET’, isTransient: undefined } }
相关配置文件
Dockerfile
FROM node:18-alpine WORKDIR /app COPY ./package*.json . RUN npm install COPY . . ENV APP_DATA_BASE = ************* ENV API_HOST = 192.168.0.190 ENV INSTANCE_NAME = mssqlserver ENV DB_PORT = 1433 ENV PORT = 8080 ENV DIALECT = ***** ENV DB_USER = ***** ENV PASSWORD = ****** ENV TLS_VERSION = ***** ENV SECRET= ********** ENV BI_DATABASE = **** ENV BI_USER = **** ENV BI_PASSWORD = ***** ENV BI_HOST = 192.168.0.190 ENV BI_PORT = 1433 EXPOSE 8080
docker-compose.yml
version: ‘3.7’ services: cockpit-api: build: context: . dockerfile: Dockerfile # target: base volumes: - ./src:/usr/src/app container_name: cockpit-api expose: - '8080' ports: - '8080:8080' command: npm run dev
App DataSource配置
import ‘reflect-metadata’ import ‘dotenv/config’ import { join } from ‘path’ import { DataSource } from ‘typeorm’ export const AppDataSource = new DataSource({ type: 'mssql', host: process.env.API_HOST, port: Number(process.env.DB_PORT), username: process.env.DB_USER, password: process.env.PASSWORD, database: process.env.APP_DATA_BASE, synchronize: false, logging: false, entities: [join(__dirname, './entities/*{.ts,.js}')], migrations: [join(__dirname, './migrations/*{.ts,.js}')], subscribers: [], extra: { encrypt: false, trustServerCertificate: true } })
server.ts
import 'reflect-metadata' import { AppDataSource } from '../infra/db/mssql/cockpit/datasource' import mssql from 'mssql'; const sql = mssql import app from './config/app' export const biEmisConfig = { user: process.env.BI_USER, password: process.env.BI_PASSWORD, database: process.env.BI_DATABASE, server: process.env.BI_HOST || '', pool: { max: 10, min: 0, idleTimeoutMillis: 30000 }, options: { encrypt: false, // for azure trustServerCertificate: true, // change to true for local dev / self-signed certs port: Number(process.env.BI_PORT) } } AppDataSource.initialize() .then(async () => { console.log('App Data Source initilized') await sql.connect(biEmisConfig) console.log('Bi initialized') app.listen(process.env.PORT, () => { console.log(`Server is running on ${process.env.PORT}`) }) }) .catch(error => console.error(error))
package.json
{ "name": "cockpit-api", "version": "1.0.0", "main": "index.js", "license": "MIT", "type": "commonjs", "scripts": { "start": "node build/main/server.js", "build": "rimraf build && tsc", "dev": "tsnd --transpile-only --respawn --ignore-watch node_modules src/main/server.ts", "test": "vitest", "coverage": "vitest run --coverage", "typeorm": "typeorm-ts-node-commonjs", "migration:generate": "typeorm-ts-node-commonjs migration:generate -d src/infra/db/mssql/cockpit/datasource.ts", "migration:up": "typeorm-ts-node-commonjs migration:run -d src/infra/db/mssql/cockpit/datasource.ts", "migration:down": "typeorm-ts-node-commonjs migration:revert -d src/infra/db/mssql/cockpit/datasource.ts", "migration:create": "typeorm migration:create" }, "dependencies": { "bcrypt": "^5.1.0", "dotenv": "^16.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", "mssql": "^9.1.2", "reflect-metadata": "^0.1.13", "rimraf": "^5.0.1", "typeorm": "^0.3.17", "validator": "^13.9.0" }, "devDependencies": { "@types/bcrypt": "^5.0.0", "@types/express": "^4.17.17", "@types/jsonwebtoken": "^9.0.2", "@types/mssql": "^8.1.2", "@types/node": "^20.3.2", "@types/validator": "^13.7.17", "@typescript-eslint/eslint-plugin": "^5.60.0", "@typescript-eslint/parser": "^5.60.0", "@vitest/coverage-v8": "^0.32.2", "eslint": "^8.43.0", "eslint-config-standard-with-typescript": "^35.0.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-promise": "^6.1.1", "prettier": "^2.8.8", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", "typescript": "^5.1.3", "vitest": "^0.32.2" } }
解决方案
1. 修复Dockerfile环境变量定义格式
错误日志中显示连接地址为= 192.168.0.190,核心原因是Dockerfile中环境变量赋值添加了多余的空格和等号。ENV变量赋值不能有空格,正确格式为ENV KEY=VALUE。
修改后的Dockerfile环境变量部分:
ENV APP_DATA_BASE=************* ENV API_HOST=192.168.0.190 ENV INSTANCE_NAME=mssqlserver ENV DB_PORT=1433 ENV PORT=8080 ENV DIALECT=***** ENV DB_USER=***** ENV PASSWORD=****** ENV TLS_VERSION=***** ENV SECRET=********** ENV BI_DATABASE=**** ENV BI_USER=**** ENV BI_PASSWORD=***** ENV BI_HOST=192.168.0.190 ENV BI_PORT=1433
2. 确保Docker容器能访问SQL Server
- 如果SQL Server运行在宿主机:
- Windows/macOS:使用
host.docker.internal替代192.168.0.190作为数据库主机地址 - Linux:在docker-compose中添加
network_mode: host,或确保宿主机防火墙开放1433端口,且SQL Server允许远程连接
- Windows/macOS:使用
- 如果SQL Server在局域网其他机器:确认容器所在网络能访问该机器的1433端口,SQL Server已启用TCP/IP协议,且防火墙规则放行
3. 修正Docker Compose路径映射
Dockerfile中WORKDIR为/app,但docker-compose的volume映射为./src:/usr/src/app,路径不匹配会导致代码加载异常。修改为:
volumes: - ./src:/app/src
4. 验证SQL Server配置
- 确认SQL Server已启用TCP/IP协议(在SQL Server配置管理器中查看)
- 确认SQL Server实例监听1433端口
- 确认数据库账号拥有远程连接权限
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

