|
@@ -0,0 +1,118 @@
|
|
|
|
+#!/usr/bin/env bash
|
|
|
|
+set -e
|
|
|
|
+
|
|
|
|
+if ! command -v qemu-nbd &> /dev/null; then
|
|
|
|
+ echo >&2 'error: "qemu-nbd" not found!'
|
|
|
|
+ exit 1
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+usage() {
|
|
|
|
+ echo "Convert disk image to docker image"
|
|
|
|
+ echo ""
|
|
|
|
+ echo "usage: $0 image-name disk-image-file [ base-image ]"
|
|
|
|
+ echo " ie: $0 cirros:0.3.3 cirros-0.3.3-x86_64-disk.img"
|
|
|
|
+ echo " $0 ubuntu:cloud ubuntu-14.04-server-cloudimg-amd64-disk1.img ubuntu:14.04"
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+if [ "$#" -lt 2 ]; then
|
|
|
|
+ usage
|
|
|
|
+ exit 1
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+CURDIR=$(pwd)
|
|
|
|
+
|
|
|
|
+image_name="${1%:*}"
|
|
|
|
+image_tag="${1#*:}"
|
|
|
|
+if [ "$image_tag" == "$1" ]; then
|
|
|
|
+ image_tag="latest"
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+disk_image_file="$2"
|
|
|
|
+docker_base_image="$3"
|
|
|
|
+
|
|
|
|
+block_device=/dev/nbd0
|
|
|
|
+
|
|
|
|
+builddir=$(mktemp -d)
|
|
|
|
+
|
|
|
|
+cleanup() {
|
|
|
|
+ umount "$builddir/disk_image" || true
|
|
|
|
+ umount "$builddir/workdir" || true
|
|
|
|
+ qemu-nbd -d $block_device &> /dev/null || true
|
|
|
|
+ rm -rf $builddir
|
|
|
|
+}
|
|
|
|
+trap cleanup EXIT
|
|
|
|
+
|
|
|
|
+# Mount disk image
|
|
|
|
+modprobe nbd max_part=63
|
|
|
|
+qemu-nbd -rc ${block_device} -P 1 "$disk_image_file"
|
|
|
|
+mkdir "$builddir/disk_image"
|
|
|
|
+mount -o ro ${block_device} "$builddir/disk_image"
|
|
|
|
+
|
|
|
|
+mkdir "$builddir/workdir"
|
|
|
|
+mkdir "$builddir/diff"
|
|
|
|
+
|
|
|
|
+base_image_mounts=""
|
|
|
|
+
|
|
|
|
+# Unpack base image
|
|
|
|
+if [ -n "$docker_base_image" ]; then
|
|
|
|
+ mkdir -p "$builddir/base"
|
|
|
|
+ docker pull "$docker_base_image"
|
|
|
|
+ docker save "$docker_base_image" | tar -xC "$builddir/base"
|
|
|
|
+
|
|
|
|
+ image_id=$(docker inspect -f "{{.Id}}" "$docker_base_image")
|
|
|
|
+ while [ -n "$image_id" ]; do
|
|
|
|
+ mkdir -p "$builddir/base/$image_id/layer"
|
|
|
|
+ tar -xf "$builddir/base/$image_id/layer.tar" -C "$builddir/base/$image_id/layer"
|
|
|
|
+
|
|
|
|
+ base_image_mounts="${base_image_mounts}:$builddir/base/$image_id/layer=ro+wh"
|
|
|
|
+ image_id=$(docker inspect -f "{{.Parent}}" "$image_id")
|
|
|
|
+ done
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+# Mount work directory
|
|
|
|
+mount -t aufs -o "br=$builddir/diff=rw${base_image_mounts},dio,xino=/dev/shm/aufs.xino" none "$builddir/workdir"
|
|
|
|
+
|
|
|
|
+# Update files
|
|
|
|
+cd $builddir
|
|
|
|
+diff -rq disk_image workdir \
|
|
|
|
+ | sed -re "s|Only in workdir(.*?): |DEL \1/|g;s|Only in disk_image(.*?): |ADD \1/|g;s|Files disk_image/(.+) and workdir/(.+) differ|UPDATE /\1|g" \
|
|
|
|
+ | while read action entry; do
|
|
|
|
+ case "$action" in
|
|
|
|
+ ADD|UPDATE)
|
|
|
|
+ cp -a "disk_image$entry" "workdir$entry"
|
|
|
|
+ ;;
|
|
|
|
+ DEL)
|
|
|
|
+ rm -rf "workdir$entry"
|
|
|
|
+ ;;
|
|
|
|
+ *)
|
|
|
|
+ echo "Error: unknown diff line: $action $entry" >&2
|
|
|
|
+ ;;
|
|
|
|
+ esac
|
|
|
|
+ done
|
|
|
|
+
|
|
|
|
+# Pack new image
|
|
|
|
+new_image_id="$(for i in $(seq 1 32); do printf "%02x" $(($RANDOM % 256)); done)"
|
|
|
|
+mkdir -p $builddir/result/$new_image_id
|
|
|
|
+cd diff
|
|
|
|
+tar -cf $builddir/result/$new_image_id/layer.tar *
|
|
|
|
+echo "1.0" > $builddir/result/$new_image_id/VERSION
|
|
|
|
+cat > $builddir/result/$new_image_id/json <<-EOS
|
|
|
|
+{ "docker_version": "1.4.1"
|
|
|
|
+, "id": "$new_image_id"
|
|
|
|
+, "created": "$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)"
|
|
|
|
+EOS
|
|
|
|
+
|
|
|
|
+if [ -n "$docker_base_image" ]; then
|
|
|
|
+ image_id=$(docker inspect -f "{{.Id}}" "$docker_base_image")
|
|
|
|
+ echo ", \"parent\": \"$image_id\"" >> $builddir/result/$new_image_id/json
|
|
|
|
+fi
|
|
|
|
+
|
|
|
|
+echo "}" >> $builddir/result/$new_image_id/json
|
|
|
|
+
|
|
|
|
+echo "{\"$image_name\":{\"$image_tag\":\"$new_image_id\"}}" > $builddir/result/repositories
|
|
|
|
+
|
|
|
|
+cd $builddir/result
|
|
|
|
+
|
|
|
|
+# mkdir -p $CURDIR/$image_name
|
|
|
|
+# cp -r * $CURDIR/$image_name
|
|
|
|
+tar -c * | docker load
|