At LOGIC, we are always looking to refine our workflows to be as efficient and streamlined as possible; from development to CI, preview environments and production. Our Python and Django development relies on consistent and fasts environments that work seamlessly from local development to CI and all the way to production. Today, we're excited to share a core piece of that workflow with the community: the Python with LOGIC Docker image.
This is an opinionated base Docker image, born from our experience with Python. It's built on the principles of DRY, considerate defaults, and an obsession with speed and convenience. The code is available on GitHub: https://github.com/withlogicco/python.
Why
When working across different stages of multiple projects, consistency is key. We wanted an image that would:
- Provide a Python and virtual environment setup optimized for Docker deployments.
- Leverage the incredible speed of
uv
for dependency management. - Come pre-configured for a smooth local development experience with Docker.
By open-sourcing this image, we hope to help other teams achieve the same level of efficiency we've come to rely on.
Getting started
Using the image is straightforward. For a simple project, you can get started by using the latest tag and copying your source code into the working directory:
FROM ghcr.io/withlogicco/python
COPY ./ ./
We prefer taking this one step further though, by pinning the Python version we use in each project and taking advantage of Docker's build cache mounts on our self-hosted GitHub Actions runners and minimising build steps with build bind mounts:
FROM ghcr.io/withlogicco/python:3.13
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
--mount=type=bind,source=uv.lock,target=uv.lock \
uv sync --no-install-project
Video
If you enjoy videos more than reading, you can watch our video showcasing how to get started with uv on YouTube:
No rebuilds for new dependencies
Developer experience is key at LOGIC. We want to focus on writing code, rather than managing our developer environments and workflows.
A crucial decision we took towards this direction is setting the location of uv's virtual environments to /opt/uv/venv
, complying with the Filesystem Hierarchy Standard. This helped keep Python dependencies outside of the working directory of our repositories, avoiding .venv
subdirectories, with node_module
-like experience and therefore less clutter in .gitignore
and .dockerignore
.
Most importantly though, this enabled us to preconfigure a Docker volume in /opt/uv/venv
, which automatically pre-populates local-development mounts with the Docker image's virtual environment contents. This means that when developing locally with either Docker Compose or dev containers, we get to hit the ground running with the dependencies pre-built in the image, copied in a fresh mount volume, while running uv add
updates the volume's content, and therefore requiring no further Docker image building. A simplistic compose file implementing this can be seen below:
services:
web:
build: .
volumes:
- .:/usr/src/app
- uv:/opt/uv/venv
Conclusion
The Python with LOGIC Docker image is a small but powerful tool that encapsulates our philosophy on building software of using with rock-solid, efficient and fast tooling across the whole pipeline. It has been a game-changer for our latest Python projects, and we're thrilled to share it. Give it a try and let us know what you think!
Finally, if you're looking to level up your Python and DevOps practices Get in touch with us, we'd love to help.
Stay tuned with LOGIC
Get notified when an article lands on the LOGIC blog.