Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
- ADDED admin - track files sizes
- ADDED login/logout notifications
- FIXED system - customer deploy stack name
- ADDED calandar - planning view (default for mobile)
- ADDED calendar - planning view (default for mobile)
- CHANGED system - optimize docker image size
3 changes: 3 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ uploads/
.git
.gitignore
Dockerfile
*.md
doc/
plans/
26 changes: 17 additions & 9 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ---- Base: shared setup ----
# ---- Base: shared setup (used by dev + build) ----
FROM python:3.12-slim AS base

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
Expand All @@ -19,22 +19,30 @@ EXPOSE 8000
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

# ---- Prod: deps + source ----
FROM base AS prod
# ---- Build: install deps + source (intermediate stage) ----
FROM base AS build

COPY pyproject.toml uv.lock* ./
RUN uv sync --frozen --no-dev --no-install-project

COPY . .

ARG APP_VERSION=dev
RUN echo "$APP_VERSION" > VERSION && uv sync --frozen --no-dev

# ---- Prod: clean runtime image without uv ----
FROM python:3.12-slim AS prod

LABEL org.opencontainers.image.source="https://github.com/VEAF/website-2026"
LABEL org.opencontainers.image.description="VEAF Website 2026 - Backend API"

COPY pyproject.toml uv.lock* ./
RUN uv sync --frozen --no-dev --no-install-project
RUN groupadd --gid 1000 worker && useradd --uid 1000 --gid worker --create-home worker

COPY . .
RUN echo "$APP_VERSION" > VERSION
RUN uv sync --frozen --no-dev
WORKDIR /app
ENV PATH="/app/.venv/bin:$PATH"

Comment on lines +34 to +43
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The prod stage no longer inherits ENTRYPOINT/CMD from base, so the final image lacks a startup command.

Since prod now uses FROM python:3.12-slim instead of FROM base, it no longer gets the ENTRYPOINT ["/app/entrypoint.sh"] and uvicorn CMD. The image will build but run without a default startup command, changing behavior from the previous setup.

To preserve the prior behavior, either:

  • Define the same ENTRYPOINT/CMD in the prod stage, or
  • Introduce a minimal base stage that sets the entrypoint/command and have prod inherit from it, keeping uv only in the build stage.

COPY --from=build --chown=worker:worker /app /app
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Copying the entire /app tree into prod may undermine the goal of a minimal runtime image.

This COPY pulls the entire build context into the runtime image, including build-only artifacts (uv.lock*, caches, tests, dev-only files, possibly .git, etc., depending on .dockerignore). Consider copying only the virtualenv, app code, entrypoint.sh, VERSION, and other explicit runtime assets to keep the image small, reduce surface area, and make runtime dependencies clearer.

Suggested implementation:

# Copy only runtime dependencies from the build stage to keep the image minimal.
# Adjust the paths below to match the layout produced in the build stage.
/* Python virtual environment */
COPY --from=build --chown=worker:worker /app/.venv /app/.venv

/* Application code */
COPY --from=build --chown=worker:worker /app/app /app/app

/* Entrypoint / startup scripts */
COPY --from=build --chown=worker:worker /app/entrypoint.sh /app/entrypoint.sh

/* Version / metadata files */
COPY --from=build --chown=worker:worker /app/VERSION /app/VERSION

  1. Make sure the paths (/app/app, /app/entrypoint.sh, /app/VERSION) match the actual structure produced by the build stage (e.g., if your module is backend, you might need /app/backend instead of /app/app).
  2. If there are additional runtime assets (config files, static files, migrations, etc.), add explicit COPY --from=build lines for those as well.
  3. Ensure entrypoint.sh is marked executable in the build or runtime stage (e.g., RUN chmod +x /app/entrypoint.sh if not already handled).
  4. Confirm .dockerignore excludes dev-only and build-only artifacts from the build context so they can’t accidentally leak into other layers.


RUN chown -R worker:worker /app
USER worker
EXPOSE 8000

Expand Down
1 change: 1 addition & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist
.git
.gitignore
Dockerfile
*.md
Loading