Legioniście, nadszedł czas na wielką kampanię — stworzenie kompletnej konfiguracji deployment dla naszej aplikacji NestJS! W tym projekcie połączysz całą wiedzę z tego modułu: Docker, Docker Compose, CI/CD, health checks, logging i bezpieczeństwo.
Stworzymy pełny pipeline wdrożeniowy składający się z:
1# ETAP BUDOWANIA
2FROM node:20-alpine AS builder
3WORKDIR /app
4COPY package.json yarn.lock ./
5RUN yarn install --frozen-lockfile
6COPY . .
7RUN yarn build
8RUN yarn install --frozen-lockfile --production
9
10# ETAP PRODUKCYJNY
11FROM node:20-alpine AS production
12WORKDIR /app
13RUN addgroup -g 1001 -S nodejs && \
14 adduser -S nestjs -u 1001
15COPY /app/dist ./dist
16COPY /app/node_modules ./node_modules
17COPY /app/package.json ./package.json
18USER nestjs
19EXPOSE 4000
20HEALTHCHECK \
21 CMD wget --no-verbose --tries=1 --spider http://localhost:4000/health || exit 1
22CMD ["node", "dist/main"]1version: '3.8'
2services:
3 api:
4 build:
5 context: .
6 target: production
7 ports:
8 - '4000:4000'
9 environment:
10 - NODE_ENV=production
11 - DATABASE=mongodb://imperator:roma2024@mongodb:27017/roman-imperium?authSource=admin
12 - REDIS_HOST=redis
13 - PORT=4000
14 depends_on:
15 mongodb:
16 condition: service_healthy
17 redis:
18 condition: service_started
19 networks:
20 - imperium-net
21 restart: unless-stopped
22
23 mongodb:
24 image: mongo:7.0
25 environment:
26 - MONGO_INITDB_ROOT_USERNAME=imperator
27 - MONGO_INITDB_ROOT_PASSWORD=roma2024
28 volumes:
29 - mongo-data:/data/db
30 networks:
31 - imperium-net
32 healthcheck:
33 test: echo 'db.runCommand("ping").ok' | mongosh --quiet
34 interval: 10s
35 timeout: 5s
36 retries: 5
37
38 redis:
39 image: redis:7-alpine
40 command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
41 volumes:
42 - redis-data:/data
43 networks:
44 - imperium-net
45
46volumes:
47 mongo-data:
48 redis-data:
49
50networks:
51 imperium-net:
52 driver: bridge1name: Deploy Imperium
2on:
3 push:
4 branches: [main]
5 pull_request:
6 branches: [main]
7
8jobs:
9 test:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v4
13 - uses: actions/setup-node@v4
14 with:
15 node-version: 20
16 cache: 'yarn'
17 - run: yarn install --frozen-lockfile
18 - run: yarn lint
19 - run: yarn test --coverage
20 - run: yarn build
21
22 deploy:
23 needs: test
24 runs-on: ubuntu-latest
25 if: github.ref == 'refs/heads/main'
26 steps:
27 - uses: actions/checkout@v4
28 - uses: docker/build-push-action@v5
29 with:
30 context: .
31 push: true
32 tags: imperator/roman-imperium:latest1// health/health.controller.ts
2@Controller('health')
3export class HealthController {
4 constructor(
5 private health: HealthCheckService,
6 private mongoose: MongooseHealthIndicator,
7 private memory: MemoryHealthIndicator,
8 ) {}
9
10 @Get()
11 @HealthCheck()
12 check() {
13 return this.health.check([
14 () => this.mongoose.pingCheck('mongodb'),
15 () => this.memory.checkHeap('memory', 300 * 1024 * 1024),
16 ]);
17 }
18}1// main.ts
2import { WinstonModule } from 'nest-winston';
3import * as winston from 'winston';
4
5const app = await NestFactory.create(AppModule, {
6 logger: WinstonModule.createLogger({
7 transports: [
8 new winston.transports.Console({
9 format: winston.format.combine(
10 winston.format.timestamp(),
11 winston.format.json(),
12 ),
13 }),
14 ],
15 }),
16});1// main.ts
2import helmet from 'helmet';
3import compression from 'compression';
4
5app.use(helmet());
6app.use(compression());
7app.enableCors({
8 origin: process.env.ALLOWED_ORIGINS?.split(','),
9 credentials: true,
10});
11app.useGlobalPipes(new ValidationPipe({
12 whitelist: true,
13 forbidNonWhitelisted: true,
14 transform: true,
15}));1const deploymentChecklist = {
2 docker: [
3 'Multi-stage Dockerfile',
4 'Non-root user',
5 '.dockerignore',
6 'Health check w Dockerfile',
7 ],
8 compose: [
9 'API + MongoDB + Redis',
10 'Health checks na serwisach',
11 'Wolumeny dla trwałych danych',
12 'Izolowana sieć',
13 ],
14 cicd: [
15 'Lint + Test + Build',
16 'Docker build i push',
17 'Sekrety w GitHub Secrets',
18 ],
19 security: [
20 'Helmet headers',
21 'CORS konfiguracja',
22 'Rate limiting',
23 'ValidationPipe',
24 'Compression',
25 ],
26 monitoring: [
27 'Health check endpoint',
28 'Structured logging (JSON)',
29 'Log rotation',
30 ],
31};Gratulacje, legioniście! Ukończyłeś wielką kampanię — masz teraz pełny pipeline wdrożeniowy dla swojej aplikacji NestJS. Drogi Imperium prowadzą od kodu źródłowego aż do produkcji!