9 The dev image
Read the tutorial. Build it yourself 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
To look at this code on your machine, run these commands. The first one makes a clone, if this folder has none:
[ -d cheesecracker ] || git clone https://github.com/rahuldave/cheesecracker
cd cheesecracker
git fetch --quiet --tags --force origin
git switch --detach step-08The dev image runs the checks in Linux, anywhere Docker runs.
just setupThe checks run on this machine. Another person, or a CI service, runs them on another system, with other versions of the tools. The dev image holds the whole project with every group of dependencies, and uv, just and git. So the checks run in the same Linux, anywhere Docker runs.
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.
± See the change to Dockerfile
The stage dev installs git and curl, copies uv, and installs just as a package of PyPI. It installs every group of
uv.lock into /opt/venv, copies the project into /work, and starts a shell. /opt/venv is outside /work, so a
.venv of this machine in a mounted folder is never used.
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-devThe image is about 353 MB, twice the run image, because it has every tool.
What changed
Dockerfile: the stagedev, and its lines in the comment at the top. 26 lines added. The file- look at
FROM python:3.12-slim-bookworm AS dev
- look at
The diff of 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"]9.2 just docker-shell and just docker-test
Two recipes run the dev image with this folder mounted at /work. An edit here shows in there at once, so the image
needs no rebuild after a change of the code. docker-shell opens a shell in the image. docker-test runs the recipe
that you name in the image, or just check if you name none.
docker-shell runs docker run --rm -it -v "$PWD":/work cheesecracker-dev. -v mounts this folder at /work, and
-it gives the shell a terminal. docker-test runs just in the image, with its words, or with check.
just docker-testjust check runs in Linux. The last line is 21 passed. The system tests do not run, because just check leaves them
out.
just docker-test test tests/unit -qThe eleven unit tests pass in Linux.
What changed
justfile: the recipesdocker-shellanddocker-test. 8 lines added. The file- look at
docker run --rm -v "$PWD":/work cheesecracker-dev just "${@:-check}"
- look at
The diff of justfile
@@ -86,3 +86,11 @@ docker-stop:
# Run the system tests against the server at http://localhost:9000. They fail when no server answers there
test-system *args:
uv run pytest tests/system "$@"
+
+# A shell in the dev image, with this folder mounted at /work: an edit here shows in there at once
+docker-shell:
+ docker run --rm -it -v "$PWD":/work cheesecracker-dev
+
+# Run a recipe in the dev image, with this folder mounted at /work. Alone, just check: just docker-test test tests/unit
+docker-test *args:
+ docker run --rm -v "$PWD":/work cheesecracker-dev just "${@:-check}"This part ends at the code at step-09. The code after this part