Minimal production images
Table of Contents
For production, I want the smallest possible attack surface. Distroless images have no shell, no package manager — just my application and its runtime. But I still need the correct timezone.
1. Setting the timezone on distroless
Distroless can't run apt or apk. We copy the timezone artifacts
from alpine_tz directly into the image — Alpine is lighter than
Debian and alpine_tz() already extracts both /etc/localtime and
/etc/timezone.
.with_file(path, file) copies a File artifact into the container
at the given path — like COPY in a Dockerfile. This is the only way
to get files into a distroless image since there is no shell or
package manager to run.
@function
def distroless_set_tz(self, ctr: dagger.Container) -> dagger.Container:
"""Copy timezone artifacts into a distroless container (uses Lib.timezone)."""
tz = self.alpine_tz()
return (
ctr
.with_file("/etc/localtime", tz.file("localtime"))
.with_file("/etc/timezone", tz.file("timezone"))
)
2. Distroless Python 3
For Python services that need maximum security and minimum image size.
@function
def distroless_python3_debian(self) -> dagger.Container:
"""Distroless python3 with timezone set."""
ctr = dag.container().from_(self.pinned(self._distroless_python3_image))
return self.distroless_set_tz(ctr)
dagger call distroless-python-3-debian with-exec --args="python3","-c","import os; print(os.path.exists('/etc/localtime'))" stdout
3. Distroless static
For Go or Rust services compiled as static binaries.
@function
def distroless_debian(self) -> dagger.Container:
"""Distroless static with timezone set."""
ctr = dag.container().from_(self.pinned(self._distroless_static_image))
return self.distroless_set_tz(ctr)
TMP="${TMP:-$(mktemp -d)}"
dagger call distroless-debian file --path="/etc/localtime" export --path="$TMP/out/localtime" > /dev/null
test -s "$TMP/out/localtime" && echo "non-empty"
4. Image references for pin management
See alpine for the convention.
@property
def _distroless_python3_image(self) -> str:
return f"gcr.io/distroless/python3-debian{self.debian_version}"
@property
def _distroless_static_image(self) -> str:
return f"gcr.io/distroless/static-debian{self.debian_version}"