我如何使用Docker的“git-like”function?

更新我特别感兴趣的是如何运行或回滚到特定版本的(二进制)图像从docker,并试图澄清这个问题的影响。

Docker FAQ说:

Docker包括用于跟踪容器的连续版本,检查版本之间的差异,提交新版本,回滚等类似git的function。历史logging还包括如何组装一个容器以及由谁来完成,因此您可以从生产服务器一路回到上游开发商。

谷歌,我可以find没有“回滚”到一个早期的容器,检查差异等的例子(很明显,我可以做版本pipe理的Dockerfiles这样的事情,但二进制docker的图像/容器可以改变,即使当Dockerfile不会,由于更新的软件来源,我正在寻找一种方法来查看和回滚之间的这种变化)。

举一个基本的例子:假设我跑步

docker build -t myimage . 

在一个Dockerfile,只是更新基地的Ubuntu的:

 FROM ubuntu:14:04 RUN apt-get update -q && apt-get upgrade -y 

如果几天后我制作了这个相同的图像,我怎么能区分这些图像,看看哪些软件包已经升级了? 之后再次运行相同的构build命令后,如何回滚到早期版本的图像?

编辑 :技术上我们只回滚AUFS层,不一定回滚历史。 如果我们的工作stream包含交互式修改容器和使用docker commit更改,那么这确实会回滚历史logging,因为它会删除我们在后面的图层中应用的任何程序包更新,而将版本保留在先前的图层中。 如果我们从Dockerfile重build图像,这是非常不同的。 那么这里没有任何东西让我们回到我们已经构build的以前的版本,我们只能从Dockerfile中删除步骤(层)。 换句话说,我们只能将docker commit的历史回滚到一个映像。

看起来回滚到一个较早版本的docker镜像的关键是简单地将docker标签指向一个较早的hash。

例如,考虑检查标准的ubuntu:latesthistory ubuntu:latest形象:

 docker history ubuntu:latest 

显示:

 IMAGE CREATED CREATED BY SIZE ba5877dc9bec 3 weeks ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B 2318d26665ef 3 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.903 kB ebc34468f71d 3 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 8 B 25f11f5fb0cb 3 weeks ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB 9bad880da3d2 3 weeks ago /bin/sh -c #(nop) ADD file:de2b0b2e36953c018c 192.5 MB 511136ea3c5a 14 months ago 0 B 

想象一下,我们想要回到由散列25f指示的图像:

 docker tag 25f ubuntu:latest docker history ubuntu:latest 

我们看到:

 IMAGE CREATED CREATED BY SIZE 25f11f5fb0cb 3 weeks ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB 9bad880da3d2 3 weeks ago /bin/sh -c #(nop) ADD file:de2b0b2e36953c018c 192.5 MB 511136ea3c5a 14 months ago 0 B 

当然,我们可能永远都不想这样回滚,因为它使ubuntu:latest实际上不是我们当地图书馆中最新的ubuntu。 请注意,我们可以使用任何我们想要的标签,例如

 docker tag 25f ubuntu:notlatest 

或者简单地通过哈希启动旧图像:

 docker run -it 25f /bin/bash 

这么简单,但很整洁。 请注意,我们可以将其与docker inspect结合起来,以获得Docker FAQ所引用的每个映像的元数据的更多细节。

另外请注意, docker diffdocker commit与这个过程并不相关,因为它们指的是容器(例如运行图像),而不是直接指向图像。 也就是说,如果我们以交互方式运行图像,然后添加或更改图像上的文件,我们可以通过使用docker diff <Container-id>来看到更改(在容器之间),并使用docker commit <Container id>提交更改。

我不确定你是否真的可以使用散列作为标签。 散列IIRC是对图像本身的引用,而标记更多地是图像上的元数据字段。

标签functionimho是相当不好的logging,但你应该使用它的方式可能是通过使用语义版本的sorting来组织你的标签和图像。 我们正在将一个复杂的(12-microservice)系统转移到使用Docker,并且依靠latest我迅速完成了语义版本化和Git Repo中的更改日志,以跟踪更改。

如果你说有一个docker分支会自动进行修改并在DockerHub上触发一个构build,那么这也可以是很好的 – 你可以更新一个更新日志并且知道哪个hash / timestamp与什么结合。

就个人而言,由于DockerHub构build触发器目前较为缓慢,我倾向于手动为每个映像声明一个标记并保存更改日志,但是YMMV和我怀疑这些工具会更好。