Files
minideb/buildall
T
James Westby 44030c910b Make the image build reproducible
Change the mkimage script so that the produced image is
reproducible. This involves:

   - removing the ldconfig aux-cache as it changes on every build.
   - set the mtimes of the files to a specific date so that the
     resulting tar file will have the same contents.
   - The `strings` guard around the unsafe-io tweak seems to be
     non-deterministic. It was sometimes not adding the tweak
     for the same file. Remove it as we don't care about older
     than jessie.
   - Importing the image by constructing a docker image with
     a specific timestamp and doing `docker load`.

Also change the buildall script to build each image twice and
confirm that the same tarball is produced, and that results
in the layers in the imported images matching.

Add a dockerdiff script that checks that two images are equivalent,
and tries to show the differences if not. This is useful when the
build script reports differences, as it can point to what the
differences are.
2017-02-10 11:48:28 +00:00

98 lines
3.8 KiB
Bash
Executable File

#!/bin/bash
# Build a minideb image for each supported dist
#
# First we build the image as a tarball, then we import it and tag it.
#
# However we aim to allow our images to be reproduced. That means
# we need more control over the import process. We also build and import
# each image twice to confirm that our images are still reproducible.
#
# To reproduce an image you have to:
#
# - Produce exactly the same base tarball. `mkimage` will take care of that
# for the same package inputs.
# - Import the image with the same config (`CMD` etc.)
# - Have the same creation date on the image.
#
# That last requirement leads us to some extra work to re-use timestamps.
#
# The steps are:
#
# 1. Pull image from Dockerhub and save creation date and image_id
# 2. Build image locally and import it, setting creation date to the pulled one
# 3. Build the image again and import it, also setting creation date to the pulled one
# 4. Compare the built image ids. Error if they are not the same (Docker thinks images are different, thanks to checksum)
# 5. Compare built image id with pulled image id. Both will have same creation date but may differ in checksum so ids may be different
# - If the image is the same as the pulled one then nothing changed in this build
# - If the image differs from the pulled one then:
# - Re-import the locally built image with the current timestamp so it will be shown as a new image
# - Tag the built image with the target tag, ready to push.
set -e
set -u
set -o pipefail
DISTS="jessie
unstable
"
LATEST=jessie
BASENAME=bitnami/minideb
GCR_BASENAME=gcr.io/bitnami-containers/minideb
mkdir -p build
log() {
echo "$@" >&2
}
for DIST in $DISTS; do
[ -f debootstrap/$DIST ] || (echo "buildall: Unknown distribution: $DIST" && exit 1)
current_ts="$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)"
if docker pull $BASENAME:$DIST > /dev/null; then
target_ts="$(docker inspect $BASENAME:$DIST | jq --raw-output ".[0].Created")"
pulled_image_id="$(docker inspect $BASENAME:$DIST | jq --raw-output ".[0].Id")"
else
target_ts="$current_ts"
pulled_image_id=
fi
log "============================================"
log "Building $BASENAME:$DIST"
log "============================================"
./mkimage build/$DIST.tar $DIST
built_image_id=$(./import build/$DIST.tar "$target_ts")
log "============================================"
log "Running tests for $BASENAME:$DIST"
log "============================================"
./test $built_image_id
log "============================================"
log "Rebuilding $BASENAME:$DIST to test reproducibility"
log "============================================"
./mkimage build/${DIST}-repro.tar $DIST
repro_image_id=$(./import build/${DIST}-repro.tar "$target_ts")
if [ "$repro_image_id" != "$built_image_id" ]; then
log "$BASENAME:$DIST differs after a rebuild. Examine $built_image_id and $repro_image_id"
log "to find the differences and fix the build to be reproducible again."
log "Running \`./dockerdiff $built_image_id $repro_image_id\` might be useful."
exit 1
fi
rm build/${DIST}-repro.tar
if [ -n "$pulled_image_id" ]; then
if [ "$built_image_id" != "$pulled_image_id" ]; then
log "Image changed $built_image_id (new) != $pulled_image_id (old)"
# Re-import with the current timestamp so that the image shows
# as new
built_image_id="$(./import build/$DIST.tar "$current_ts")"
else
log "Image didn't change"
continue
fi
fi
docker tag $built_image_id $BASENAME:$DIST
docker tag $built_image_id $GCR_BASENAME:$DIST
log "Tagged $built_image_id as $BASENAME:$DIST $GCR_BASENAME:$DIST"
done
docker tag $BASENAME:$LATEST $BASENAME:latest
docker tag $GCR_BASENAME:$LATEST $GCR_BASENAME:latest