123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- #!/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
- LC_ALL=C 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
|