ASP.NET Coreアプリケーションを実行するために、アプリケーションをビルドし、コンテナ内のソースコードをコピーするdockerfileを生成しました。これは、Jenkinsを使用してGitによって取得されます。したがって、私のワークスペースでは、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
の--no-cache
およびdocker run
パラメーターなどのさまざまなことを試してみました。また、コンテナーを停止/削除しますbefore新しいものがビルドされます。ここで何が間違っているのかわかりません。 COPY src src
を呼び出すとレイヤーIDが発生し、キャッシュは呼び出されないため、dockerはイメージを正しく更新しているようです。
Step 6 : COPY src src
---> 382ef210d8fd
コンテナを更新する推奨方法は何ですか?
私の典型的なシナリオは次のとおりです。アプリケーションはサーバー上でDockerコンテナーで実行されています。これで、アプリの一部が更新されました。ファイルを変更します。これで、コンテナは新しいバージョンを実行するはずです。 Dockerは、既存のコンテナーを変更するのではなく、新しいイメージを構築することを推奨しているようです。そのため、私のように再構築する一般的な方法は正しいと思いますが、実装の詳細を改善する必要があります。
いくつかの調査とテストを行った結果、Dockerコンテナの寿命について誤解していることがわかりました。コンテナを再起動するだけでは、その間にイメージが再構築されたときに、Dockerが新しいイメージを使用することはありません。代わりに、Dockerはコンテナーを実行する前にイメージのみをフェッチしています。したがって、コンテナを実行した後の状態は永続的です。
したがって、再構築と再起動だけでは不十分です。コンテナはサービスのように機能すると考えました。サービスを停止し、変更を加え、再起動すると適用されます。それが私の最大の間違いでした。
コンテナは永続的であるため、最初にdocker rm <ContainerName>
を使用してコンテナを削除する必要があります。コンテナが削除された後、docker start
で単純に起動することはできません。これは、docker run
を使用して実行する必要があります。_SOMECODE自体は、新しいコンテナインスタンスを作成するために最新のイメージを使用します。
この知識があれば、なぜコンテナにデータを保存するのが 悪い習慣として認定 であり、代わりにDockerが データボリューム/ホストディレクトリのマウント を推奨するのかを理解できます:コンテナを更新するには破棄する必要があるためアプリケーションでは、内部に保存されたデータも失われます。これにより、サービスのシャットダウン、データのバックアップなどに余分な作業が発生します。
したがって、これらのデータをコンテナから完全に除外するのは賢明なソリューションです。ホストに安全に保存され、コンテナがアプリケーション自体のみを保持している場合、データを心配する必要はありません。
-rf
が本当に役に立たない理由docker run
コマンドには、-rf
と呼ばれるClean upスイッチがあります。 Dockerコンテナを永続的に保持する動作を停止します。 -rf
を使用すると、Dockerは終了後にコンテナを破棄します。ただし、このスイッチには2つの問題があります。
-d
スイッチを使用してバックグラウンドでコンテナーを実行することはできません-rf
スイッチは、クイックテストのために開発中の作業を節約するのに適したオプションですが、実稼働環境ではあまり適していません。特に、バックグラウンドでコンテナを実行するオプションがないため、ほとんどの場合これが必要になります。
コンテナを削除するだけで、これらの制限を回避できます。
docker rm --force <ContainerName>
実行中のコンテナでSIGKILLを使用する--force
(または-f
)スイッチ。代わりに、次の前にコンテナを停止することもできます。
docker stop <ContainerName>
docker rm <ContainerName>
両方とも同等です。 docker stop
も SIGTERM を使用しています。ただし、--force
スイッチを使用すると、特にCIサーバーを使用する場合、スクリプトが短縮されます。コンテナが実行されていない場合、docker stop
はエラーをスローします。これにより、Jenkinsおよび他の多くのCIサーバーは、ビルドが失敗したと誤って判断します。これを修正するには、質問で行ったようにコンテナが実行されているかどうかを最初に確認する必要があります(containerRunning
変数を参照)。
この新しい知識によると、スクリプトを次のように修正しました。
#!/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
これは完璧に動作します:)
Dockerfile、compose、requirementsに変更が加えられるたびに、docker-compose up --build
を使用して再実行します。画像が再構築および更新されるように