将VM虚拟机镜像转换为容器镜像

目录
  1. 从本地VM创建TAR文件
  2. 从远程VM创建TAR文件
  3. 从TAR文件创建Docker镜像

作者:杨冬 欢迎转载,也请保留这段声明。谢谢!
出处:https://andyyoung01.github.io/http://andyyoung01.16mb.com/

Docker Hub上并不会有所有可能的基础镜像,对于一些特定的Linux发行版及用例,人们需要自己创建。或者你已经有一个已经存在的VM状态,想要将其放入docker继续进行迭代,来享有Docker生态系统的好处,这就需要将VM虚拟机的镜像转换为Docker镜像。

在理想的世界中,将VMs转换成容器,可以只是在某个与你的VMs类似的发行版的Docker镜像上简单地运行配置管理脚本;或者从头构建一个与你的VM等同的docker镜像,使用标准的Docker技术,如Dockerfiles,配合上标准的配置管理工具。然而在现实里,很多虚拟机并没有认真地进行配置管理,随着VM的使用,使用更加结构化的方式重新构建容器镜像并不值得。所以从VM镜像直接转换为docker镜像更加省时省力。
这是通过使用qemu-nbd工具来从VM的文件系统中创建TAR文件来实现的。在TAR文件创建完成后,在Dockerfile中使用ADD命令把TAR文件加入到scratch镜像中,从而完成容器镜像的创建。

从本地VM创建TAR文件

在开始前,需要做以下准备:

  • 安装qemu-nbd工具(Ubuntu上为qemu-utils包,CentOS上为qemu-img包)。
  • 编译安装nbd.ko核心模块(编译过程参考此处此处)。
  • 找到VM磁盘镜像的文件路径。
  • 关闭你的VM。

如果VM磁盘镜像的格式为.vdi或.vmdk格式,则此技术应该可以成功。其它格式的虚拟机镜像则可能成功也可能不成功。下面的命令组演示了怎样将你的VM镜像文件转换成虚拟磁盘,以便于拷贝所有其中的文件并且打成一个TAR包:

1
2
3
4
5
6
7
$ sudo modprobe nbd max_part=8
$ lsmod | grep nbd
$ sudo qemu-nbd -c /dev/nbd0 -r ~/centos7.vdi
$ ls /dev/nbd0*
$ sudo mount /dev/nbd0p2 /mnt
$ sudo tar cf img.tar -C /mnt .
$ sudo umount /mnt && sudo qemu-nbd -d /dev/nbd0

上面代码第1行加载由qemu-nbd需要的编译好的nbd模块,注意要加上后面的参数max_part=8,否则后面使用qemu-nbd连接磁盘到虚拟设备节点时不能自动将磁盘的分区连接上(就是后面第4行执行的结果不会显示出/dev/nbd0p1等节点);第2行确认模块加载成功;第3行将VM磁盘连接到虚拟设备节点上;第4行查看可用的分区以便于挂载使用;第5行将虚拟磁盘第二个分区挂载到/mnt挂载点上;第6行创建tar文件;第7行卸载和断开到VM的连接。这样便得到了需要的tar文件。

使用sudo cfdisk /dev/nbd0命令来查看虚拟磁盘中有什么分区。注意如果里面包含LVM分区的话,需要使用其它方法挂载LVM分区。

从远程VM创建TAR文件

如果VM在远程,可以或者关闭VM并且将你需要的分区dump出来,或者在VM仍然运行时创建一个TAR文件。
如果你得到了分区的dump文件,你可以简单得将此文件mount后将其转换为TAR文件,如下:

1
2
3
$ sudo mount -o loop partition.dump /mnt
$ sudo tar cf $(pwd)/img.tar -C /mnt .
$ sudo umount /mnt

或者你可以从一个仍在运行的系统创建TAR文件。在你登录进系统后也非常简单,如下:

1
2
$ cd /
$ sudo tar cf /img.tar --exclude=/img.tar --one-file-system /

创建了TAR文件后就可以通过scp命令将此文件传送到其它机器。

从TAR文件创建Docker镜像

一旦从VM的文件系统得到了TAR文件,就可以将其添加到容器镜像中。这非常简单,由包含2行代码的Dockerfile就可以实现:

FROM scratch
ADD img.tar /

然后就可以通过docker build .命令来构建你的容器镜像!
现在已经有了一个可用的Docker镜像了,但是我们还想将镜像的大小精简,以便以此镜像为基础创建其它镜像。我们可以试验着将镜像中的文件减小,包括删除无用文件,strip可执行文件等,直到满意为止,然后就可以使用docker export命令导出一个新的、更加精简的TAR文件,此文件便可作为其它镜像的基础。