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

Docker化Nest.js应用无法读取.env文件变量问题排查

问题:Docker化Nest.js应用无法读取.env环境变量

我有一个已Docker化的Nest.js应用,包含server、PostgreSQL数据库和pgAdmin4三个服务,原本运行正常,但后来发现项目根目录下的.env文件中的变量无法被读取:调用ConfigService的configService.get()方法始终返回undefined,直接使用process.env.VARIABLE也得到同样结果,在配置JWT策略认证时发现了这个问题。项目通过docker-compose up启动,代码来自一个未Docker化的项目。

相关代码及配置文件

main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { TransformInterceptor } from './transform.interceptor';
import { ConfigService } from '@nestjs/config';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  const configService = app.get(ConfigService);

  app.enableCors();
  app.useGlobalPipes(new ValidationPipe());
  app.useGlobalInterceptors(new TransformInterceptor());

  const port = configService.get('PORT');
  const secret = configService.get('JWT_SECRET');

  // const port = process.env.PORT;
  // const secret = process.env.JWT_SECRET;

  console.log('port', port, 'secret', secret);

  await app.listen(port || 4250);
}
bootstrap();

app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from './users/users.module';
import { TaskModule } from './task/task.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
// import { ConfigService } from '@nestjs/config/dist';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: `.env`,
    }),
    // TypeOrmModule.forRoot({
    //   type: 'postgres',
    //   host: 'db',
    //   port: 5432,
    //   username: 'postgres',
    //   password: 'postgres',
    //   database: 'postgres',
    //   autoLoadEntities: true,
    //   synchronize: true,
    // }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        const isProduction = configService.get('STAGE') === 'prod';
        return {
          ssl: isProduction,
          extra: {
            ssl: isProduction ? { rejectUnauthorized: false } : null,
          },
          type: 'postgres',
          autoLoadEntities: true,
          synchronize: true,
          // host: configService.get('DB_HOST'),
          // port: configService.get('DB_PORT'),
          // username: configService.get('DB_USERNAME'),
          // password: configService.get('DB_PASSWORD'),
          // database: configService.get('DB_DATABASE'),
          host: 'db',
          port: 5432,
          username: 'postgres',
          password: 'postgres',
          database: 'postgres',
        };
      },
    }),
    UsersModule,
    TaskModule,
  ],
})
export class AppModule {}

Dockerfile

FROM node:18-alpine AS base

WORKDIR /app
COPY package*.json ./

## dev ##
FROM base AS dev
RUN npm i --frozen-lockfile
COPY . .
CMD ["npm", "run", "start:dev"]


## prod ##
FROM base AS prod
RUN npm ci --frozen-lockfile
COPY . .
RUN npm run build 
CMD ["npm", "run", "start:prod"]

docker-compose.yml

version: '3.9'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    ports:
      - 4250:4250
    volumes:
      - ./src:/app/src
    depends_on:
      - db

  db:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    environment:
      POSTGRES_PASSWORD: postgres
  
  dbadmin:
    image: dpage/pgadmin4
    restart: always
    ports:
      - 5050:80
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@admin.com
      PGADMIN_DEFAULT_PASSWORD: pgadmin4

.env

JWT_SECRET=SUPERsecret123PAssWORd
PORT=4250

DB_HOST=db
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_DATABASE=postgres

请问我遗漏了什么配置?是否应该弃用.env文件,转而在docker-compose.yml中定义所有变量?


解决方案

1. 核心问题:.env文件未被挂载到容器内

你的docker-compose.yml中只挂载了./src目录到容器的/app/src,但根目录下的.env文件并没有被挂载进去,也没有通过其他方式传递给容器。容器内的应用无法访问宿主机上的.env文件,自然读取不到变量。

2. 修复方式(二选一即可)

方式一:挂载.env文件到容器

修改docker-compose.yml中的app服务配置,添加.env文件的挂载:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    ports:
      - 4250:4250
    volumes:
      - ./src:/app/src
      - ./.env:/app/.env  # 新增这一行,挂载.env文件
    depends_on:
      - db

方式二:在docker-compose.yml中定义环境变量

如果不想使用.env文件,可以直接在docker-compose.yml的app服务里通过environment字段定义变量,或者通过env_file字段引入整个.env文件:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: dev
    ports:
      - 4250:4250
    volumes:
      - ./src:/app/src
    environment:
      - JWT_SECRET=SUPERsecret123PAssWORd
      - PORT=4250
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USERNAME=postgres
      - DB_PASSWORD=postgres
      - DB_DATABASE=postgres
    # 或者用env_file直接引入整个.env文件:
    # env_file:
    #   - ./.env
    depends_on:
      - db

3. 额外注意事项

  • 如果使用挂载.env的方式,确保宿主机上的.env文件路径正确,容器内的路径要和ConfigModule.forRoot中envFilePath配置的一致(你这里是.env,对应容器内/app/.env,挂载路径匹配)。
  • 开发环境下,挂载.env文件更方便修改后实时生效;生产环境建议使用docker-compose.yml的environment字段或者Docker secrets来管理敏感变量,避免.env文件泄露。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:35:01