Files
Business-Management/changelog/2026-04-13_rootless-containers.md
T
curo1305 a5baef73d9 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>
2026-04-13 17:18:02 +02:00

1.4 KiB

2026-04-13 — Rootless containers

Timestamp: 2026-04-13T00:00:00

Summary

All containers now run as non-root users with explicit UID:GID assignments enforced in both Dockerfiles and docker-compose files.

User mapping

Service User UID:GID Notes
db postgres 70:70 Fixed by postgres:16-alpine; image owns PGDATA as 70:70 so named-volume seeding works
backend appuser 1001:1001 Created via useradd in runtime stage
frontend (prod) nginx 101:101 Switched to nginxinc/nginx-unprivileged:alpine; listens on 8080
frontend (dev) appuser 1001:1001 Created via adduser in builder stage

Files Modified

  • backend/Dockerfile — added groupadd/useradd for appuser (1001:1001), --chown on all COPY directives, USER appuser
  • frontend/Dockerfile — builder stage: added addgroup/adduser for appuser (1001:1001), USER appuser; prod stage: switched to nginxinc/nginx-unprivileged:alpine, EXPOSE 8080
  • frontend/nginx.conf — changed listen 80listen 8080 to match unprivileged image default
  • docker-compose.yml — added user: "70:70" to db, user: "1001:1001" to backend, user: "101:101" to frontend; updated frontend port mapping to "80:8080"
  • docker-compose.dev.yml — added user: "1001:1001" to backend and frontend overrides
  • TODO.md — marked rootless containers item as completed