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