Posted at
DockerDay 23

Docker コンテナと仮想マシン間の変換(お試しレベル)

More than 3 years have passed since last update.

Docker Advent Calendar 2015 23日目の記事です。。。が、まだ途中です。すみません。。。


概要

実用性は別にして、ふと、「既存の仮想マシン環境をコンテナとして実行できないか、また逆に、コンテナを仮想マシンに変換できないか」と思い立ったので、お試しレベルでやってみました。


仮想マシンから Docker イメージへの変換

仮想マシン上にはコンテナとして動作するのに必要なファイルが揃っているので(逆に余分なファイルが多い)、容量など考えずに単純に Docker イメージにするだけなら簡単です。

[お試し環境]


  • 仮想マシン: CentOS7.1 (on Hyper-V)

  • Dockerホスト: CentOS7.1 + Docker1.9.1

まずは、仮想マシン上のファイルを tar で取り出します。取り出し途中のファイルの整合性(停止点の確保)とかは考えてません。


仮想マシン側

# 不要なディレクトリとファイルを tar に含めないために、以下のファイルを作成しておく。

$ cat /tmp/exclude.txt
/boot/*
/dev/*
/mnt/*
/proc/*
/sys/*
/tmp/*

# 仮想マシン上のファイルを収集。
$ sudo tar czpf /tmp/vmfiles.tar.gz / -X /tmp/exclude.txt

# 生成された tar.gz ファイル
$ ls -lh vmfiles.tar.gz
-rw-r--r--. 1 root root 424M Dec 23 08:50 vmfiles.tar.gz

# これを Docker ホストへ転送する
$ scp /tmp/vmfiles.tar.gz root@dockerhost:/tmp/


Docker ホスト側で、この tar.gz を Docker イメージとしてインポートします。


Dockerホスト側

# インポート

$ cat /tmp/vmfiles.tar.gz | docker import - vmimage

# インポートされたことを確認
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
vmimage latest d5285c5cec5d 3 minutes ago 1.3 GB


インポートに成功しましたが サイズが 1.3GB とかなり大きいです。本当なら、Base Image からの差分だけを含めるようにしたいのですが。

コンテナを起動してみます。まぁ普通に起動しますが、これだけだと面白いことは何も無いですね。。。


Dockerホスト側

$ docker run -it --name test1 vmimage /bin/bash

[root@ed455f3e2a46 /]# ls /
bin dev home lib64 media opt root sbin sys usr
boot etc lib lost+found mnt proc run srv tmp var

# ホスト名はコンテナのIDに変更されている
[root@ed455f3e2a46 /]# hostname
ed455f3e2a46



Docker コンテナから仮想マシンイメージへの変換

こちらは少し難しいです。Docker コンテナには仮想マシンとして起動させるためのファイルやブートローダーが含まれてないので、それを補ってあげる必要があります。

まず、対象となるコンテナのディレクトリツリーを tar にエクスポート。


Dockerホスト側

# docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
804cf88745c0 centos "/bin/bash" 2 minutes ago Exited (0) About a minute ago test

# docker export test > container.tar
# ls -lh container.tar
-rw-r--r--. 1 root root 262M 12月 23 19:32 container.tar


次に、仮想マシン用のイメージファイルを作成して、そこにエクスポートしたファイルを流し込みます。

Linux に詳しくないので正しい手順なのか分かりませんが、以下のようにしてみました。


Dockerホスト側


[空のイメージファイルを作成]
# dd if=/dev/zero of=disk.img bs=1M count=2048

[fdisk でパーティションを作成]
# fdisk disk.img

[イメージファイルのパーティションテーブルからデバイスマップを作成]
# kpartx -av disk.img

[フォーマット&マウント]
# mkfs.ext4 /dev/mapper/loop0p1
# mount /dev/mapper/loop0p1 /mnt

[エクスポートしたコンテナのディレクトリツリーをイメージファイル内に展開]
# tar xvf container.tar -C /mnt


もちろんこれだけで起動するイメージにはならなくて、この後 Kernel や Grub などのインストールや設定が必要になります。

続きはまた時間のある時に試してみます(なんか、Docker の話から離れてるし・・・)。