contrib/dockerize-disk.sh
d1af2bc2
 #!/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
8630ad15
 LC_ALL=C diff -rq disk_image workdir \
d1af2bc2
   | 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