Reusable container helpers for Dagger
Table of Contents
daggerlib is a Dagger module that gives you pre-configured container images for everyday tasks: setting timezones, creating non-root users, managing Python virtualenvs, running Docker-in-Docker, and more.
Pick a base image, compose the helpers you need, and get a ready-to-use
container in a single dagger call.
Note: daggerlib is not Dagger itself — it is a library of helpers that builds on top of Dagger.
1. What can I do with it?
Most services I deploy run in France, so the first thing I need is a container with the correct timezone. Alpine is my default base image — it's small and fast to pull. When I need more packages or better compatibility with native libraries, I reach for Debian instead.
For production, I want the smallest possible attack surface. Distroless images have no shell and no package manager — just the runtime and the timezone file copied from Debian.
Running as root inside containers is a bad habit. The user helpers let me create a non-root user with optional sudo and group memberships in a single call, on any base image.
Python projects need virtualenvs. The Alpine and Debian targets can set one up automatically, but sometimes I need standalone tools: pip-tools for dependency management, or a pre-built Flask venv I can copy into a final image.
Some CI jobs need to build Docker images. Docker-in-Docker handles the cgroup setup, tmpfs mounts, and dockerd lifecycle so I don't have to think about it.
For automated development tasks, Ralph runs the ralph-orchestrator inside a container with Claude Code, picking tasks from a todo list, implementing them, running tests, and committing — all without human intervention.
All of this is verified by automated tests that exercise every target
via dagger call.
2. Examples
Each example is a self-contained Dagger project that uses daggerlib as a dependency. You can read the org file, or run the commands yourself.
- Shipping a webhook receiver — Flask app, gunicorn, container packaging
- Packaging a log collector CLI — Alpine, Debian, distroless
- Building a data pipeline CLI — virtualenvs, pip-tools, CSV transform
- Shipping a Python service to production — distroless, timezone injection
- Testing a container orchestrator — Docker-in-Docker
- Running CI tests like production — non-root users, UID matching
3. Running the tests
./test.sh
4. How it works
The source of truth lives in org files (literate programming). Python modules and shell scripts are generated from those files via tangling. See TECHNICAL.org for the full details on the build pipeline and editor setup.
5. Dagger concepts
If you're new to Dagger: instead of writing YAML pipelines, you write functions in Python (or Go, TypeScript, …) that describe what each container should look like. The Dagger SDK provides a fluent API to build and manipulate those containers. Here are the key primitives used in this project, with links to the API reference:
dag.container()— creates a new, empty container..from_(image)— sets the base image (likeFROMin a Dockerfile)..with_exec([cmd])— runs a command inside the container (likeRUN)..with_env_variable(name, value)— sets an environment variable..with_workdir(path)— changes the working directory..with_user(username)— switches the active user..with_file(path, file)— copies a file into the container..file(path)— extracts a single file from a container..directory(path)— extracts a directory from a container.@function/@object_type— decorators that expose Python methods as callable Dagger functions (invokable viadagger call).