Docker映像格式

我想build立一个没有docker的Docker镜像。 我已经看过Packer ,但是它需要在构build器主机上安装Docker。

我已经看了DockerregistryAPI文档,但是这个信息似乎没有在那里。

我想这个图像只是一个压缩包,但我希望看到一个完整的格式说明,即需要什么样的格式,以及是否需要任何元数据文件。 我可以尝试从registry中下载图像,看看里面是什么,但没有关于如何获取图像本身的信息。

我的项目的想法是实现一个脚本,从我已经编译的exception中创build一个映像,并将其上传到registry中。 我想用OpenEmbedded来实现这个目的,本质上这是对Bitbake的扩展。

在阅读James Coyle的博客后 ,我想到docker savedocker load命令是我所需要的。

 > docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE progrium/consul latest e9fe5db22401 11 days ago 25.81 MB > docker save e9fe5db22401 | tar x > ls e9fe5db22401* VERSION json layer.tar 

VERSION文件只包含1.0 ,而json包含了相当多的信息:

 { "id": "e9fe5db224015ddfa5ee9dbe43b414ecee1f3108fb6ed91add11d2f506beabff", "parent": "68f9e4929a4152df9b79d0a44eeda042b5555fbd30a36f98ab425780c8d692eb", "created": "2014-08-20T17:54:30.98176344Z", "container": "3878e7e9b9935b7a1988cb3ebe9cd45150ea4b09768fc1af54e79b224bf35f26", "container_config": { "Hostname": "7f17ad58b5b8", "Domainname": "", "User": "", "Memory": 0, "MemorySwap": 0, "CpuShares": 0, "Cpuset": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "PortSpecs": null, "ExposedPorts": { "53/udp": {}, "8300/tcp": {}, "8301/tcp": {}, "8301/udp": {}, "8302/tcp": {}, "8302/udp": {}, "8400/tcp": {}, "8500/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "SHELL=/bin/bash" ], "Cmd": [ "/bin/sh", "-c", "#(nop) CMD []" ], "Image": "68f9e4929a4152df9b79d0a44eeda042b5555fbd30a36f98ab425780c8d692eb", "Volumes": { "/data": {} }, "WorkingDir": "", "Entrypoint": [ "/bin/start" ], "NetworkDisabled": false, "OnBuild": [ "ADD ./config /config/" ] }, "docker_version": "1.1.2", "author": "Jeff Lindsay <progrium@gmail.com>", "config": { "Hostname": "7f17ad58b5b8", "Domainname": "", "User": "", "Memory": 0, "MemorySwap": 0, "CpuShares": 0, "Cpuset": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "PortSpecs": null, "ExposedPorts": { "53/udp": {}, "8300/tcp": {}, "8301/tcp": {}, "8301/udp": {}, "8302/tcp": {}, "8302/udp": {}, "8400/tcp": {}, "8500/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "SHELL=/bin/bash" ], "Cmd": [], "Image": "68f9e4929a4152df9b79d0a44eeda042b5555fbd30a36f98ab425780c8d692eb", "Volumes": { "/data": {} }, "WorkingDir": "", "Entrypoint": [ "/bin/start" ], "NetworkDisabled": false, "OnBuild": [ "ADD ./config /config/" ] }, "architecture": "amd64", "os": "linux", "Size": 0 } 

layer.tar文件看起来是空的。 所以检查父母和祖父母都没有在他们的layer.tar文件中包含任何文件。

所以假设4.0K是一个空的压缩包的标准大小:

  for layer in $(du -hs */layer.tar | grep -v 4.0K | cut -f2) do (echo $layer:;tar tvf $layer) done 

看到这些包含对文件系统的简单增量更改。

所以有一个结论是,像Packer一样,最好使用Docker来构build映像并将其推送到registry中。

文档中描述了从头开始构build映像的方法。

事实certificate, docker import - scratch并不关心tarball中的内容。 我只是假设这是rootfs。

 > touch foo > tar c foo | docker import - scratch 02bb6cd70aa2c9fbaba37c8031c7412272d804d50b2ec608e14db054fc0b9fab > docker save 02bb6cd70aa2c9fbaba37c8031c7412272d804d50b2ec608e14db054fc0b9fab | tar x > ls 02bb6cd70aa2c9fbaba37c8031c7412272d804d50b2ec608e14db054fc0b9fab/ VERSION json layer.tar > tar tvf 02bb6cd70aa2c9fbaba37c8031c7412272d804d50b2ec608e14db054fc0b9fab/layer.tar drwxr-xr-x 0/0 0 2014-09-01 13:46 ./ -rw-r--r-- 500/500 0 2014-09-01 13:46 foo 

就OpenEmbedded集成而言,build立rootfs tarball可能是最好的,这是Yocto开箱即用的方式,并且使用官方的Python库来导入rootfs tar包中的import_image(src='rootfs.tar', repository='scratch') ,然后推送私人registry方法。

这不是最优雅的解决scheme,但这是目前的工作方式。 否则,可能只是用自己的方式来pipe理和部署rootfs修订版,只是在目标主机上使用docker import ,这仍然不是一个好的select,但有点简单。

Docker镜像格式在这里指定: https : //github.com/docker/docker/blob/master/image/spec/v1.md

最简单的图像是一个包含以下内容的tar文件:

 repositories uniqid/VERSION uniqid/json uniqid/layer.tar 

其中VERSION包含1.0 ,layer.tar包含chroot内容,json / repositories是JSON文件,如上面的spec中所指定的。

生成的tar可以通过docker load < image.tar加载到docker load < image.tar