SkillAgentSearch skills...

Diffoci

diff for Docker and OCI container images

Install / Use

/learn @reproducible-containers/Diffoci
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

diffoci: diff for Docker and OCI container images

diffoci compares Docker and OCI container images for helping reproducible builds.

[!NOTE] "OCI" here refers to the "Open Container Initiative", not to the "Oracle Cloud Infrastructure".

$ diffoci diff --semantic alpine:3.18.2 alpine:3.18.3
TYPE    NAME                                 INPUT-0                                                             INPUT-1
File    lib/libcrypto.so.3                   4518b7d5f6563f81ca1b3d857bbd7008d686545d8211283240506449618b2858    d21ccbb32c1e98340027504e4d951ab4c38450f1f211a4157fa9e962216ac625
File    usr/bin/iconv                        8c54b8962ef07047032facf57cacb2f19eecfbefe03ad001e8c6c2b332e0d334    07115db0a4bd082f746ddbc6433b96397adcb523956417cb8376cd1ab4faf3d6
File    usr/lib/engines-3/capi.so            1b0508fa6be2efe1412f59da46b3963c7611696563b6b2b699b1aa9dba447b5a    cc03f5d58b206389f9560e8e7f15495d2bd2f384793549f63f3cb3cb9c71b466
File    bin/busybox                          6bf2a4358d5c26033d2d2e30ef9ce0ba9e3a9b34d81f0964f1d127123ae3e827    89f85a8b92bdb5ada51bd8ee0d9d687da1a759a0d80f8d012e7f8cbb3933a3a0
File    etc/os-release                       fb844374742438cf1b4e675dcd7d87c2fd6fbdb7cc7be30c62d4027240474aaf    e08e943282c5d38f99bfde311c7d5759a4578f92fca5943e5b1351e8cd472892
File    usr/lib/engines-3/padlock.so         670f9a084f97974b12c81cc7a88fce5ec9f47dcee00da3192a17577a5298e62f    15fb67a501ad1293034dd16106edbdee0c07803ebcbbeb5a8123b4e784c1491f
File    usr/bin/getconf                      d314880d6288d48e8223b3da02d00605f6a993b669593c1c1a0fa5fd95339d48    040fc0ddb83193809919381bb23d89e4efefdc207e18ef0f3d0e0d9977bf2b58
File    lib/ld-musl-x86_64.so.1              c6b3288ba48945a21ede7ccf6f7a257d41bacf2c061236726ff9b5def383a766    35002c47957674f588389c0f3ca23b01adab091ea5773326e1c7782e5ece1207
File    usr/lib/engines-3/afalg.so           2aaa6a94f0e07f556e77faa8bec55321d0fe138f27193fdcd6ef8ccef051c7ba    9ef6555b3594798ce5a05dfd79b996397642b367c75b5cab0c752050d28e6138
File    lib/apk/db/installed                 d8b49a733ba6590033ae75f27a52f83281b693ba46751a9e488bf12dbdb06c61    c5cd4d9ed0a78abe602cc1e5fb29c84bef033c99d7c7f5e15fdb76b6c6cf8ad0
File    lib/apk/db/scripts.tar               fbc51430c9f8b6a1a547281858fb36dff7947a2660a8bb6937b48f12361e3bb1    7d28a05788bda8fc5ec835257d5204d6d45c002458b04ad4981bce3be733c80f
File    etc/alpine-release                   8fc1c65f6ef13f8ef573d59100eb183cf5a66aa7e94a6e6cba1dd22e7a0af51b    7cc26f207ef55a1422daecc84d155e9fa50fd170574807e73e55823dd81407d9
File    etc/ssl/misc/tsget.pl                559f94eb47d2d6f81c361e334fd882596858c7934a8b0111177f535a910f2990    3feab60fb8d102da8746aa2a422ba77c60dda6b4ae9ac33056fe82bfc071969d
File    lib/apk/db/triggers                  f78b6968b2c85c453a9dd89368a9fc78788d7c34aeb202544a41714e90544a37    ff37f223b335fc42d5a563dd268cbf476411d8fdd2b88addade5b5f715f0425a
File    lib/libssl.so.3                      c22f9f45c1266ebdcc5f89c2f3471e89ffc5b2a4cd299f672156723270994133    91ad7b1cc8cf5575afeeb202c0fd1fefb63ceea1492491218f3132813eb04e49
File    usr/lib/engines-3/loader_attic.so    4f419a09b9f608e753045d83c255818c793913c274f724eb10d8ca8f474ae457    959301d5c88fab262a0631f1c87d02e1ef52215de35e0316af4513014a449b7f
File    usr/bin/getent                       1c6aa066998ddd019b6df0142ffcf8b1f4307593dc42b92e7fc82cd601905f75    c22523bc4d2208c8df51b9c7b87ad5596aaf171a4e69d169f007ada8241c5d09
File    usr/lib/ossl-modules/legacy.so       5b677eca0c3a3ac53c1a49fbac49534ea2862c62416d14ec6053f2080d5bae50    65b55bc81cbab89e7d2d7e5636455ef86642ae8c377dec3924103d3513ede888

Installation

Binary

Binaries are available for Linux and macOS: https://github.com/reproducible-containers/diffoci/releases

Using mise

If you are an enthusiast user of mise, the polyglot tool versions manager you can install diffoci with a command like:

mise use -g diffoci@latest

Source

Needs Go 1.21 or later.

go install github.com/reproducible-containers/diffoci/cmd/diffoci@latest

Basic usage

Strict mode

diffoci diff IMAGE0 IMAGE1

[!TIP] Non-Linux users and those comparing multi-platform images from Docker typically have to specify --platform explicitly. e.g., diffoci diff --platform=linux/amd64 IMAGE0 IMAGE1. (Note: Platform filtering for docker:// images requires Docker v28+)

The strict mode is often too strict. Consider using the non-strict mode (see below).

Non-strict (aka "semantic") mode

diffoci diff --semantic IMAGE0 IMAGE1

Non-strict mode ignores:

  • Timestamps
  • Build histories
  • File ordering in tar layers
  • Image name annotations

Advanced usage

Dumping conflicting files

Set --report-dir=DIR to dump conflicting files in the specified dir.

$ diffoci diff --semantic --report-dir=/tmp/diff alpine:3.18.2 alpine:3.18.3
TYPE    NAME                                 INPUT-0                                                             INPUT-1
...
File    etc/alpine-release                   8fc1c65f6ef13f8ef573d59100eb183cf5a66aa7e94a6e6cba1dd22e7a0af51b    7cc26f207ef55a1422daecc84d155e9fa50fd170574807e73e55823dd81407d9
...

$ diff -ur /tmp/diff/input-0/ /tmp/diff/input-1/
Binary files /tmp/diff/input-0/manifests-0/layers-0/bin/busybox and /tmp/diff/input-1/manifests-0/layers-0/bin/busybox differ
diff -ur /tmp/diff/input-0/manifests-0/layers-0/etc/alpine-release /tmp/diff/input-1/manifests-0/layers-0/etc/alpine-release
--- /tmp/diff/input-0/manifests-0/layers-0/etc/alpine-release   2023-06-15 00:03:14.000000000 +0900
+++ /tmp/diff/input-1/manifests-0/layers-0/etc/alpine-release   2023-08-07 22:09:12.000000000 +0900
@@ -1 +1 @@
-3.18.2
+3.18.3
...

Accessing containerd images

diffoci uses the containerd image store by default when containerd v1.7 or later is running. The default namespace is default.

To explicitly enable containerd:

diffoci --backend=containerd --containerd-socket=SOCKET --containerd-namespace=NAMESPACE

To explicitly disable containerd:

diffoci --backend=local

Accessing Docker images

To access Docker images that are not pushed to a registry, prepend docker:// to the image name:

docker build -t foo ~/foo
docker build -t bar ~/bar
diffoci diff docker://foo docker://bar

You do NOT need to specify a custom --backend to access Docker images.

Accessing Podman images

To access Podman images that are not pushed to a registry, prepend podman:// to the image name. See the docker:// example above, and read docker as podman.

Accessing private images

To access private images, create a credential file as ~/.docker/config.json using docker login.


Examples

Non-reproducible Docker Hub images

golang:1.21-alpine3.18

The sources of the official Docker Hub images are available at https://github.com/docker-library.

For example, the source of golang:1.21-alpine3.18 can be found at https://github.com/docker-library/golang/blob/d1ff31b86b23fe721dc65806cd2bd79a4c71b039/1.21/alpine3.18/Dockerfile.

The source can be built as follows:

$ DOCKER_BUILDKIT=0 docker build -t my-golang-1.21-alpine3.18 'https://github.com/docker-library/golang.git#d1ff31b86b23fe721dc65806cd2bd79a4c71b039:1.21/alpine3.18'
...
Successfully tagged my-golang-1.21-alpine3.18:latest

[!NOTE] DOCKER_BUILDKIT=0 is specified here because the official golang:1.21-alpine3.18 image is currently built with the legacy builder. A future revision of the official image may be built with BuildKit, and in such a case, DOCKER_BUILDKIT=1 will rather need to be specified here.

The resulting image binary (my-golang-1.21-alpine3.18) can be compared with the official image binary (golang:1.21-alpine3.18) as follows:

$ 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: 2.6 s  total:   0.0 B  (0.0 B/s)
INFO[0004] 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: 2.6 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               342eaa013375398497bfc21dff7dd017a647032ec5c486011142c576b7ccc989
Layer    ctx:/layers-1/layer       name "usr/local/share/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 "etc/ca-certificates/.wh..wh..opq" only appears in input 0                
Layer    ctx:/layers-2/layer       length mismatch (13927 vs 13926)                                               
Layer    ctx:/layers-2/layer       name "usr/local/go/.wh..wh..opq" only appears in input 0                       
File     lib/apk/db/scripts.tar    073bb5094fc5bba800f06661dc7f1325c5cb4250b13209fb9e3eaf4e60e4bfc4               1369581b62bd60304c59556ea85f585bd498040c8fa223243622bb7990833063
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  

[!NOTE] The

View on GitHub
GitHub Stars565
CategoryDevelopment
Updated17h ago
Forks14

Languages

Go

Security Score

95/100

Audited on Mar 30, 2026

No findings