Skip to content

Commit d153ac3

Browse files
leodidoona-agent
andcommitted
feat(docker): pass SOURCE_DATE_EPOCH as build arg for deterministic images
Pass SOURCE_DATE_EPOCH as a Docker build arg to enable deterministic Docker image timestamps. Dockerfiles MUST declare ARG SOURCE_DATE_EPOCH for BuildKit to use the timestamp for image metadata: FROM alpine:3.18 ARG SOURCE_DATE_EPOCH Without this ARG declaration, images will have non-deterministic timestamps even though the environment variable is set (from PR #284). With the ARG, BuildKit uses SOURCE_DATE_EPOCH for: - Image metadata timestamps (created field) - History timestamps - OCI annotations The ARG is also available in RUN commands for custom build logic: RUN go build -ldflags "-X main.BuildTime=$SOURCE_DATE_EPOCH" -o app Co-authored-by: Ona <no-reply@ona.com>
1 parent 5d71f0e commit d153ac3

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,39 @@ packages:
329329

330330
**Docker builds:**
331331

332-
For Docker packages, leeway automatically enables BuildKit (`DOCKER_BUILDKIT=1`) and exports `SOURCE_DATE_EPOCH`. For deterministic Docker images, see PR #285 which passes the value as a build arg (requires `ARG SOURCE_DATE_EPOCH` in Dockerfiles).
332+
For Docker packages, leeway automatically enables BuildKit (`DOCKER_BUILDKIT=1`) and exports `SOURCE_DATE_EPOCH`. Additionally, leeway passes `SOURCE_DATE_EPOCH` as a build arg to enable deterministic image timestamps.
333333

334334
BuildKit is the default builder since Docker Engine v23.0 and is always used in Docker Desktop.
335335

336+
**Dockerfile requirements for deterministic images:**
337+
338+
Dockerfiles MUST declare the build arg for BuildKit to use the timestamp for image metadata:
339+
340+
```dockerfile
341+
FROM alpine:3.18
342+
ARG SOURCE_DATE_EPOCH
343+
COPY app /usr/local/bin/app
344+
```
345+
346+
With the `ARG SOURCE_DATE_EPOCH` declaration, BuildKit (>= v0.13) automatically uses the timestamp for:
347+
- Layer creation timestamps
348+
- Image config `created` timestamp
349+
- History timestamps
350+
- OCI annotations
351+
352+
Without the ARG declaration, images will have non-deterministic timestamps even though leeway sets the environment variable.
353+
354+
For multi-stage builds, declare the ARG in each stage:
355+
356+
```dockerfile
357+
FROM golang:1.21 AS builder
358+
ARG SOURCE_DATE_EPOCH
359+
RUN go build -o app
360+
361+
FROM alpine:3.18
362+
ARG SOURCE_DATE_EPOCH
363+
COPY --from=builder /app /app
364+
```
336365
## Package Variants
337366
Leeway supports build-time variance through "package variants". Those variants are defined on the workspace level and can modify the list of sources, environment variables and config of packages.
338367
For example consider a `WORKSPACE.YAML` with this variants section:

pkg/leeway/build.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,8 @@ func (p *Package) buildDocker(buildctx *buildContext, wd, result string) (res *p
19921992
buildcmd = append(buildcmd, "--build-arg", fmt.Sprintf("DEP_%s=%s", arg, val))
19931993
}
19941994
buildcmd = append(buildcmd, "--build-arg", fmt.Sprintf("__GIT_COMMIT=%s", p.C.Git().Commit))
1995+
// Pass SOURCE_DATE_EPOCH for deterministic Docker image timestamps
1996+
buildcmd = append(buildcmd, "--build-arg", fmt.Sprintf("SOURCE_DATE_EPOCH=%d", mtime))
19951997
if cfg.Squash {
19961998
buildcmd = append(buildcmd, "--squash")
19971999
}

0 commit comments

Comments
 (0)