Skip to content

Commit bcf473e

Browse files
Merge branch 'devops/docker-implementation'
2 parents 9b25d97 + 2b5f72f commit bcf473e

File tree

130 files changed

+16994
-2675
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+16994
-2675
lines changed

.github/workflows/deploy.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: '🚀 Deploy NestJS API Docker App'
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
build-and-deploy:
9+
runs-on: self-hosted
10+
name: '🐳 Build & Deploy'
11+
12+
steps:
13+
- name: '🔍 Checkout Code'
14+
uses: actions/checkout@v4
15+
16+
- name: '🔒 Verify SSH Secrets Exist'
17+
run: |
18+
missing=0
19+
for var in SERVER_HOST SERVER_USER SERVER_SSH_KEY; do
20+
# Use indirect expansion to check each env var
21+
if [ -z "${!var}" ]; then
22+
echo "❌ Critical error: Secret $var is missing!"
23+
missing=1
24+
else
25+
echo "✅ Secret $var is present"
26+
fi
27+
done
28+
if [ $missing -ne 0 ]; then
29+
exit 1
30+
fi
31+
env:
32+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
33+
SERVER_USER: ${{ secrets.SERVER_USER }}
34+
SERVER_SSH_KEY: ${{ secrets.SERVER_SSH_KEY }}
35+
36+
- name: '🐳 Log in to GitHub Container Registry'
37+
uses: docker/login-action@v2
38+
with:
39+
registry: ghcr.io
40+
username: ${{ github.actor }}
41+
password: ${{ secrets.GITHUB_TOKEN }}
42+
43+
- name: '📦 Build & Push Docker Image'
44+
uses: docker/build-push-action@v3
45+
with:
46+
context: .
47+
push: true
48+
tags: ghcr.io/codebuilderinc/codebuilder-api:latest
49+
env:
50+
BUILDKIT_PROGRESS: plain
51+
52+
- name: '🚀 Deploy to Remote Server'
53+
if: github.ref == 'refs/heads/main'
54+
uses: appleboy/ssh-action@v0.1.6
55+
with:
56+
host: ${{ secrets.SERVER_HOST }}
57+
username: ${{ secrets.SERVER_USER }}
58+
key: ${{ secrets.SERVER_SSH_KEY }}
59+
script: |
60+
echo "➡️ Ensuring Docker network 'codebuilder-net' exists..."
61+
if ! docker network ls | grep -q codebuilder-net; then
62+
echo "🆕 Creating network codebuilder-net"
63+
docker network create codebuilder-net
64+
else
65+
echo "✔️ Network codebuilder-net already exists"
66+
fi
67+
68+
echo "➡️ Ensuring database container is running..."
69+
if docker ps -a --format '{{.Names}}' | grep -q '^nest-db$'; then
70+
if ! docker ps --format '{{.Names}}' | grep -q '^nest-db$'; then
71+
echo "🟡 Starting existing 'nest-db' container..."
72+
docker start nest-db
73+
else
74+
echo "✔️ Database container 'nest-db' is already running"
75+
fi
76+
else
77+
echo "🆕 Deploying fresh database container..."
78+
docker-compose -f docker-compose.nest.yml up -d db
79+
fi
80+
81+
echo "⏳ Waiting for database to be healthy on db:5432..."
82+
until nc -z db 5432; do sleep 1; done
83+
echo "✅ Database is healthy"
84+
85+
echo "➡️ Pulling latest NestJS image..."
86+
docker pull ghcr.io/codebuilderinc/codebuilder-api:latest
87+
88+
echo "🔄 Deploying NestJS API service on port 4000..."
89+
docker-compose -f docker-compose.nest.yml up -d --no-deps nest-api
90+
91+
- name: '🗑️ Prune Old Docker Images'
92+
if: always()
93+
run: docker image prune -af

.prettierrc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@
77
"trailingComma": "es5",
88
"bracketSpacing": true,
99
"arrowParens": "always",
10-
"endOfLine": "lf"
10+
"endOfLine": "lf",
11+
"editor.formatOnSave": true,
12+
"jsxSingleQuote": false
1113
}

.vscode/settings.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"sqltools.connections": [
3+
{
4+
"mysqlOptions": {
5+
"authProtocol": "default",
6+
"enableSsl": "Disabled"
7+
},
8+
"previewLimit": 50,
9+
"server": "localhost",
10+
"port": 3306,
11+
"driver": "MariaDB",
12+
"name": "MySQL",
13+
"database": "codebuilder_main",
14+
"username": "codebuilder",
15+
"password": "joker123"
16+
}
17+
]
18+
}

Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# syntax=docker/dockerfile:1
2+
FROM node:24-alpine
3+
4+
# install pnpm globally
5+
RUN npm install -g pnpm
6+
7+
# your working dir in container
8+
WORKDIR /usr/src/app
9+
10+
# copy only manifest and lockfile, install prod deps
11+
COPY package.json pnpm-lock.yaml ./
12+
RUN pnpm install --prod
13+
14+
# copy source & build
15+
COPY . .
16+
RUN pnpm build
17+
18+
# ensure entrypoint is executable
19+
RUN chmod +x docker-entrypoint.sh
20+
21+
# expose the NestJS port
22+
EXPOSE 4000
23+
24+
# run migrations then start
25+
ENTRYPOINT ["./docker-entrypoint.sh"]

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ Check out a few resources that may come in handy when working with NestJS:
8383
- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs).
8484
- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com).
8585

86+
![Database Schema](./dbml/schema.png)
87+
![DB Schema](https://raw.github.com/codebuilderinc/<codebuilder-api/<main/dbml/schema.png)
88+
8689
## Support
8790

8891
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).

default.json

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
{
2+
"APP_SETTINGS": {
3+
"port": 8090,
4+
"body_limit": "50mb",
5+
"body_parameter_limit": 50000
6+
},
7+
"JWT_ACCESS_SECRET": "tasdasdklaslkdaslkd",
8+
"CORS_SETTINGS": {
9+
"allowed_origins": [],
10+
"allowed_paths": [],
11+
"allowed_methods": [
12+
"GET",
13+
"POST",
14+
"PUT",
15+
"PATCH",
16+
"DELETE",
17+
"OPTIONS"
18+
],
19+
"allowed_credentials": false,
20+
"allowed_headers": []
21+
},
22+
"LOGGER_SETTINGS": {
23+
"level": "info",
24+
"silence": [
25+
"healthz"
26+
]
27+
},
28+
"DB_SETTINGS": {
29+
"host": "pg-1.dexcelerate.com",
30+
"port": 5432,
31+
"username": "nestjswebsockettest",
32+
"password": "joker123!",
33+
"database": "nestjswebsockettest",
34+
"logging": "all",
35+
"synchronize": true
36+
},
37+
"JWT_SETTINGS": {
38+
"secret_key": "secret_key",
39+
"algorithm": "HS512",
40+
"access_token_expires_in": 20,
41+
"refresh_token_expires_in": 10080
42+
},
43+
"REDIS_SETTINGS": {
44+
"host": "redis-1.dexcelerate.com",
45+
"port": 7001,
46+
"key": "nestjs_example"
47+
},
48+
"REDIS_SERVERS": {
49+
"STANDALONE": {
50+
"host": "redis-1.dexcelerate.com",
51+
"port": 6379,
52+
"tls": true,
53+
"password": "aslkdjkkjadwkljdaslkjdwqklqajd39821ikdjal"
54+
},
55+
"RATE": {
56+
"host": "redis-1.dexcelerate.com",
57+
"port": 3788,
58+
"tls": false,
59+
"password": "aslkdjkkjadwkljdaslkjdwqklqajd39821ikdjal"
60+
},
61+
"AUTH": {
62+
"host": "redis-1.dexcelerate.com",
63+
"port": 7001,
64+
"tls": true,
65+
"password": "aslkdjkkjadwkljdaslkjdwqklqajd39821ikdjal"
66+
},
67+
"TOKENS": {
68+
"host": "redis-1.dexcelerate.com",
69+
"port": 7001,
70+
"tls": true,
71+
"password": "aslkdjkkjadwkljdaslkjdwqklqajd39821ikdjal"
72+
},
73+
"CHAT": {
74+
"host": "redis-1.dexcelerate.com",
75+
"port": 7001,
76+
"tls": true,
77+
"password": "aslkdjkkjadwkljdaslkjdwqklqajd39821ikdjal"
78+
}
79+
},
80+
"WSS_SETTINGS": {
81+
"port": 8091,
82+
"ping_interval": 3000,
83+
"ping_timeout": 10000,
84+
"path": "/socket.io"
85+
},
86+
"RABBITMQ_SETTINGS": {
87+
"exchange": "nestjs_example_service",
88+
"name": "rabbitmq",
89+
"host": "localhost",
90+
"vhost": "vhost",
91+
"port": 5672,
92+
"username": "admin",
93+
"password": "password"
94+
},
95+
"GRAPHQL_SETTINGS": {
96+
"playground": true,
97+
"debug": true,
98+
"introspection": true,
99+
"installSubscriptionHandlers": true
100+
},
101+
"GRAPHQL_APIS": {
102+
"api_1": "http://localhost:8090/graphql",
103+
"api_2": "http://localhost:8091/graphql"
104+
},
105+
"GRAPHQL_GUARD": {
106+
"username": "admin",
107+
"password": "password"
108+
}
109+
}

docker-compose.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
version: '3.8'
2+
3+
services:
4+
db:
5+
image: postgres:13-alpine
6+
container_name: nest-db
7+
environment:
8+
POSTGRES_USER: ${DB_USER:-nestjs}
9+
POSTGRES_PASSWORD: ${DB_PASSWORD:-nestpass}
10+
POSTGRES_DB: ${DB_NAME:-nestdb}
11+
volumes:
12+
- db-data:/var/lib/postgresql/data
13+
networks:
14+
- codebuilder-net
15+
16+
nest-api:
17+
build:
18+
context: .
19+
dockerfile: Dockerfile
20+
container_name: nest-api
21+
environment:
22+
DB_HOST: db
23+
DB_PORT: 5432
24+
DB_USER: ${DB_USER:-nestjs}
25+
DB_PASSWORD: ${DB_PASSWORD:-nestpass}
26+
DB_NAME: ${DB_NAME:-nestdb}
27+
PORT: 4000
28+
ports:
29+
- "4000:4000"
30+
depends_on:
31+
- db
32+
entrypoint: ["./docker-entrypoint.sh"]
33+
networks:
34+
- codebuilder-net
35+
36+
volumes:
37+
db-data:
38+
39+
networks:
40+
codebuilder-net:
41+
external: true

docker-entrypoint.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env sh
2+
#
3+
# Entrypoint for NestJS container.
4+
# - waits for the database
5+
# - runs migrations
6+
# - starts the app
7+
8+
set -e
9+
10+
# Color codes for output
11+
RED='\033[0;31m'
12+
GREEN='\033[0;32m'
13+
YELLOW='\033[1;33m'
14+
BLUE='\033[0;34m'
15+
NC='\033[0m' # No Color
16+
17+
export FORCE_COLOR=1
18+
export NODE_ENV=${NODE_ENV:-production}
19+
20+
DB_HOST=${DB_HOST:-db}
21+
DB_PORT=${DB_PORT:-5432}
22+
23+
echo -e "${BLUE}🐳 Starting NestJS application...${NC}"
24+
echo -e "${YELLOW}⏳ Waiting for database at ${DB_HOST}:${DB_PORT}...${NC}"
25+
26+
# Wait until the DB port is open
27+
while ! nc -z $DB_HOST $DB_PORT; do
28+
sleep 1
29+
done
30+
31+
echo -e "${GREEN}✅ Database is ready.${NC}"
32+
echo -e "${YELLOW}🔄 Running database migrations...${NC}"
33+
34+
# run migrations (adjust script name if needed)
35+
pnpm run migration:run
36+
37+
echo -e "${GREEN}✅ Migrations complete.${NC}"
38+
echo -e "${BLUE}🚀 Launching NestJS (prod)...${NC}"
39+
40+
# Replace this shell with the main process (PID 1)
41+
exec node dist/main.js

eslint.config.mjs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,17 @@ export default tseslint.config(
2626
},
2727
{
2828
rules: {
29-
'@typescript-eslint/no-explicit-any': 'off',
30-
'@typescript-eslint/no-floating-promises': 'warn',
31-
'@typescript-eslint/no-unsafe-argument': 'warn'
29+
'@typescript-eslint/no-explicit-any': 'off',
30+
'@typescript-eslint/no-floating-promises': 'off',
31+
'@typescript-eslint/no-unsafe-call': 'off',
32+
'@typescript-eslint/no-unsafe-return': 'off',
33+
'@typescript-eslint/no-unsafe-member-access': 'off',
34+
'@typescript-eslint/no-unsafe-argument': 'off',
35+
'@typescript-eslint/interface-name-prefix': 'off',
36+
'@typescript-eslint/no-unsafe-assignment': 'off',
37+
'@typescript-eslint/explicit-function-return-type': 'off',
38+
'@typescript-eslint/explicit-module-boundary-types': 'off',
39+
'@typescript-eslint/no-unused-vars': 'off',
3240
},
3341
},
3442
);

0 commit comments

Comments
 (0)