What happens
src/mock_vws/_flask_server/Dockerfile does:
COPY --chown=10001:10001 . /app
...
RUN uv sync --no-cache
There is no .dockerignore in the repository, and no uv.lock.
Three consequences.
Everything is copied into the image. .git, tests/, docs/, newsfragments/, secrets.tar.gpg, and any local .venv or docker_venvs a contributor has, all land in /app in the published images. check-manifest already maintains a list of what does not belong in the distribution, in [tool.check-manifest], but nothing applies an equivalent to the image.
The dependency layer is invalidated by any source edit. Because the copy precedes uv sync, changing one line in src/mock_vws/target.py re-resolves and re-installs every dependency. docker-build.yml builds for linux/amd64 and linux/arm64, so that cost is paid twice per build.
Image builds are not reproducible. With no lockfile and >= constraints throughout [project.dependencies], uv sync resolves afresh at build time. Two builds of the same commit on different days can ship different versions of flask, numpy, opencv-contrib-python-headless, pillow and the rest. A released image tag is therefore not a fixed artefact, and a bug reproducible in one build of :latest may not reproduce in another.
Why it matters
The reproducibility point is the one that matters. The Docker images are the supported way to use this mock from languages other than Python, so they are a release artefact in their own right, and they are currently the only part of the project without pinned dependencies — optional-dependencies.dev pins every development tool to an exact version.
The other two are build time and image size, which are cheap to fix at the same time.
Suggested resolution
- Add a
.dockerignore. The [tool.check-manifest] ignore list is a reasonable starting point for its contents.
- Commit a
uv.lock and build with uv sync --locked, so the image contents follow from the commit. Dependabot already updates dependencies here, so keeping the lockfile current fits the existing workflow.
- Copy
pyproject.toml and the lockfile, run uv sync, then copy the source, so that source edits do not invalidate the dependency layer.
Worth checking whether adding a lockfile interacts with setuptools-scm and the SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 workaround already in the Dockerfile.
What happens
src/mock_vws/_flask_server/Dockerfiledoes:There is no
.dockerignorein the repository, and nouv.lock.Three consequences.
Everything is copied into the image.
.git,tests/,docs/,newsfragments/,secrets.tar.gpg, and any local.venvordocker_venvsa contributor has, all land in/appin the published images.check-manifestalready maintains a list of what does not belong in the distribution, in[tool.check-manifest], but nothing applies an equivalent to the image.The dependency layer is invalidated by any source edit. Because the copy precedes
uv sync, changing one line insrc/mock_vws/target.pyre-resolves and re-installs every dependency.docker-build.ymlbuilds forlinux/amd64andlinux/arm64, so that cost is paid twice per build.Image builds are not reproducible. With no lockfile and
>=constraints throughout[project.dependencies],uv syncresolves afresh at build time. Two builds of the same commit on different days can ship different versions offlask,numpy,opencv-contrib-python-headless,pillowand the rest. A released image tag is therefore not a fixed artefact, and a bug reproducible in one build of:latestmay not reproduce in another.Why it matters
The reproducibility point is the one that matters. The Docker images are the supported way to use this mock from languages other than Python, so they are a release artefact in their own right, and they are currently the only part of the project without pinned dependencies —
optional-dependencies.devpins every development tool to an exact version.The other two are build time and image size, which are cheap to fix at the same time.
Suggested resolution
.dockerignore. The[tool.check-manifest]ignore list is a reasonable starting point for its contents.uv.lockand build withuv sync --locked, so the image contents follow from the commit. Dependabot already updates dependencies here, so keeping the lockfile current fits the existing workflow.pyproject.tomland the lockfile, runuv sync, then copy the source, so that source edits do not invalidate the dependency layer.Worth checking whether adding a lockfile interacts with
setuptools-scmand theSETUPTOOLS_SCM_PRETEND_VERSION=0.0.0workaround already in the Dockerfile.