docker-patcher
provides a cli & API to calculate and apply binary diffs against Docker images. Diffing is done using bsdiff
/bspatch
, wrapped nicely by @icedream/go-bsdiff.
While binary patching might not be particularly useful in traditional datacenter/server environments, it can be very beneficial for devices with limited internet connectivity (e.g. IoT/M2M).
The CLI has some rough edges. The package's main API was broken to make it easier to include in other projects.
$ go build -o bin/didiff ./cmd/didiff
Extra: temporarily add these tools to your path
$ export PATH=$PATH:`pwd`/bin
didiff create sha256:original_docker_image sha256:new_docker_image /path/to/diff.patch
didiff apply sha256:original_docker_image sha256:new_docker_image /path/to/diff.patch
didiff apply
accepts an optional -t
argument, specifying the a repo:tag to be applied to the new image, once loaded. This is optional.
In this example we'll create a patch to upgrade from nginx:1.15.11
to nginx:1.15.12
.
To create the patch, ensure you have both the old and new images available:
$ docker images --no-trunc
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.15.11 sha256:bb776ce48575796501bcc53e511563116132b789ab0552d520513da8c738cba2 12 days ago 109MB
nginx 1.15.12 sha256:27a188018e1847b312022b02146bb7ac3da54e96fab838b7db9f102c8c3dd778 6 days ago 109MB
The shortened image IDs for 1.15.11 and 1.15.12 are bb776ce48575
and 27a188018e18
, respectively.
didiff create bb776ce48575 27a188018e18 `pwd`/nginx_1-15-11_to_1-15-12.patch # Using full length IDs is supported, too
After a few seconds (or minutes, depending :)) the patch will be written to nginx_1-15-1_to_1-15-12.patch
.
Upon inspecting the patch, we can see that in this case we're weighing in under 300KB! That's much better than a ~23MB pull (assuming caching).
$ du -hs ./nginx_1-15-11_to_1-15-12.patch
260K ./nginx_1-15-11_to_1-15-12.patch
Applying the patch takes similar motions. If you're testing this out on a machine with the old and new images, you can easily remove an image with docker rmi your_img_id_here
Ensure the image doesn't exist locally:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.15.11 bb776ce48575 12 days ago 109MB
Now we can use the use the patch we built previously. Specifying -t
ensures that the new image is properly re-tagged.
./didiff apply bb776ce48575 27a188018e18 `pwd`/nginx_1-15-11_to_1-15-12.patch -t nginx:1.15.12
We can see the image was patched and loaded by running docker images
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.15.12 27a188018e18 6 days ago 109MB
nginx 1.15.11 bb776ce48575 12 days ago 109MB
As a final step, for good measure, let's verify the new image works!
$ docker run --rm -d \
--name docker-patch-test \
-p 8080:80 27a188018e18 \
&& curl -sSL -D - localhost:8080 -o /dev/null | grep Server: \
&& docker kill docker-patch-test
The above command should have printed (among other things!) Server: nginx/1.15.12
, indicating success!
Please feel free to open PRs, Issues, or send me an email!