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

时间:2014-12-17 15:35:43

标签: python git deployment continuous-integration 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

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

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

  • 我有新的提交时如何更新我的代码,在Docker容器构建时,它会附带新代码(注意:当我运行构建时,由于缓存而无法获取它)。
  • 这种方法的最佳工作流程是什么?

5 个答案:

答案 0 :(得分:21)

您可以使用几种方法。

  1. 您可以使用docker build --no-cache来避免使用Git克隆的缓存。
  2. 启动命令调用git pull。因此,如果事情更复杂,您可以使用python manage.py或使用启动脚本,而不是运行CMD cd /repo && git pull && python manage.py
  3. 我倾向于选择2.您也可以运行一个cron作业来更新容器中的代码,但这样做的工作要多一些,并且与Docker的理念有所不同。

答案 1 :(得分:10)

我建议您检查主机上的代码并将其COPY放入图片中。这样,无论何时进行更改,它都会更新。此外,在开发期间,您可以将源目录绑定到容器中的代码目录,这意味着任何更改都会立即反映在容器中。

用于检查上次更新的git存储库的docker命令非常有用!

答案 2 :(得分:6)

另一种解决方案。

只要指令字符串与缓存图像完全相同,Docker构建命令就会使用缓存。所以,如果你写的话

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

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

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

这可以防止docker使用缓存。

答案 3 :(得分:2)

我想提供另一种可能的解决方案。但我需要提醒一下,它绝对不是#34;码头工作方式"做事并依赖于卷的存在(这可能是Docker Swarm和Kubernetes等工具的潜在阻碍者)

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

在你的情况下,你会使/opt/app成为Docker卷。您不需要将Volume明确映射到主机文件系统上的某个位置,因为我将在下面进行描述,映射可以动态获取。

因此对于初学者来说,完全保留Dockerfile并将容器创建命令切换为:

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

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

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

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}

使用这种方法可以获得的好处是:

  • 没有可能成本高昂的无缓存图片重建
  • 无需将特定于应用程序的运行信息移动到run命令中。 Dockerfile是检测应用程序所需的唯一来源

<强>更新

您可以使用docker cp(启动Docker 1.8)获得上面提到的相同结果。这样容器就不需要有卷,您可以像在主机文件系统上一样替换容器中的代码。

当然,正如我在回答的开头所提到的,这不是#34;码头工作方式&#34;做事,主张容器是不可改变的和可重复的。

答案 4 :(得分:0)

如果您使用GitHub,您可以使用GitHub API来缓存特定的RUN命令。

您需要安装jq来解析JSON: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