ファイルの変更時にDockerコンテナを再構築する


93

ASP.NET Coreアプリケーションを実行するために、アプリケーションをビルドし、Jenkinsを使用してGitによってフェッチされたソースコードをコンテナーにコピーするdockerfileを生成しました。したがって、私のワークスペースでは、dockerfileで次のことを行います。

WORKDIR /app
COPY src src

JenkinsはGitを使用してホスト上のファイルを正しく更新しますが、Dockerはこれをイメージに適用しません。

構築するための私の基本的なスクリプト:

#!/bin/bash
imageName=xx:my-image
containerName=my-container

docker build -t $imageName -f Dockerfile  .

containerRunning=$(docker inspect --format="{{ .State.Running }}" $containerName 2> /dev/null)

if [ "$containerRunning" == "true" ]; then
        docker stop $containerName
        docker start $containerName
else
        docker run -d -p 5000:5000 --name $containerName $imageName
fi

新しいコンテナをビルドする前に、コンテナのパラメータや停止/削除など--rm、さまざまなことを試しました。ここで何が間違っているのかわかりません。dockerはイメージを正しく更新しているようです。これを呼び出すと、レイヤーIDが生成され、キャッシュ呼び出しは行われません。--no-cachedocker runCOPY src src

Step 6 : COPY src src
 ---> 382ef210d8fd

コンテナを更新するための推奨される方法は何ですか?

私の典型的なシナリオは次のとおりです。アプリケーションはサーバー上のDockerコンテナーで実行されています。これで、ファイルを変更するなどして、アプリの一部が更新されます。これで、コンテナは新しいバージョンを実行するはずです。Dockerは、既存のコンテナーを変更するのではなく、新しいイメージをビルドすることを推奨しているようです。そのため、私のように再構築する一般的な方法は正しいと思いますが、実装の詳細を改善する必要があります。


ビルドコマンドや各コマンドからの出力全体など、コンテナをビルドするために実行した正確な手順をリストできますか?
BMitch 2016

回答:


140

いくつかの調査とテストの結果、Dockerコンテナの存続期間について誤解があることがわかりました。コンテナを再起動するだけでは、その間にイメージが再構築されたときに、Dockerが新しいイメージを使用することはありません。代わりに、Dockerはコンテナを作成する前にのみイメージをフェッチしています。したがって、コンテナを実行した後の状態は永続的です。

削除が必要な理由

したがって、再構築して再起動するだけでは不十分です。コンテナはサービスのように機能すると思いました。サービスを停止し、変更を加え、再起動すると、適用されます。それが私の最大の間違いでした。

コンテナは永続的であるため、docker rm <ContainerName>最初にを使用して削除する必要があります。コンテナが削除された後は、単純にで開始することはできませんdocker start。これはdocker run、を使用して実行する必要があります。これ自体は、新しいコンテナインスタンスを作成するために最新のイメージを使用します。

コンテナは可能な限り独立している必要があります

この知識があれば、データをコンテナに保存することが悪い習慣と見なされる理由が理解でき、Dockerは代わりにデータボリューム/ホストディレクトリのマウントを推奨します。アプリケーションを更新するにはコンテナを破棄する必要があるため、内部に保存されているデータも失われます。これにより、サービスのシャットダウン、データのバックアップなどに余分な作業が発生します。

したがって、これらのデータをコンテナから完全に除外するのは賢明なソリューションです。データがホストに安全に保存され、コンテナがアプリケーション自体のみを保持している場合、データについて心配する必要はありません。

なぜ-rf本当にあなたを助けないかもしれません

docker runこのコマンドは、持っているクリーンアップと呼ばれるスイッチを-rf。Dockerコンテナを永続的に保持する動作を停止します。を使用すると-rf、Dockerはコンテナが終了した後にコンテナを破棄します。しかし、このスイッチには2つの問題があります。

  1. Dockerは、コンテナーに関連付けられた名前のないボリュームも削除します。これにより、データが強制終了される可能性があります
  2. このオプションを使用すると、-dswitchを使用してバックグラウンドでコンテナを実行することはできません

一方で-rf、スイッチが簡単なテストのために開発中の作業を保存するには良い選択肢である、それは生産にはあまり適しています。特に、コンテナをバックグラウンドで実行するオプションがないため、ほとんどの場合必要になります。

コンテナを削除する方法

コンテナを削除するだけで、これらの制限を回避できます。

docker rm --force <ContainerName>

--force(または-f)コンテナを実行するにSIGKILLを使用するスイッチ。代わりに、次の前にコンテナを停止することもできます。

docker stop <ContainerName>
docker rm <ContainerName>

どちらも同じです。SIGTERMdocker stopも使用しています。ただし、switchを使用すると、特にCIサーバーを使用している場合にスクリプトが短くなります。コンテナーが実行されていない場合はエラーがスローされます。これにより、Jenkinsや他の多くのCIサーバーは、ビルドが失敗したと誤って見なします。これを修正するには、最初に、質問で行ったようにコンテナーが実行されているかどうかを確認する必要があります(変数を参照)。--forcedocker stopcontainerRunning

Dockerコンテナを再構築するための完全なスクリプト

この新しい知識に従って、私は次の方法でスクリプトを修正しました。

#!/bin/bash
imageName=xx:my-image
containerName=my-container

docker build -t $imageName -f Dockerfile  .

echo Delete old container...
docker rm -f $containerName

echo Run new container...
docker run -d -p 5000:5000 --name $containerName $imageName

これは完璧に機能します:)


4
「Dockerコンテナの存続期間について誤解があったことがわかりました」あなたは私の口から言葉を取り出しました。細かくご説明いただきありがとうございます。Dockerの初心者にはこれをお勧めします。これにより、VMとコンテナの違いが明確になります。
Vince Banzon 2018年

2
あなたの説明の後、私がしたことは、私が既存のイメージにしたことをメモすることです。変更を保持するために、新しいDockerfileを作成して、追加したい変更が既に含まれている新しいイメージを作成しました。そうすることで、作成された新しいイメージが(ある程度)更新されます。
Vince Banzon 2018年

--force-recreatedocker composeのオプションは、ここで説明するものと似ていますか?もしそうなら、代わりにこのソリューションを使用する価値はありません(その質問がばかげている場合は申し訳ありませんが、私は
港湾労働者

2
@cglacetはい、似ていますが、直接比較することはできません。しかしdocker-compose、単純なdockerコマンドよりも賢いです。私は定期的に仕事をしていdocker-composeて、変化検出がうまく機能しているので、--force-recreateめったに使用しません。ちょうどはdocker-compose up --buildカスタムイメージ(構築している場合に重要であるbuild代わりに、例えばドッカーハブから画像を使用してのコンファイル内のディレクティブを)。
ライオン

35

dockerfile、compose、requirementsに変更が加えられた場合は、を使用して再実行してくださいdocker-compose up --build。イメージが再構築されて更新されるように


1
MySQL Dockerコンテナを1つのサービスとして使用している場合、ボリュームを使用した場合、その後DBは空になります/opt/mysql/data:/var/lib/mysqlか?
マルティン・トマ

私には--build、ローカル開発環境で常に使用することにマイナス面はないように思われます。Dockerがファイルを再コピーする速度は、他の方法ではコピーする必要がないと想定される場合があり、数ミリ秒しかかからず、WTFの時間を大幅に節約します。
ダナック

1

docker-composeファイルでサービス名をどのように呼び出したかと一致する必要がある場所で実行することbuildにより、特定のサービスに対して実行docker-compose up --build <service name>できます。

docker-composeファイルに多くのサービス(.netアプリ-データベース-暗号化しましょう...など)が含まれていてapplication、docker-composeファイルのように名前が付けられた.netアプリのみを更新するとします。その後、単に実行することができますdocker-compose up --build application

追加のパラメーター-dバックグラウンドで実行 する場合など、コマンドに追加のパラメーターを追加する場合、パラメーターはサービス名の前にある必要があります。 docker-compose up --build -d application

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.