Docker部署Node.js后端遇TypeORM 'driver not connected'错误求助
Docker中运行后端应用遇到'driver not connected'错误排查
问题描述
在Docker中运行后端应用时,发起请求时遇到了driver not connected错误,不确定问题是否出在数据库连接方式上,服务层使用了事务和Repository。
数据库连接相关代码
class DataSourceFactory { private Isource: DataSource; get source(): DataSource { return this.Isource; } constructor() { this.Isource = new DataSource({ type: 'postgres', host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT as string), username: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, synchronize: process.env.NODE_ENV === EnvResult.dev ? true : false, entities: ['src/entities/**/*{entity.ts,entity.js}'], logging: process.env.NODE_ENV === EnvResult.dev ? true : false, subscribers: [EveryEventSubscriber], namingStrategy: new SnakeNamingStrategy(), }); } } export default new DataSourceFactory();
import DataSourceFactory from '@source/data.source'; import { logger } from '@/logger/custom.logger'; class DatabaseProvider { async init(): Promise<void> { try { await DataSourceFactory.source.initialize(); logger.client.info('Database connection is successful::...'); } catch (err: any) { logger.client.error(err.message); } } } export const databaseSource = new DatabaseProvider();
服务层事务示例
@Service() export class MemberService { private readonly dbSource = DataSourceFactory.source; public async register( dto: MemberRegisterDto ): Promise<CreatedResponse<IdentifierResDto>> { return await this.dbSource.manager.transaction( async (transactionalEntityManager: EntityManager) => { try { const newMember = await transactionalEntityManager .withRepository(MemberRepository) .customCreate(dto); const newUser = await transactionalEntityManager .withRepository(UserRepository) .customCreate(dto, newMember); const newToken = await transactionalEntityManager .withRepository(TokenRepository) .customCreate({ operation: TokenOperationType.verifyAfterRegistration, userId: newUser.id, memberId: newMember.id, publicId: newUser.publicId, app: newUser.app, globalDeviceName: newUser.globalDeviceName, }); new ElectronicMessaging({ contact: newUser.app.type === ApplicationType.Src ? newUser.I.phone : newUser.I.mail, content: { token: newToken.clientToken, fullName: newUser.name + ' ' + newUser.surname, }, operation: newToken.operation as TokenOperationType.verifyAfterRegistration, }).load(newToken.app.type); const convertData = TransformService.convert< IdentifierResDto, UserEntity >(newUser, IdentifierResDto, 'excludeAll'); return new CreatedResponse<IdentifierResDto>( Code.SUCCESS_CREATE, Messages.SUCCESS_CREATE, convertData ); } catch (error) { throw error; } } ); }}
Docker Compose配置示例
version: '3.9' services: postgresql: image: postgres restart: unless-stopped ports: - '5732:5732' networks: - app environment: POSTGRES_PASSWORD: mypassword POSTGRES_USER: postgres nats: image: nats-streaming:0.17.0 networks: - app command: - '-p' - '4222' - '-m' - '8222' - '-hbi' - '5s' - '-hbt' - '5s' - '-hbf' - '2' - '-SD' - '-cid' - 'bestneting' - '-cluster' - 'nats://0.0.0.0:6222' ports: - 4222:4222 - 8222:8222 backend: image: nurettinsenbackend/bestnetbackend restart: on-failure depends_on: - postgresql - nats command: sh -c "while ! nc -z postgresql 5432; do sleep 1; done && npm run dev" environment: - DB_PASS=mypassword - DB_HOST=postgresql - NATS_URL=http://nats:4222 ports: - 2000:2000 networks: - app mail: image: nurettinsenbackend/mail restart: on-failure depends_on: - nats environment: - NATS_URL=http://nats:4222 ports: - 4000:4000 networks: - app sms: image: nurettinsenbackend/bestnetsms restart: on-failure depends_on: - nats environment: - NATS_URL=http://nats:4222 ports: - 6000:6000 networks: - app networks: app: driver: bridge
核心排查与修复点
- 端口不匹配问题:
Docker Compose中postgres容器映射的是5732:5732,但后端启动命令里用nc -z postgresql 5432检测的是默认5432端口,同时数据源配置里的DB_PORT未在backend环境变量中设置。要么把postgres容器的内部端口改回默认5432(映射外部5732,即ports: - '5732:5432'),要么在backend的environment中添加DB_PORT=5732,并把启动命令里的检测端口改成5732。 - 缺失环境变量:
backend服务的environment中缺少DB_USER和DB_NAME,虽然postgres默认用户是postgres,默认数据库名也是postgres,但显式配置更稳妥,添加- DB_USER=postgres和- DB_NAME=postgres到backend的环境变量中。 - 数据源初始化时机:
确保databaseSource.init()在应用启动时被调用,且必须等待初始化完成后再启动HTTP服务或处理请求。比如在main函数中先执行await databaseSource.init(),再启动服务。 - 事务调用时机:
确认在调用dbSource.manager.transaction之前,数据源已经完成初始化。如果应用还没建立数据库连接就触发请求,必然会出现driver not connected错误。
内容的提问来源于stack exchange,提问作者Kerem Esen
相关产品推荐
相关产品推荐

