diff --git a/backend/Dockerfile b/backend/Dockerfile index 364fc1a6..a8e87052 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -29,26 +29,28 @@ RUN uv sync --frozen --no-dev # --- runtime --- FROM base AS runtime +# Create non-root user before COPY so --chown can reference it. +# Using COPY --chown avoids a slow recursive chown on overlay2 (docker/for-linux#388). +RUN groupadd --system appgroup && useradd --system --gid appgroup --create-home appuser \ + && chown appuser:appgroup /app + # Copy virtual environment from deps stage -COPY --from=deps /app/.venv /app/.venv +COPY --from=deps --chown=appuser:appgroup /app/.venv /app/.venv ENV PATH="/app/.venv/bin:${PATH}" # Copy app source -COPY backend/migrations ./migrations -COPY backend/alembic.ini ./alembic.ini -COPY backend/app ./app +COPY --chown=appuser:appgroup backend/migrations ./migrations +COPY --chown=appuser:appgroup backend/alembic.ini ./alembic.ini +COPY --chown=appuser:appgroup backend/app ./app # Copy provisioning templates. # In-repo these live at `backend/templates/`; runtime path is `/app/templates`. -COPY backend/templates ./templates +COPY --chown=appuser:appgroup backend/templates ./templates # Copy worker scripts. # In-repo these live at `scripts/`; runtime path is `/app/scripts`. -COPY scripts ./scripts +COPY --chown=appuser:appgroup scripts ./scripts -# Run as non-root user -RUN groupadd --system appgroup && useradd --system --gid appgroup appuser \ - && chown -R appuser:appgroup /app USER appuser # Default API port diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 61293512..09bf6811 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -31,16 +31,18 @@ ARG NEXT_PUBLIC_AUTH_MODE ENV NEXT_PUBLIC_API_URL=auto ENV NEXT_PUBLIC_AUTH_MODE=${NEXT_PUBLIC_AUTH_MODE} -COPY --from=builder /app/.next ./.next +# Create non-root user before COPY so --chown can reference it. +# Using COPY --chown avoids a slow recursive chown on overlay2 (docker/for-linux#388). +RUN addgroup -S appgroup && adduser -S -G appgroup appuser \ + && chown appuser:appgroup /app + +COPY --from=builder --chown=appuser:appgroup /app/.next ./.next # `public/` is optional in Next.js apps; repo may not have it. # Avoid failing the build when the directory is absent. -COPY --from=builder /app/package.json ./package.json -COPY --from=builder /app/node_modules ./node_modules -COPY --from=builder /app/next.config.ts ./next.config.ts +COPY --from=builder --chown=appuser:appgroup /app/package.json ./package.json +COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules +COPY --from=builder --chown=appuser:appgroup /app/next.config.ts ./next.config.ts -# Run as non-root user -RUN addgroup -S appgroup && adduser -S -G appgroup appuser \ - && chown -R appuser:appgroup /app USER appuser EXPOSE 3000