9.1 The dev image installs every group

Build it yourself. Read the tutorial is the other way to read this part.

This walk goes through rahuldave/cheesecracker on GitHub. This part starts from the code at step-08. The code before this part

This part does not start where the part before it ends, because the walk skips some changes. This command puts the files that this part starts from in place of yours. Run it, and then go on:

git fetch --quiet --tags --force origin; git restore --source de0780b72a5c --staged -- :/ && git restore --source step-08 --staged --worktree -- :/

If you start at this part, make your clone as Get the project says, and then run this command. It puts in your clone the files that this part starts from. A file that the project deleted before this part stays, so delete it if git check lists it:

git fetch --quiet --tags --force origin; git rm -rq --cached --ignore-unmatch -- :/ && git restore --source step-08 --staged --worktree -- :/
just setup

The whole tutorial then adds the system tests, and the recipe just test-system. The dev image is for working on the project, so it installs every group.

9.1 the dev image, to work on the project in Linux

The dev image is a fourth stage of the Dockerfile, dev. It takes uv from the stage uv, and nothing from the run image.

Apply the patch to Dockerfile, from the top of the project:

curl -fsSL https://github.com/rahuldave/cheesecracker/commit/ccf62d330f28c6eec4c0b993e1a71e2c11a8b5af.diff | git apply --include=Dockerfile

Apply the patch. Read the new lines at the top of the file, then the stage dev at the end. Read its line RUN uv tool install, and its line RUN uv sync --locked, which installs every group.

docker build --target dev --tag cheesecracker-dev .

Near the end, the line naming to docker.io/library/cheesecracker-dev names the image.

docker image ls cheesecracker-dev

The image is about 353 MB, twice the run image, because it has every tool.

Check your files against this move. The command prints nothing when they match, and otherwise shows what differs:

git check ccf62d330f28

If you are stuck, this command puts the files of this move in place of yours. A file that you made yourself stays:

git fetch --quiet --tags --force origin; git restore --source step-08 --staged -- :/ && git restore --source ccf62d330f28 --staged --worktree -- :/

What changed

  • Dockerfile: the stage dev, and its lines in the comment at the top. 26 lines added. The file
    • look at FROM python:3.12-slim-bookworm AS dev

The patch to Dockerfile
@@ -2,6 +2,8 @@
 #
 #   docker build --target run --tag cheesecracker-run .
 #       the production image: Python, the dependencies of the server and its code. It starts the server
+#   docker build --target dev --tag cheesecracker-dev .
+#       the development image: every dependency group, uv, just and git. It starts a shell
 #
 # The environment lives in /opt/venv, never in the project folder.
 
@@ -32,3 +34,27 @@ USER app
 EXPOSE 9000
 # Four workers, and no restart on a change: the server as it runs in production
 CMD ["uvicorn", "api.service:app", "--host", "0.0.0.0", "--port", "9000", "--workers", "4"]
+
+# The dev image: the whole project with every dependency group, and uv, just and git to work in it
+FROM python:3.12-slim-bookworm AS dev
+# hadolint ignore=DL3008
+RUN apt-get update \
+    && apt-get install --yes --no-install-recommends ca-certificates curl git \
+    && rm -rf /var/lib/apt/lists/*
+COPY --from=uv /uv /uvx /usr/local/bin/
+ENV UV_PROJECT_ENVIRONMENT=/opt/venv \
+    UV_PYTHON_DOWNLOADS=never \
+    UV_LINK_MODE=copy \
+    UV_NO_CACHE=1 \
+    UV_TOOL_BIN_DIR=/usr/local/bin \
+    PATH=/opt/venv/bin:$PATH \
+    PYTHONUNBUFFERED=1
+# just, as a wheel from PyPI. git refuses a folder that another user owns, and a mounted folder
+# belongs to the user of the host, so every folder is safe
+RUN uv tool install "rust-just==1.50.0" \
+    && git config --system --add safe.directory '*'
+WORKDIR /work
+COPY pyproject.toml uv.lock .python-version ./
+RUN uv sync --locked
+COPY . .
+CMD ["bash"]

This change on GitHub

This part ends at the code at ccf62d330f28, partway through step-09. The code after this part