Implement rootless containers for all services

- backend: appuser UID/GID 1001 via useradd, USER directive, --chown on COPY
- frontend builder: appuser UID/GID 1001 via adduser, USER directive
- frontend prod: switch to nginxinc/nginx-unprivileged:alpine (nginx UID 101), listen on 8080
- docker-compose: explicit user: for all services (70:70 db, 1001:1001 backend/frontend-dev, 101:101 frontend-prod)
- nginx.conf: listen 8080 to match unprivileged image

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-13 17:18:02 +02:00
parent 3c88e719ed
commit a5baef73d9
7 changed files with 55 additions and 13 deletions
+12 -6
View File
@@ -1,18 +1,24 @@
# ── Stage 1: build ────────────────────────────────────────────────────────────
FROM node:20-alpine AS builder
WORKDIR /app
# Create non-root user (UID/GID 1001)
RUN addgroup -g 1001 appuser && adduser -u 1001 -G appuser -s /bin/sh -D appuser
COPY package.json package-lock.json* ./
WORKDIR /app
RUN chown appuser:appuser /app
USER appuser
COPY --chown=appuser:appuser package.json package-lock.json* ./
RUN npm ci
COPY . .
COPY --chown=appuser:appuser . .
RUN npm run build
# ── Stage 2: serve with nginx ─────────────────────────────────────────────────
FROM nginx:alpine
# ── Stage 2: serve with nginx (unprivileged, UID 101) ─────────────────────────
FROM nginxinc/nginx-unprivileged:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
EXPOSE 8080