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
This commit is contained in:
Tiago Yamamoto 2025-12-27 00:36:26 -03:00
parent d1d2f3f338
commit 93da628362
5 changed files with 21 additions and 31 deletions

View file

@ -1,4 +1,4 @@
DATABASE_URL=postgresql://user:password@host:port/dbname?schema=public DATABASE_URL=postgresql://user:password@host:port/dbname?schema=public
JWT_SECRET=secret-key JWT_SECRET=dev-secret
PORT=3000 PORT=3000
API_URL=http://localhost:3000 API_URL=http://localhost:3000

View file

@ -19,26 +19,22 @@ COPY . .
RUN pnpm prisma:generate && pnpm build RUN pnpm prisma:generate && pnpm build
# ===== STAGE 4: Production ===== # ===== STAGE 4: Production =====
FROM node:22-alpine AS production
# Cria usuário não-root # ===== STAGE 4: Production (Distroless) =====
RUN addgroup --system --gid 1001 nodejs && \ FROM gcr.io/distroless/nodejs22-debian12:nonroot
adduser --system --uid 1001 nestjs
WORKDIR /app WORKDIR /app
# Copia apenas o necessário para produção # Copia apenas o necessário para produção
COPY --from=build --chown=nestjs:nodejs /app/dist ./dist COPY --from=build --chown=nonroot:nonroot /app/dist ./dist
COPY --from=build --chown=nestjs:nodejs /app/prisma ./prisma COPY --from=build --chown=nonroot:nonroot /app/prisma ./prisma
COPY --from=build --chown=nestjs:nodejs /app/node_modules/.prisma ./node_modules/.prisma COPY --from=build --chown=nonroot:nonroot /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=build --chown=nestjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma COPY --from=build --chown=nonroot:nonroot /app/node_modules/@prisma ./node_modules/@prisma
COPY --from=deps --chown=nestjs:nodejs /app/node_modules ./node_modules COPY --from=deps --chown=nonroot:nonroot /app/node_modules ./node_modules
COPY --chown=nestjs:nodejs package.json ./ COPY --chown=nonroot:nonroot package.json ./
ENV NODE_ENV=production ENV NODE_ENV=production
USER nestjs
EXPOSE 3000 EXPOSE 3000
CMD ["node", "dist/main.js"] CMD ["dist/main.js"]

View file

@ -19,8 +19,8 @@ import { RefreshTokenStrategy } from './strategies/refresh-token.strategy';
imports: [ConfigModule], imports: [ConfigModule],
inject: [ConfigService], inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({ useFactory: async (configService: ConfigService) => ({
secret: configService.get<string>('JWT_ACCESS_SECRET') || 'access-secret', secret: configService.get<string>('JWT_SECRET') || 'dev-secret',
signOptions: { expiresIn: configService.get<string>('JWT_ACCESS_EXPIRES', '15m') }, signOptions: { expiresIn: configService.get<string>('JWT_EXPIRES_IN', '24h') },
}), }),
}), }),
PrismaModule, PrismaModule,
@ -30,4 +30,4 @@ import { RefreshTokenStrategy } from './strategies/refresh-token.strategy';
controllers: [AuthController], controllers: [AuthController],
exports: [JwtAuthGuard, RefreshTokenGuard, AuthService], exports: [JwtAuthGuard, RefreshTokenGuard, AuthService],
}) })
export class AuthModule {} export class AuthModule { }

View file

@ -10,7 +10,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
super({ super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false, ignoreExpiration: false,
secretOrKey: configService.get<string>('JWT_ACCESS_SECRET') || 'access-secret', secretOrKey: configService.get<string>('JWT_SECRET') || 'dev-secret',
}); });
} }

View file

@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# ===== STAGE 1: Builder ===== # ===== STAGE 1: Builder =====
FROM python:3.12-slim AS builder FROM python:3.11-slim AS builder
WORKDIR /build WORKDIR /build
@ -16,29 +16,23 @@ RUN --mount=type=cache,target=/root/.cache/pip \
pip install --upgrade pip && \ pip install --upgrade pip && \
pip install -r requirements.txt pip install -r requirements.txt
# ===== STAGE 2: Production ===== # ===== STAGE 2: Production (Distroless) =====
FROM python:3.12-slim AS production FROM gcr.io/distroless/python3-debian12:nonroot
# Variáveis de ambiente Python otimizadas # Variáveis de ambiente Python otimizadas
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
PATH="/opt/venv/bin:$PATH" PYTHONPATH="/opt/venv/lib/python3.11/site-packages"
WORKDIR /app WORKDIR /app
# Copia virtualenv do builder # Copia virtualenv do builder (apenas site-packages pois distroless já tem python)
COPY --from=builder /opt/venv /opt/venv COPY --from=builder /opt/venv/lib/python3.11/site-packages /opt/venv/lib/python3.11/site-packages
# Copia código fonte # Copia código fonte
COPY src ./src 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 EXPOSE 8000
# Uvicorn com workers otimizados # 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"]