rewrite containerd docker tarballs
#!/bin/bash | |
# | |
# rewrite-docker-tar ./image.tar ./output.tar | |
# | |
# Exporting 'docker' tarballs with buildctl is creating manifests with no file | |
# extensions (no .json or .tar.gz on the config or layers). This works with | |
# dockerd because it never looks at the extensions just tries various things with | |
# safe fallbacks. Other tooling relies on extensions and checks for | |
# .json, .tar, and .tar.gz. | |
# | |
# This script will rebuild one of these containerd tarballs with file | |
# extensions so most other tooling can process it. | |
# | |
# This is probably brittle as hell. | |
set -euo pipefail | |
image=${1:-''} | |
result=${2:-''} | |
if [[ -z "${image}" || -z "${result}" ]]; then | |
echo "Usage: rewrite-docker-tar in.tar out.tar" && exit 1 | |
fi | |
workdir=$(mktemp -d -t rewrite-docker-tar.XXXX) | |
image_dir=${workdir}/image | |
output_dir=${workdir}/output | |
mkdir -p ${image_dir} ${output_dir} | |
cleanup(){ | |
rc=${1:-0} | |
find ${workdir} | |
test -d ${workdir} && rm -rf ${workdir} | |
exit ${rc} | |
} | |
trap cleanup EXIT | |
contents=$(tar -tf ${image}) | |
tar -C ${image_dir} -xf ${image} | |
manifest=${image_dir}/manifest.json | |
# Extract the current manifest, I have only seen these fields in produced images. | |
config_json=$(jq -r '.[].Config' ${manifest}) | |
layers=() | |
for layer in $(jq -r '.[].Layers[]' ${manifest}); do | |
layers+=(${layer}) | |
done | |
# Rename files | |
mv ${image_dir}/${config_json}{,.json} | |
for layer in ${layers[@]}; do | |
mv ${image_dir}/${layer}{,.tar.gz} | |
done | |
# Rewrite json | |
#jq --arg manifest "${manifest}.json" '.[].Config = $manifest' ${image_dir}/manifest.json | |
sed -i -e 's|'"${config_json}"'|'"${config_json}"'.json|' ${image_dir}/manifest.json | |
for layer in ${layers[@]}; do | |
sed -i -e 's|'"${layer}"'|'"${layer}"'.tar.gz|' ${image_dir}/manifest.json | |
done | |
# Build output tar, this could totally be incomplete if the format changes in containerd. | |
# | |
pushd ${image_dir} > /dev/null | |
tar -cf ${output_dir}/out.tar -T /dev/null > /dev/null | |
for file in *; do | |
tar -rf ${output_dir}/out.tar ${file} | |
done | |
popd > /dev/null | |
mv ${output_dir}/out.tar ${result} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment