github.com/afbjorklund/moby@v20.10.5+incompatible/contrib/dockerize-disk.sh (about) 1 #!/usr/bin/env bash 2 set -e 3 4 if ! command -v qemu-nbd &> /dev/null; then 5 echo >&2 'error: "qemu-nbd" not found!' 6 exit 1 7 fi 8 9 usage() { 10 echo "Convert disk image to docker image" 11 echo "" 12 echo "usage: $0 image-name disk-image-file [ base-image ]" 13 echo " ie: $0 cirros:0.3.3 cirros-0.3.3-x86_64-disk.img" 14 echo " $0 ubuntu:cloud ubuntu-14.04-server-cloudimg-amd64-disk1.img ubuntu:14.04" 15 } 16 17 if [ "$#" -lt 2 ]; then 18 usage 19 exit 1 20 fi 21 22 CURDIR=$(pwd) 23 24 image_name="${1%:*}" 25 image_tag="${1#*:}" 26 if [ "$image_tag" == "$1" ]; then 27 image_tag="latest" 28 fi 29 30 disk_image_file="$2" 31 docker_base_image="$3" 32 33 block_device=/dev/nbd0 34 35 builddir=$(mktemp -d) 36 37 cleanup() { 38 umount "$builddir/disk_image" || true 39 umount "$builddir/workdir" || true 40 qemu-nbd -d $block_device &> /dev/null || true 41 rm -rf $builddir 42 } 43 trap cleanup EXIT 44 45 # Mount disk image 46 modprobe nbd max_part=63 47 qemu-nbd -rc ${block_device} -P 1 "$disk_image_file" 48 mkdir "$builddir/disk_image" 49 mount -o ro ${block_device} "$builddir/disk_image" 50 51 mkdir "$builddir/workdir" 52 mkdir "$builddir/diff" 53 54 base_image_mounts="" 55 56 # Unpack base image 57 if [ -n "$docker_base_image" ]; then 58 mkdir -p "$builddir/base" 59 docker pull "$docker_base_image" 60 docker save "$docker_base_image" | tar -xC "$builddir/base" 61 62 image_id=$(docker inspect -f "{{.Id}}" "$docker_base_image") 63 while [ -n "$image_id" ]; do 64 mkdir -p "$builddir/base/$image_id/layer" 65 tar -xf "$builddir/base/$image_id/layer.tar" -C "$builddir/base/$image_id/layer" 66 67 base_image_mounts="${base_image_mounts}:$builddir/base/$image_id/layer=ro+wh" 68 image_id=$(docker inspect -f "{{.Parent}}" "$image_id") 69 done 70 fi 71 72 # Mount work directory 73 mount -t aufs -o "br=$builddir/diff=rw${base_image_mounts},dio,xino=/dev/shm/aufs.xino" none "$builddir/workdir" 74 75 # Update files 76 cd $builddir 77 LC_ALL=C diff -rq disk_image workdir \ 78 | 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" \ 79 | while read action entry; do 80 case "$action" in 81 ADD | UPDATE) 82 cp -a "disk_image$entry" "workdir$entry" 83 ;; 84 DEL) 85 rm -rf "workdir$entry" 86 ;; 87 *) 88 echo "Error: unknown diff line: $action $entry" >&2 89 ;; 90 esac 91 done 92 93 # Pack new image 94 new_image_id="$(for i in $(seq 1 32); do printf "%02x" $(($RANDOM % 256)); done)" 95 mkdir -p $builddir/result/$new_image_id 96 cd diff 97 tar -cf $builddir/result/$new_image_id/layer.tar * 98 echo "1.0" > $builddir/result/$new_image_id/VERSION 99 cat > $builddir/result/$new_image_id/json <<- EOS 100 { "docker_version": "1.4.1" 101 , "id": "$new_image_id" 102 , "created": "$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)" 103 EOS 104 105 if [ -n "$docker_base_image" ]; then 106 image_id=$(docker inspect -f "{{.Id}}" "$docker_base_image") 107 echo ", \"parent\": \"$image_id\"" >> $builddir/result/$new_image_id/json 108 fi 109 110 echo "}" >> $builddir/result/$new_image_id/json 111 112 echo "{\"$image_name\":{\"$image_tag\":\"$new_image_id\"}}" > $builddir/result/repositories 113 114 cd $builddir/result 115 116 # mkdir -p $CURDIR/$image_name 117 # cp -r * $CURDIR/$image_name 118 tar -c * | docker load