From 93da6283629660eb67261f60592649bc93c4d4fd Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Sat, 27 Dec 2025 00:36:26 -0300 Subject: [PATCH] chore: optimize Dockerfiles (distroless) and align JWT config - Optimized Backoffice Dockerfile: node:22-alpine -> gcr.io/distroless/nodejs22-debian12 - Optimized BFF Dockerfile: python:3.12-slim -> gcr.io/distroless/python3-debian12 - Updated Backoffice Auth to use JWT_SECRET for local verification - Updated .env.example with correct env vars --- backoffice/.env.example | 2 +- backoffice/Dockerfile | 22 ++++++++----------- backoffice/src/auth/auth.module.ts | 6 ++--- .../src/auth/strategies/jwt.strategy.ts | 2 +- saveinmed-bff/Dockerfile | 20 ++++++----------- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/backoffice/.env.example b/backoffice/.env.example index 688f6c9..0edc61b 100644 --- a/backoffice/.env.example +++ b/backoffice/.env.example @@ -1,4 +1,4 @@ DATABASE_URL=postgresql://user:password@host:port/dbname?schema=public -JWT_SECRET=secret-key +JWT_SECRET=dev-secret PORT=3000 API_URL=http://localhost:3000 diff --git a/backoffice/Dockerfile b/backoffice/Dockerfile index 5580c41..8b7b861 100644 --- a/backoffice/Dockerfile +++ b/backoffice/Dockerfile @@ -19,26 +19,22 @@ COPY . . RUN pnpm prisma:generate && pnpm build # ===== STAGE 4: Production ===== -FROM node:22-alpine AS production -# Cria usuário não-root -RUN addgroup --system --gid 1001 nodejs && \ - adduser --system --uid 1001 nestjs +# ===== STAGE 4: Production (Distroless) ===== +FROM gcr.io/distroless/nodejs22-debian12:nonroot WORKDIR /app # Copia apenas o necessário para produção -COPY --from=build --chown=nestjs:nodejs /app/dist ./dist -COPY --from=build --chown=nestjs:nodejs /app/prisma ./prisma -COPY --from=build --chown=nestjs:nodejs /app/node_modules/.prisma ./node_modules/.prisma -COPY --from=build --chown=nestjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma -COPY --from=deps --chown=nestjs:nodejs /app/node_modules ./node_modules -COPY --chown=nestjs:nodejs package.json ./ +COPY --from=build --chown=nonroot:nonroot /app/dist ./dist +COPY --from=build --chown=nonroot:nonroot /app/prisma ./prisma +COPY --from=build --chown=nonroot:nonroot /app/node_modules/.prisma ./node_modules/.prisma +COPY --from=build --chown=nonroot:nonroot /app/node_modules/@prisma ./node_modules/@prisma +COPY --from=deps --chown=nonroot:nonroot /app/node_modules ./node_modules +COPY --chown=nonroot:nonroot package.json ./ ENV NODE_ENV=production -USER nestjs - EXPOSE 3000 -CMD ["node", "dist/main.js"] +CMD ["dist/main.js"] diff --git a/backoffice/src/auth/auth.module.ts b/backoffice/src/auth/auth.module.ts index 32735cc..f03c84d 100644 --- a/backoffice/src/auth/auth.module.ts +++ b/backoffice/src/auth/auth.module.ts @@ -19,8 +19,8 @@ import { RefreshTokenStrategy } from './strategies/refresh-token.strategy'; imports: [ConfigModule], inject: [ConfigService], useFactory: async (configService: ConfigService) => ({ - secret: configService.get('JWT_ACCESS_SECRET') || 'access-secret', - signOptions: { expiresIn: configService.get('JWT_ACCESS_EXPIRES', '15m') }, + secret: configService.get('JWT_SECRET') || 'dev-secret', + signOptions: { expiresIn: configService.get('JWT_EXPIRES_IN', '24h') }, }), }), PrismaModule, @@ -30,4 +30,4 @@ import { RefreshTokenStrategy } from './strategies/refresh-token.strategy'; controllers: [AuthController], exports: [JwtAuthGuard, RefreshTokenGuard, AuthService], }) -export class AuthModule {} +export class AuthModule { } diff --git a/backoffice/src/auth/strategies/jwt.strategy.ts b/backoffice/src/auth/strategies/jwt.strategy.ts index 7844e32..48797a6 100644 --- a/backoffice/src/auth/strategies/jwt.strategy.ts +++ b/backoffice/src/auth/strategies/jwt.strategy.ts @@ -10,7 +10,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, - secretOrKey: configService.get('JWT_ACCESS_SECRET') || 'access-secret', + secretOrKey: configService.get('JWT_SECRET') || 'dev-secret', }); } diff --git a/saveinmed-bff/Dockerfile b/saveinmed-bff/Dockerfile index 2b64971..c52c1ed 100644 --- a/saveinmed-bff/Dockerfile +++ b/saveinmed-bff/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 # ===== STAGE 1: Builder ===== -FROM python:3.12-slim AS builder +FROM python:3.11-slim AS builder WORKDIR /build @@ -16,29 +16,23 @@ RUN --mount=type=cache,target=/root/.cache/pip \ pip install --upgrade pip && \ pip install -r requirements.txt -# ===== STAGE 2: Production ===== -FROM python:3.12-slim AS production +# ===== STAGE 2: Production (Distroless) ===== +FROM gcr.io/distroless/python3-debian12:nonroot # Variáveis de ambiente Python otimizadas ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ - PATH="/opt/venv/bin:$PATH" + PYTHONPATH="/opt/venv/lib/python3.11/site-packages" WORKDIR /app -# Copia virtualenv do builder -COPY --from=builder /opt/venv /opt/venv +# Copia virtualenv do builder (apenas site-packages pois distroless já tem python) +COPY --from=builder /opt/venv/lib/python3.11/site-packages /opt/venv/lib/python3.11/site-packages # Copia código fonte COPY src ./src -# Cria usuário não-root -RUN useradd --system --no-create-home --uid 1001 appuser && \ - chown -R appuser:appuser /app - -USER appuser - EXPOSE 8000 # Uvicorn com workers otimizados -CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"] +CMD ["/opt/venv/lib/python3.11/site-packages/bin/uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]