如何将代码从Git更新到Docker容器

我有一个Docker文件试图将Django代码部署到一个容器

FROM ubuntu:latest MAINTAINER { myname } #RUN echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main universe" >> /etc/apt/sou$ RUN apt-get update RUN DEBIAN_FRONTEND=noninteractive apt-get install -y tar git curl dialog wget net-tools nano buil$ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python python-dev python-distribute python-p$ RUN mkdir /opt/app WORKDIR /opt/app #Pull Code RUN git clone git@bitbucket.org/{user}/{repo} RUN pip install -r website/requirements.txt #EXPOSE = ["8000"] CMD python website/manage.py runserver 0.0.0.0:8000 

然后我构build我的代码作为docker build -t dockerhubaccount/demo:v1 . ,这将我的代码从Bitbucket拉到容器。 我运行它作为docker run -p 8000:8080 -td felixcheruiyot/demo:v1和东西似乎工作正常。

现在我想更新代码,即因为我使用git clone ... ,我有这个困惑:

  • 当我有新的提交时,并且在Docker容器使用新的代码构build它时,我怎样才能更新我的代码(注意:当我运行构build时,它不会因为caching而获取它)。
  • 什么是这种方法的最佳工作stream程?

有几种方法可以使用。

  1. 您可以使用docker build --no-cache来避免使用Git克隆的caching。
  2. 启动命令调用git pull 。 所以不是运行python manage.py ,而是使用CMD cd /repo && git pull && python manage.py或者在事情更复杂的情况下使用启动脚本。

我倾向于更喜欢2.你也可以运行一个cron工作来更新你的容器中的代码,但是这是一个更多的工作,有点违背了Docker的理念。

我build议你在主机上签出代码并COPY到图像中。 这样,每当你做出改变,它都会被更新。 而且,在开发过程中,您可以将源目录绑定到容器中的代码目录上,这意味着任何更改都会立即反映在容器中。

虽然git仓库的docker命令检查最后一次更新将是非常有用的!

解决scheme

只要指令string与caching图像完全相同,Docker构build命令就会使用caching。 所以,如果你写

 RUN echo '2014122400' >/dev/null && git pull ... 

在下次更新时,您更改如下。

 RUN echo '2014122501' >/dev/null && git pull ... 

这可以防止docker使用caching。

我想提供另一个可能的解决scheme。 然而,我需要警告的是,这绝对不是做事的“docker方式”,而是依赖于卷的存在(这可能是像Docker Swarm和Kubernetes这样的工具的潜在阻碍者)

我们将要利用的基本原则是用作Docker卷的容器目录的内容实际上存储在主机的文件系统中。 看看这部分的文档。

在你的情况下,你会/opt/app Docker卷。 您不需要将卷明确映射到主机文件系统上的某个位置,因为如下所述,可以dynamic获取映射。

因此,对于初学者,将Dockerfile完全保持原样,并将您的容器创build命令切换为如下所示:

 docker run -p 8000:8080 -v /opt/app --name some-name -td felixcheruiyot/demo:v1 

命令docker inspect -f {{index .Volumes "/opt/webapp"}} some-name将会在代码存储的主机上打印完整的文件系统path( 这是我拿起检查技巧的地方)。

有了这些知识,你所要做的就是replace那些代码和你所有的东西。 所以一个非常简单的部署脚本就像这样:

 code_path=$(docker inspect -f {{index .Volumes "/opt/webapp"}} some-name) rm -rfv $code_path/* cd $code_path git clone git@bitbucket.org/{user}/{repo} 

你用这种方法得到的好处是:

  • 没有潜在的昂贵的无caching图像重build
  • 不需要将应用程序特定的运行信息移动到运行命令中。 Dockerfile是检测应用程序所需的唯一来源

UPDATE

您可以使用docker cp (启动Docker 1.8)来达到上述相同的结果。 通过这种方式,容器不需要卷,并且可以像在主机文件系统上那样replace容器中的代码。

当然,正如我在回答开头所提到的,这不是“做事的泊坞子”,它主张容器是不变的,可重复的。

如果使用GitHub,则可以使用GitHub API不caching特定的RUN命令。

你需要安装jq来parsingJSON: apt-get install -y jq

例:

 docker build --build-arg SHA=$(curl -s 'https://api.github.com/repos/Tencent/mars/commits' | jq -r '.[0].sha') -t imageName . 

在Dockerfile中(ARG命令应该在RUN之前):

 ARG SHA=LATEST RUN SHA=${SHA} \ git clone https://github.com/Tencent/mars.git 

或者如果你不想安装jq:

 SHA=$(curl -s 'https://api.github.com/repos/Tencent/mars/commits' | grep sha | head -1) 

如果一个仓库有新的提交, git clone将被执行。