web-dev-qa-db-ja.com

GitからDockerコンテナーにコードを更新する方法

DjangoコードをコンテナにデプロイしようとしているDockerファイルがあります

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 [email protected]/{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コンテナーがビルドされると、コードを更新する方法を教えてください(注:ビルドを実行すると、キャッシュが原因でフェッチされません)。
  • この種のアプローチに最適なワークフローは何ですか?
29
Cheruiyot Felix

使用できるアプローチはいくつかあります。

  1. docker build --no-cacheを使用すると、Gitクローンのキャッシュの使用を回避できます。
  2. 起動コマンドはgit pullを呼び出します。したがって、python manage.pyを実行する代わりに、CMD cd /repo && git pull && python manage.pyのようなものを使用するか、より複雑な場合は開始スクリプトを使用します。

私は2を好む傾向があります。また、コンテナー内のコードを更新するためにcronジョブを実行することもできますが、それはもう少し作業であり、Dockerの哲学に多少反します。

21
seanmcl

ホスト上のコードをチェックアウトし、COPYをイメージに組み込むことをお勧めします。これにより、変更を加えるたびに更新されます。また、開発中は、コンテナのコー​​ドディレクトリにソースディレクトリをバインドマウントすることができます。つまり、変更はコンテナにすぐに反映されます。

ただし、最後の更新をチェックするgitリポジトリのdockerコマンドは非常に便利です。

10
Adrian Mouat

別のソリューション。

Docker buildコマンドは、命令文字列がキャッシュされたイメージのものとまったく同じである限り、キャッシュを使用します。だから、あなたが書くなら

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

次の更新では、次のように変更します。

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

これにより、Dockerがキャッシュを使用できなくなります。

6
takaomag

私は別の可能な解決策を提供したいと思います。ただし、これは明らかに「ドッカーの方法」ではなく、ボリュームの存在に依存していることを警告する必要があります(これは、Docker SwarmやKubernetesなどのツールの潜在的なブロッカーになる可能性があります)。

私たちが利用する基本的な原則は、Dockerボリュームとして使用されるコンテナーディレクトリの内容が実際にはホストのファイルシステムに格納されるという事実です。チェックアウト this ドキュメントの一部。

あなたの場合、あなたは/opt/app Dockerボリューム。以下で説明するように、マッピングは動的に取得できるため、ボリュームをホストのファイルシステム上の場所に明示的にマッピングする必要はありません。

そのため、まず、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 [email protected]/{user}/{repo}

このようなアプローチで得られる利点は次のとおりです。

  • コストがかかる可能性のあるキャッシュレスイメージの再構築はありません
  • アプリケーション固有の実行情報をrunコマンドに移動する必要はありません。 Dockerfileは、アプリケーションのインスツルメンテーションに必要な唯一のソースです

[〜#〜]更新[〜#〜]

docker cp (Docker 1.8以降)を使用すると、上記と同じ結果を得ることができます。この方法では、コンテナーにボリュームが必要なく、ホストファイルシステムで行うようにコンテナー内のコードを置き換えることができます。

もちろん、回答の冒頭で述べたように、これは、コンテナを不変で再現性のあるものにすることを主張する、「ドッキング方法」ではありません。

2
geoand

GitHubを使用する場合、GitHub APIを使用して特定のRUNコマンドをキャッシュしないようにすることができます。

JSONを解析するには、jqをインストールする必要があります: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が実行されます。

0