Dockerization Support and Externalised Configs
Added externalised configuration with @nestjs/config. Added Dockerfile to create image for twitter-node-backend project Added docker-compose.yml file to run the project and postgres database in one run. Updated README.MD file for docker instruction,
@championswimmer @ohbus @subhatanay
Here's one way of how we could dockerize the entire application and keep track of different environments easily.
- [x] Dockerfile
# Specify the base image
FROM node:14-alpine
# Create app directory, this is in our container/in our image
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
# If you are building your code for production
# RUN npm ci --only=production
RUN npm install
# Bundle app source
COPY . .
# Build the app
RUN npm run build
# Set the node env to production
ENV NODE_ENV=production
# Expose the necessary port
EXPOSE 3000
# * This is a wait script which you're
# * required to execute before you run
# * your app
# ? Reason:
# * Even if your db instance starts up,
# * it still takes some time to get
# * ready to accept connections from
# * your API, so this wait script takes
# * care of it by applying a retry logic
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait
# Finally, run your app
CMD /wait && npm run start:prod
- [x] docker-compose.yml
version: '3'
services:
api:
build: .
ports:
- '3000:3000'
depends_on:
- db
environment:
WAIT_HOSTS: db:5432
db:
image: postgres:13-alpine
ports:
- '5432:5432'
volumes:
- './db-data:/var/lib/postgresql/data'
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
- [x] .dockerignore
.dockerignore
.git
.gitignore
node_modules
.env*
.vscode
npm-debug.log
Dockerfile*
docker-compose*
README.md
LICENSE
dist
- [x] .env.dev
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=mooadmin
POSTGRES_PASSWORD=moopass
POSTGRES_DB=moodb
PORT=3000
ADDRESS=127.0.0.1
- [x] .env.production
POSTGRES_HOST=db
POSTGRES_PORT=5432
POSTGRES_USER=mooadmin
POSTGRES_PASSWORD=moopass
POSTGRES_DB=moodb
PORT=3000
ADDRESS=0.0.0.0
- [x] app.module.ts
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: process.env.NODE_ENV
? `.env.${process.env.NODE_ENV}`
: '.env.dev',
}),
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.POSTGRES_HOST,
port: process.env.POSTGRES_PORT as unknown as number,
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DB,
synchronize: true,
logger: 'advanced-console',
logging: 'all',
entities: [UserEntity, PostEntity, PasswordEntity, SessionsEntity],
}),
UsersModule,
PostsModule,
HashtagsModule,
AuthModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
- [x] main.ts
await app.listen(process.env.PORT, process.env.ADDRESS);
- [x] package.json
{
"name": "twitter-backend-node",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/src/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest --config ./jest-e2e.json",
"test:watch": "jest --watch",
"test:cov": "jest --config ./jest-e2e.json --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^7.6.15",
"@nestjs/config": "^1.0.0",
"@nestjs/core": "^7.6.15",
"@nestjs/platform-fastify": "^7.6.18",
"@nestjs/swagger": "^4.8.1",
"@nestjs/typeorm": "^7.1.5",
"bcrypt": "^5.0.1",
"fastify-compress": "^3.6.0",
"fastify-swagger": "^4.8.0",
"pg": "^8.6.0",
"pg-hstore": "^2.3.4",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.6.6",
"typeorm": "^0.2.34"
},
"devDependencies": {
"@nestjs/cli": "^7.6.0",
"@nestjs/schematics": "^7.3.0",
"@nestjs/testing": "^7.6.15",
"@types/bcrypt": "^5.0.0",
"@types/jest": "^26.0.22",
"@types/node": "^14.14.36",
"@types/supertest": "^2.0.10",
"@typescript-eslint/eslint-plugin": "^4.19.0",
"@typescript-eslint/parser": "^4.19.0",
"eslint": "^7.22.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"jest": "^26.6.3",
"prettier": "^2.2.1",
"supertest": "^6.1.3",
"ts-jest": "^26.5.4",
"ts-loader": "^8.0.18",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
after docker compose

after health check

after create-user request

The dockerfile @alpha037 suggested is better, it takes care of the pg spinup time
@alpha037 @ohbus any updates on this ?
@alpha037 @ohbus any updates on this ?
Haven't heard back from @subhatanay yet. Let's wait for a couple of days and see if he modifies his PR accordingly, otherwise I'll raise one, if that's okay.
Sorry for late reply ... I will push this by tomorrow
Hi @alpha037 I have used the suggestion you provided. please check and let me know any issue.
Please check now.
Hi @alpha037 addressed your comment. Please check now thanks
Hi @ohbus can this PR be merged? or do you want more changes?
let me know thanks
Hi @ohbus can this PR be merged? or do you want more changes?
let me know thanks
@championswimmer you may merge this.