diffoci: diff for reproducible builds of Docker/OCI container images

Akihiro Suda suda.kyoto at gmail.com
Fri Aug 25 12:27:35 UTC 2023


Let me introduce my new project: diffoci
https://github.com/reproducible-containers/diffoci

diffoci is a tool to compare Docker and OCI (Open Container
Initiative) images to help reproducible builds of containers.

The following example compares Docker's official
`golang:1.21-alpine3.18` image with a local image built from its
public source (
https://github.com/docker-library/golang/blob/d1ff31b/1.21/alpine3.18/Dockerfile
):

```
$ export DOCKER_BUILDKIT=0 # because Docker Hub still doesn't use BK

$ docker build -q -t my-golang-1.21-alpine3.18
'https://github.com/docker-library/golang.git#d1ff31b86b23fe721dc65806cd2bd79a4c71b039:1.21/alpine3.18'
2>/dev/null
sha256:13852f166ad097d0130c4a5cbcf1b29b15b501eef8bbbe8ee5d5f59ff6505c71

$ diffoci diff docker://golang:1.21-alpine3.18
docker://my-golang-1.21-alpine3.18 --semantic --report-dir=~/diff
INFO[0000] Loading image "docker.io/library/golang:1.21-alpine3.18"
from "docker"
docker.io/library/golang:1.21 alpine3.18 saved
Importing elapsed: 1.2 s total:   0.0 B (0.0 B/s)
INFO[0003] Loading image
"docker.io/library/my-golang-1.21-alpine3.18:latest" from "docker"
docker.io/library/my golang 1.21 alpine3 saved
Importing elapsed: 1.1 s total:   0.0 B (0.0 B/s)
TYPE     NAME                      INPUT-0
                                           INPUT-1
Layer    ctx:/layers-1/layer       length mismatch (457 vs 454)
File     lib/apk/db/scripts.tar
eef110e559acb7aa00ea23ee7b8bddb52c4526cd394749261aa244ef9c6024a4
        e076a3969fc86abef71c7ed14ae34a678b569ef53161dae9be65bf6fddbb5bbb
Layer    ctx:/layers-1/layer       name
"etc/ca-certificates/.wh..wh..opq" only appears in input 0
Layer    ctx:/layers-1/layer       name
"usr/share/ca-certificates/.wh..wh..opq" only appears in input 0
Layer    ctx:/layers-1/layer       name
"usr/local/share/ca-certificates/.wh..wh..opq" only appears in input 0
Layer    ctx:/layers-2/layer       length mismatch (13927 vs 13926)
File     lib/apk/db/scripts.tar
073bb5094fc5bba800f06661dc7f1325c5cb4250b13209fb9e3eaf4e60e4bfc4
        d0e2585156400b0e3a1afde804ad6c9f7eb4577daea552c8eccf1a6467b1d404
Layer    ctx:/layers-2/layer       name "usr/local/go/.wh..wh..opq"
only appears in input 0
Layer    ctx:/layers-3/layer       length mismatch (4 vs 3)
Layer    ctx:/layers-3/layer       name "go/.wh..wh..opq" only appears
in input 0

$ find ~/diff -type f
/home/suda.linux/diff/input-1/layers-2/lib/apk/db/scripts.tar
/home/suda.linux/diff/input-1/layers-1/lib/apk/db/scripts.tar
/home/suda.linux/diff/input-0/layers-3/go/.wh..wh..opq
/home/suda.linux/diff/input-0/layers-2/lib/apk/db/scripts.tar
/home/suda.linux/diff/input-0/layers-2/usr/local/go/.wh..wh..opq
/home/suda.linux/diff/input-0/layers-1/lib/apk/db/scripts.tar
/home/suda.linux/diff/input-0/layers-1/usr/local/share/ca-certificates/.wh..wh..opq
/home/suda.linux/diff/input-0/layers-1/usr/share/ca-certificates/.wh..wh..opq
/home/suda.linux/diff/input-0/layers-1/etc/ca-certificates/.wh..wh..opq
/home/suda.linux/diff/report.json
```

The image is reproducible except `lib/apk/db/scripts.tar`, the AUFS
whiteouts (`.wh..wh..opq`), and the timestamp stuff.
The diff of `lib/apk/db/scripts.tar` is negligible as they only
differs in the timestamps (can be checked with `diffoscope`)
So, the `golang:1.21-alpine3.18` image can be verified to be built
from its public source.

But usually apk package versions can differ, and it is really hard to
check whether the diff is negligible for security.
I'm also working on another project "repro-get" (
https://github.com/reproducible-containers/repro-get ) to pin apk
packages, but its UX is still not great.

Regards,
Akihiro Suda


More information about the rb-general mailing list