node.jsamazon-web-servicesdockernestjsamazon-ecs

AWS ECS Service Envs are undefined


Heres my dockerfile:

FROM --platform=linux/amd64 alpine:latest 

WORKDIR /usr/app

RUN apk add --no-cache nodejs npm

COPY . .

RUN npm install

RUN npm run build

# Start the server using the production build
CMD [ "node", "dist/main.js" ]

Here is my docker-compose.yaml file:


services:
  iu-app:
    restart: always
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 3000:3000
    environment:
      - NODE_ENV=production
      - PORT=3000
      - MONGODB_URI=<db uris are same as env.>
      - JWT_SECRET=JWT_SECRET=verysecretkey
      - JWT_EXPIRES=7d
    command: npm run start:prod

dockerignore: node_modules

my app.module.ts file:

import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { UsersModule } from './users/users.module';
import { TeachersModule } from './teachers/teachers.module';
import { AuthModule } from './auth/auth.module';
import { MailerModule } from './mailer/mailer.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: '.env',
    }),
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: '7d' },
      global: true,
    }),
    MongooseModule.forRoot(process.env.MONGODB_URI),
    UsersModule,
    TeachersModule,
    AuthModule,
    MailerModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
console.log('process.env.JWT_SECRET', process.env.JWT_SECRET);
console.log('process.env.MONGODB_URI', process.env.MONGODB_URI);

When i run my docker or my docker-compose, i can see the 'process.env.JWT_SECRET' and 'process.env.MONGODB_URI' logs.

But when i go to my ECS SERVICE logs I got these:enter image description here also the logs 'process.env.JWT_SECRET' and 'process.env.MONGODB_URI' logged undefined

Also, here is my github actions yml file:

---
name: Build and Push Node.js Docker image to AWS ECR
on:
  push:
    branches: [master]
jobs:
  build-and-push:
    name: Build and Push to ECR
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: eu-west-1

      - name: Login to AWS ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ui-app-be
          IMAGE_TAG: latest
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      - name: Download task definition
        run: |
          aws ecs describe-task-definition --task-definition iu-app-task --query taskDefinition > task-definition.json

      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: iu-app-container
          image: ${{ steps.build-image.outputs.image }}

      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: iu-app-servicev2
          cluster: iu-app-cluster
          wait-for-service-stability: true
```

Solution

  • As @Mark already mentioned in the comments below your question, you need to pass configuration options and secrets to the ECS Container via the corresponding configuration section in ECS Task Definition.

    In order to follow best practices it is better to not pass secrets as plain text and use the service that allows to pass it in a safe way. If you're in the AWS ecosystem you might want to consider using AWS Secrets Manager.

    Here steps you need to take:

    1. Navigate to Secrets Manager and create a new secret. Put your secrets into the dictionary.

    2. In the Task Definition in for your service create a new revision and add references secrets you created.

    If you're using JSON definition they will be something like this:

    {
      "containerDefinitions": [{
        "secrets": [{
          "name": "JWT_SECRET",
          "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:your_secret_name: JWT_SECRET::"
        }]
      }]
    }
    

    In case of UI, you need to add an environment variable, choose the name, select valueFrom and paste a arn of the secret with the field you're referencing too.