Git的Dockerfile策略

使用Dockerfile将私有Git存储库克隆到Docker容器中的最佳策略是什么? 优点缺点?

我知道我可以在Dockerfile上添加命令,以便将我的私有存储库克隆到Docker容器中。 但是我想知道人们在这个案例中使用了哪些不同的方法。

这不在Dockerfile最佳实践指南中。

你通常有两种方法:

  • 通过引用保险箱,您可以获取必要的秘密数据,以访问需要放置在映像中的内容(这里是您的ssh密钥以访问您的私人回购)
  • 或挤压技术

对于第二种方法,请参阅“将Git拖放到Docker镜像中而不将SSH密钥留在后面 ”

  • 将私钥添加到Dockerfile
  • 把它添加到ssh-agent
  • 运行需要SSHauthentication的命令
  • 删除私钥

Dockerfile:

ADD ~/.ssh/mykey /tmp/ RUN ssh-agent /tmp # RUN bundle install or similar command RUN rm /tmp/mykey 

现在我们来构build这个图像:

 $ docker build -t original . 
  • 压扁图层:

     docker save original | sudo docker-squash -t squashed | docker load 

我会分享我迄今为止发现的。

将Git源代码放入Docker构build中有不同的策略。 其中许多与Docker的caching机制有不同的交互方式,可能或多或less适合您的项目以及您打算如何使用Docker。

运行git clone

如果你像我一样,当你在Dockerfile中看到你可以使用的命令时,首先会想到这个方法。 这样做的麻烦在于它可以通过Docker的构buildcaching机制以不直观的方式进行交互。 例如,如果您对git存储库进行了更新,然后重新运行具有RUN git clone命令的docker build,那么根据前面的Dockerfile命令是否已失效,可能会也可能不会得到新的提交caching。

解决这个问题的一个方法是使用docker build --no-cache ,但是如果克隆之前有任何时间密集的命令,他们将不得不再次运行。

另一个问题是你(或者你分发Dockerfile的人)可能会在上游的git仓库更新的时候意外地返回到一个坏的版本。

在这种情况下,仍然使用RUN git克隆的方法是把它放在一个具有特定版本签出的行上,例如:

 RUN git clone https://github.com/example/example.git && cd example && git checkout 0123abcdef 

然后,更新修订版以在Dockerfile中签出将使该行处的caching无效并导致克隆/检出运行。

这种方法的一个可能的缺点是你必须在你的容器中安装git。

运行curl或添加标记/提交压缩包URL

这样就避免了必须在你的容器环境中安装git,并且可以明确caching何时会中断(也就是说,如果标记/修订是URL的一部分,那么URL更改将会破坏caching)。 请注意,如果您使用Dockerfile ADD命令从远程URL进行复制,则每次运行构build时都会下载该文件,并且HTTP Last-Modified标头也将用于使caching失效。

你可以在golang Dockerfile中看到这个方法。

Dockerfile仓库中的Git子模块

如果您将Dockerfile和Docker构build在源代码的单独存储库中,或者您的Docker构build需要多个源存储库,那么在此存储库中使用git子模块(或git子树)可能是将源代码回收到构build中的有效方法上下文。 这可以避免一些Dockercaching和上游更新的问题,因为您在子模块/子树规范中locking了上游修订版本。 更新它们会改变你的Dockercaching,因为它改变了构build上下文。

请注意,这只会将这些文件放到Docker构build上下文中,您仍然需要在Dockerfile中使用ADD命令将这些path复制到容器中所期望的位置。

你可以在这里看到这个方法

git仓库中的Dockerfile

在这里,您只需将Dockerfile与您要构build/testing/部署的代码放在同一个git存储库中,以便自动作为构build上下文的一部分发送,因此您可以添加。 /项目将上下文复制到容器中。 这样做的好处是,你可以testing更改,而无需潜在地提交/推送它们到一个testingdocker构build; 缺点是每次修改工作目录中的任何文件都会使ADD命令中的caching失效。 发送大的源/数据目录的构build上下文也是耗时的。 所以,如果你使用这种方法,你也可能需要明智地使用.dockerignore文件 ,包括忽略.gitignore和.git目录本身的所有内容。

卷映射

如果您使用Docker来设置要在您的主机上的各种源回放之间共享的开发/testing环境,则将主机目录挂载为数据卷可能是一种可行的策略。 这使您可以指定在docker运行时包含哪些目录,并避免担心docker构buildcaching,但这些内容都不会在Dockerfile或容器映像的其他用户之间共享。

参考文献:

  • “Docker的Git策略” Ryan Baumann – / etc(博客),2015年7月29日