简体   繁体   English

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

[英]How to update code from Git to a Docker container

I have a Docker file trying to deploy Django code to a container 我有一个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

And then I build my code as docker build -t dockerhubaccount/demo:v1 . 然后我将我的代码docker build -t dockerhubaccount/demo:v1 . , and this pulls my code from Bitbucket to the container. ,这将我的代码从Bitbucket拉到容器中。 I run it as docker run -p 8000:8080 -td felixcheruiyot/demo:v1 and things appear to work fine. 我运行它作为docker run -p 8000:8080 -td felixcheruiyot/demo:v1 ,事情似乎工作正常。

Now I want to update the code ie since I used git clone ... , I have this confusion: 现在我想更新代码,即因为我使用git clone ... ,我有这样的困惑:

  • How can I update my code when I have new commits and upon Docker containers build it ships with the new code (note: when I run build it does not fetch it because of cache). 当我有新的提交时,如何更新我的代码,并且在Docker容器构建它时附带新代码(注意:当我运行构建时,它不会因为缓存而获取它)。
  • What is the best workflow for this kind of approach? 这种方法的最佳工作流程是什么?

There are a couple of approaches you can use. 您可以使用几种方法。

  1. You can use docker build --no-cache to avoid using the cache of the Git clone. 您可以使用docker build --no-cache来避免使用Git克隆的缓存。
  2. The startup command calls git pull . 启动命令调用git pull So instead of running python manage.py , you'd have something like CMD cd /repo && git pull && python manage.py or use a start script if things are more complex. 因此,不是运行python manage.py ,而是使用CMD cd /repo && git pull && python manage.py或者如果事情更复杂则使用启动脚本。

I tend to prefer 2. You can also run a cron job to update the code in your container, but that's a little more work and goes somewhat against the Docker philosophy. 我倾向于选择2.你也可以运行一个cron作业来更新你容器中的代码,但这样做的工作要多一些,并且有点违背了Docker的理念。

I would recommend you checkout out the code on your host and COPY it into the image. 我建议您检查主机上的代码并将其COPY到图像中。 That way it will be updated whenever you make a change. 这样,无论何时进行更改,它都会更新。 Also, during development you can bind mount the source directory over the code directory in the container, meaning any changes are reflected immediately in the container. 此外,在开发期间,您可以将源目录绑定到容器中的代码目录,这意味着任何更改都会立即反映在容器中。

A docker command for git repositories that checks for the last update would be very useful though! 检查上次更新的git存储库的docker命令虽然非常有用!

Another solution. 另一种方法。

Docker build command uses cache as long as a instruction string is exactly same as the one of cached image. 只要指令字符串与缓存图像完全相同,Docker构建命令就会使用缓存。 So, if you write 所以,如果你写

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

On next update, you change as follows. 在下次更新时,您将更改如下。

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

This can prevents docker from using cache. 这可以防止docker使用缓存。

I would like to offer another possible solution. 我想提供另一种可能的解决方案。 I need to warn however that it's definitely not the "docker way" of doing things and relies on the existence of volumes (which could be a potential blocker in tools like Docker Swarm and Kubernetes) 我需要提醒一下,它肯定不是处理器的“对接方式”,而是依赖于卷的存在(这可能是Docker Swarm和Kubernetes等工具的潜在阻碍)

The basic principle that we will be taking advantage of is the fact that the contents of container directories that are used as Docker Volumes, are actually stored in the file system of the host. 我们将利用的基本原则是,用作Docker Volumes的容器目录的内容实际上存储在主机的文件系统中。 Check out this part of the documentation. 查看文档的这一部分。

In your case you would make /opt/app a Docker Volume. 在您的情况下,您将使用/opt/app Docker Volume。 You don't need to map the Volume explicitly to a location on the host's file-system since as a I will describe below, the mapping can be obtained dynamically. 您不需要将Volume显式映射到主机文件系统上的某个位置,因为我将在下面介绍,可以动态获取映射。

So for starters leave your Dockerfile exactly as it is and switch your container creation command to something like: 因此,对于初学者来说,完全保留Dockerfile,并将容器创建命令切换为:

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

The command docker inspect -f {{index .Volumes "/opt/webapp"}} some-name will print the full file system path on the host where your code is stored ( this is where I picked up the inspect trick). 命令docker inspect -f {{index .Volumes "/opt/webapp"}} some-name将在存储代码的主机上打印完整的文件系统路径( 是我选择检查技巧的地方)。

Armed with that knowledge all you have to do is replace that code and your all set. 有了这些知识,你所需要做的就是替换那些代码和你的所有代码。 So a very simple deploy script would be something like: 所以一个非常简单的部署脚本将是这样的:

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}

The benefits you get with an approach like this are: 使用这种方法可以获得的好处是:

  • There are no potentially costly cacheless image rebuilds 没有潜在的昂贵的无缓存图像重建
  • There is no need to move application specific running information into the run command. 无需将特定于应用程序的运行信息移动到run命令中。 The Dockerfile is the only source of needed for instrumenting the application Dockerfile是检测应用程序所需的唯一来源

UPDATE UPDATE

You can achieve the same results I have mentioned above using docker cp (starting Docker 1.8). 您可以使用docker cp (启动Docker 1.8)获得上面提到的相同结果。 This way the container need not have volumes, and you can replace code in the container as you would on the host file-system. 这样容器不需要有卷,您可以像在主机文件系统上一样替换容器中的代码。

Of course as I mentioned in the beginning of the answer, this is not the "docker way" of doing things, which advocates containers being immutable and reproducible. 当然,正如我在回答的开头所提到的,这不是做事的“对接方式”,它主张容器是不可变的和可重复的。

If you use GitHub you can use the GitHub API to not cache specific RUN commands. 如果使用GitHub,则可以使用GitHub API来缓存特定的RUN命令。

You need to have jq installed to parse JSON: apt-get install -y jq 你需要安装jq来解析JSON: apt-get install -y jq

Example: 例:

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

In Dockerfile (ARG command should be right before RUN): 在Dockerfile中(ARG命令应该在RUN之前):

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

Or if you don't want to install jq: 或者如果您不想安装jq:

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

If a repository has new commits, git clone will be executed. 如果存储库有新的提交,则将执行git clone

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM