GNU/Linux >> Linux の 問題 >  >> Linux

ダウンタイムがゼロまたは最小のDockerコンテナの更新

コンテナでサービスを実行していて、Dockerイメージから利用できるサービスの新しいバージョンがあるとします。このような場合、Dockerコンテナを更新します。

Dockerコンテナーの更新は問題ではありませんが、ダウンタイムなしでDockerコンテナーを更新することは困難です。

混乱している?両方の方法を1つずつ紹介します。

方法1:Dockerコンテナーを最新のイメージに更新する(ダウンタイムが発生する)

この方法は、基本的に次の手順で構成されています。

  • 最新のDockerイメージをプルします
  • 古いDockerイメージを実行しているコンテナを停止して削除します
  • 新しくプルされたDockerイメージを使用して新しいコンテナを作成します

コマンドが欲しいですか?どうぞ。

Dockerイメージを一覧表示し、更新されたDockerイメージを取得します。 docker pullコマンドを使用してこのイメージの最新の変更を取得します:

docker pull image_name

次に、古いDockerイメージを実行しているコンテナのコンテナIDまたは名前を取得します。この目的には、dockerpsコマンドを使用します。このコンテナを停止します:

docker stop container_ID

そして、コンテナを削除します:

docker rm container_id

次のステップは、前のコンテナーの実行に使用したのと同じパラメーターを使用して新しいコンテナーを実行することです。そもそもパラメータを作成したので、これらのパラメータが何であるかを知っていると思います。

docker run --name=container_name [options] docker_image

このアプローチに問題がありますか?実行中のコンテナを停止してから、新しいコンテナを作成する必要があります。これにより、実行中のサービスのダウンタイムが発生します。

ダウンタイムは、たとえ1分間であっても、ミッションクリティカルなプロジェクトやトラフィックの多いWebサービスの場合、大きな影響を与える可能性があります。

この問題に対するより安全でより良いアプローチを知りたいですか?次のセクションを読んでください。

方法2:リバースプロキシ設定でDockerコンテナを更新する(ゼロまたは最小のダウンタイム)

簡単な解決策を探していた場合は、失望させて申し訳ありませんが、Docker Composeを使用してリバースプロキシアーキテクチャでコンテナをデプロイする必要があるため、解決策にはなりません。

Dockerコンテナーを使用して重要なサービスを管理する場合は、リバースプロキシ方式が長期的には非常に役立ちます。

リバースプロキシ設定の主な利点を3つ挙げてみましょう。

  • 同じサーバーに複数の公開サービスを展開できます。ここではポートブロッキングはありません。
  • Let's Encryptサーバーは、すべてのサービス、すべてのコンテナーのSSL展開を処理します。
  • 実行中のサービスに影響を与えることなくコンテナを更新できます(ほとんどのWebサービスの場合)。

詳細について知りたい場合は、リバースプロキシの一般的な使用法とロードバランサーとの比較を強調した公式のNginx用語集を確認できます。

同じサーバー上のコンテナーで実行されているWebサービスの複数のインスタンスをホストするようにNginxリバースプロキシを設定するための非常に詳細なチュートリアルがあります。それで、ここでそれについて再び議論するつもりはありません。最初に、このアーキテクチャを使用してコンテナをセットアップする必要があります。私を信じてください、これは問題の価値があります。

このチュートリアルでは、日々のDevOpsアクティビティで非常に役立つステップバイステップの方法論を設計しました。この要件は、コンテナを更新する場合だけでなく、実行中のアプリのいずれかに非常に必要な変更を加え、貴重な稼働時間を犠牲にする場合にも必要になります。

これ以降は、リバースプロキシ設定でWebアプリケーションを実行していることを前提としています。これにより、構成が変更された後、新しい最新のコンテナーに対して再ルーティングが期待どおりに機能するようになります。

最初にこの方法の手順を示し、次に実際の例を示します。

ステップ1:ドッカー作成ファイルを更新する

まず、既存のdockercomposeファイルを最新の画像のバージョン番号で編集する必要があります。 Docker Hub、特にアプリケーションの「タグ」セクションで表示できます。

アプリケーションディレクトリに移動し、コマンドラインテキストエディタを使用してdocker-composeファイルを編集します。ここではNanoを使用しました。

[email protected]:~/web-app$ nano docker-compose.yml

サービス内: image:web-app:x.x.xを更新します 最新のバージョン番号を使用してファイルを保存します。

バージョン番号を手動で指定する代わりに、とにかく最新のタグを使用しないのはなぜだろうと思うかもしれません。コンテナを更新しているときに、ドッキングされたアプリケーションの最新バージョンを実際に取得する際に、最新のタグが断続的に遅延する可能性があることに気付いたので、意図的に行いました。バージョン番号を直接使用すると、いつでも絶対に使用できます。確かに。

ステップ2:新しいコンテナをスケールアップする

次のコマンドを使用すると、dockercomposeファイルで行われた新しい変更に基づいて新しいコンテナが作成されます。

[email protected]:~/web-app$ docker-compose up -d --scale web-app=2 --no-recreate

前のコンテナはまだ稼働中であることに注意してください。 -scale フラグは、指定された追加のコンテナーを作成するために使用されます。ここでは、 web-app Webアプリケーションのサービス名として設定されています。

2つのコンテナへのスケールアップを指定した場合でも、-no-recreate 古いコンテナがすでに実行されているため、1つだけ追加されます。

-scaleの詳細については および--no-recreate フラグを立てて、公式のドッカーを確認してください-ドキュメントページを作成してください。

ステップ3:古いコンテナを削除します

手順2の後、新しい変更が有効になるまで15〜20秒ほど待ってから、古いコンテナを削除します。

[email protected]:~/web-app$ docker rm -f old-web-app

異なるWebアプリでは、上記のコマンドを実行した後、反映される変更の動作が異なります(このチュートリアルの一番下にボーナスのヒントとして説明されています)。

ステップ4:以前と同じように単一コンテナのセットアップにスケールダウンします

最後のステップとして、もう一度単一コンテナのセットアップにスケールダウンします。

[email protected]:〜/ web-app $ docker-compose up -d --scale web-app =1 --no-recreate

私はこのメソッドをGhost、WordPress、Rocket.Chat、Nextcloudインスタンスでテストしました。 Nextcloudが数秒間メンテナンスモードに切り替わる以外は、この手順は他の3つでも非常にうまく機能します。

ただし、談話は別の話であり、この場合、ハイブリッドモデルのため、非常にトリッキーな例外になる可能性があります。

重要なのは、Webアプリがドッキングするときに標準のDockerプラクティスを使用するほど、すべてのWebアプリコンテナーを日常的に管理するのが便利になるということです。

実際の例:ダウンタイムなしでライブGhostインスタンスを更新する

約束通り、実例をお見せします。 Dockerコンテナで実行されているGhostをダウンタイムなしで新しいバージョンに更新する方法を紹介します。

GhostはCMSであり、Linuxハンドブックに使用しています。ここに示す例は、このWebサイトを実行しているGhostインスタンスを更新するために使用するものです。

たとえば、 / home / avimanyu / ghostにある古いバージョンに基づく既存の構成があります。 :

version: '3.5'
services:
  ghost:
    image: ghost:3.36
    volumes:
      - ghost:/var/lib/ghost/content
    environment:
      - VIRTUAL_HOST=blog.domain.com
      - LETSENCRYPT_HOST=blog.domain.com
      - url=https://blog.domain.com
      - NODE_ENV=production
    restart: always
    networks:
      - net

volumes:
  ghost:
    external: true

networks:
  net:
    external: true

上記のdockercompose構成は、ここで説明する既存のNginx docker構成に基づいており、 netという名前のネットワークで実行されていることに注意してください。 。そのdockerボリュームもdockervolume create ghost-blogを使用して手動で作成されていました 。

docker psで確認すると :

CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
2df6c27c1fe3        ghost:3.36                             "docker-entrypoint.s…"   9 days ago          Up 7 days           2368/tcp                                   ghost_ghost-blog_1
89a5a7fdcfa4        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   9 days ago          Up 7 days                                                      letsencrypt-helper
90b72e217516        jwilder/nginx-proxy                      "/app/docker-entrypo…"   9 days ago          Up 7 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse-proxy

この記事の執筆時点では、これはGhostの古いバージョンです。それを最新バージョン3.37.1に更新する時が来ました!そこで、画像セクションで次のように修正します。

version: '3.5'
services:
  ghost-blog:
    image: ghost:3.37.1
    volumes:
      - ghost-blog:/var/lib/ghost/content
    environment:
      - VIRTUAL_HOST=blog.domain.com
      - LETSENCRYPT_HOST=blog.domain.com
      - url=https://blog.domain.com
      - NODE_ENV=production
    restart: always
    networks:
      - net

volumes:
  ghost-blog:
    external: true

networks:
  net:
    external: true

次に、スケーリング方法を有効に活用します。

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=2 --no-recreate

上記のコマンドを使用すると、古いコンテナは影響を受けませんが、新しいコンテナは同じ構成で参加しますが、Ghostの最新バージョンに基づいています:

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=2 --no-recreate
Pulling ghost (ghost:3.37.1)...
3.37.1: Pulling from library/ghost
bb79b6b2107f: Already exists
99ce436c3449: Already exists
f7bdc31da5f5: Already exists
7a1300b9ff59: Already exists
a495c68fa838: Already exists
6e362a39ec35: Already exists
b68b4f3c36f7: Already exists
41f8b02d4a71: Pull complete
3ecc736ea4e5: Pull complete
Digest: sha256:595c759980cd22e99037811397012908d89efb799776db222a4be6d4d892917c
Status: Downloaded newer image for ghost:3.37.1
Starting ghost_ghost-blog_1 ... done
Creating ghost_ghost-blog_2 ... done

docker-compose up -dを使用した従来のアプローチを使用していましたか 代わりに、Ghostの最新のイメージに基づいた既存のコンテナーの再作成を回避することはできなかったでしょう。

レクリエーションには、古いコンテナを削除し、同じ設定でその場所に新しいコンテナを作成することが含まれます。これは、ダウンタイムが発生し、サイトにアクセスできなくなる場合です。

これが、-no-recreateを使用する必要がある理由です。 スケールアップ中にフラグを立てます。

これで、同じゴースト構成に基づいて2つのコンテナーが実行されました。これは、ダウンタイムを回避するための重要な部分です:

[email protected]:~/ghost$ docker ps
CONTAINER ID        IMAGE                                    COMMAND                  CREATED             STATUS              PORTS                                      NAMES
f239f677de54        ghost:3.37.1                               "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        2368/tcp                                   ghost_ghost-blog_2
2df6c27c1fe3        ghost:3.36                             "docker-entrypoint.s…"   9 days ago          Up 7 days           2368/tcp                                   ghost_ghost-blog_1
89a5a7fdcfa4        jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   9 days ago          Up 7 days                                                      letsencrypt-helper
90b72e217516        jwilder/nginx-proxy                      "/app/docker-entrypo…"   9 days ago          Up 7 days           0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   reverse-proxy

古いコンテナの名前はghost_ghost-blog_1であることに注意してください 。ドメイン名を確認すると、 blog.domain.comから引き続きアクセスできます。 。 blog.domain.com/ghostにあるGhost管理パネルを更新した場合 スケールアップした後、古いコンテナを削除するまで、それ自体をロードしようとし続けます:

[email protected]:~/ghost$ docker rm -f ghost_ghost-blog_1

しかし、Ghostブログ自体については、ダウンタイムはまったくありません。したがって、この方法で、Ghostブログを更新するときにダウンタイムをゼロにすることができます。

最後に、構成を元の設定にスケールダウンします。

[email protected]:~/ghost$ docker-compose up -d --scale ghost-blog=1 --no-recreate
Starting ghost_ghost-blog_2 ... done

前述のように、古いコンテナーを削除した後、変更はそれぞれのWebアプリに反映されますが、アプリの設計が多様であるため、明らかに動作が異なります。

ここにいくつかの観察があります:

WordPressについて :必ずdefine('AUTOMATIC_UPDATER_DISABLED'、true);を追加してください。 / var / www / htmlにあるファイルwp-config.phpの一番下の行として、ボリュームとして/ var / www/htmlの代わりに/var/ www / html/wp-contentをマウントします。詳しくはこちらをご覧ください。手順3の後、WordPress管理パネルにWordPressが最新であることが表示され、続行してデータベースを更新するように求められます。更新はWordPressサイトでダウンタイムなしで迅速に行われ、それだけです!

Rocket.Chatで Admin> Info には約15〜20秒かかる場合があります 手順3を実行する前でも、最新バージョンを実行していることを示すページ。ダウンタイムはもうありません!

Nextcloud上 :ステップ2の後、Nextcloudは数秒間メンテナンスモードに切り替わり、ファイルを再度ロードします。 管理>概要>セキュリティとセットアップの警告 、「Webサーバーが「./well-known/carddav」を解決するように適切に設定されていません。これは古いコンテナがまだ実行されているためです。手順3で削除すると、この警告が表示されます。 Nginxコンテナが最新バージョンに基づいて新しくスケーリングされたNextcloudコンテナを認識するまで、502の不正なゲートウェイエラーが表示される可能性があるため、NextcloudURLにアクセスする前に時間を取ってください。

ボーナスのヒント

この方法に従う際に留意すべきいくつかのヒントと事柄があります。

ヒント1

さまざまなアプリケーション間でダウンタイムを最小限に抑えるには、手順2で古いコンテナーを削除する前に、Nginxコンテナーが最終的にそれらを確認できるように、新しくスケーリングされた最新のコンテナーに十分な時間を与えるようにしてください。

上記の手順2に進む前に、手順1を実行した後、ブラウザでのアプリケーションの動作を確認することをお勧めします(ログイン後のページの更新、またはキャッシュのないプライベートブラウザウィンドウでの新しいページへのアクセスの両方として)。

アプリケーションごとに設計が異なるため、古いコンテナを停止する前に、この方法が非常に役立ちます。

ヒント2

これは、コンテナを実行するアプリの最新バージョンに更新するための非常に機知に富んだ方法ですが、同じ方法を使用して、ダウンタイムの問題に直面することなく、構成の変更や環境設定の変更を行うこともできます。

これは、問題のトラブルシューティングを行う必要がある場合、または稼働中のコンテナーで必要と思われる変更を実行する必要があるが、その間にダウンさせたくない場合に重要になる可能性があります。変更を加えて問題が修正されたことを確認したら、古いものを簡単に削除できます。

ライブコンテナの1つでログローテーションが有効になっていないことがわかったとき、私たちはこれに直面しました。これを有効にするために必要な変更を加え、同時にこの方法でダウンタイムを回避しました。

ヒント3

container_name を使用して、YMLファイルでコンテナーに具体的に名前を付けた場合 、このメソッドは、新しいコンテナ名の作成を伴うため、期待どおりに機能しません。

コンテナの命名タスクをDockerComposeに任せることで、この競合を回避できます(命名規則に従って自動的に実行されます)。 Docker Composeは、コンテナーに directory-name_service-name_1という名前を付けます。 。最後の数字は、コンテナが更新されるたびに増加します(docker-compose downを使用するまで)。

docker composeファイルでカスタムの名前付きコンテナーを使用してサービスを既に使用している場合、このメソッドを使用するには、 container_name を含む行(#プレフィックス付き)をコメントアウトするだけです。 サービス定義内。

このチュートリアルで説明されているように、ステップ1を使用して上記の新しいコンテナーを作成した後、ステップ2では、古いコンテナー(ダウンタイムを回避するために停止されなかった)の名前は、 container_name> (` docker psでも確認できます `古いコンテナを削除する前に)。

何か新しいことを学びましたか?

この記事は少し長いことは知っていますが、ドッキングされたWebアプリケーションを実行している本番サーバーのダウンタイムの問題をDevOpsコミュニティが管理するのに役立つことを願っています。ダウンタイムは個人レベルと商業レベルの両方で大きな影響を及ぼします。そのため、このトピックをカバーすることが絶対に必要でした。

ディスカッションに参加して、下のコメントセクションであなたの考え、フィードバック、提案を共有してください。


Linux
  1. UbuntuにDockerでWordPressをインストールする方法

  2. 7つの楽しいLinuxコンテナ/画像転送機能

  3. Dockerコンテナを一覧表示する方法

  1. Dockerイメージに基づいてデプロイされたコンテナーを更新する

  2. Docker がディレクトリの変更を更新しない

  3. 特権 Docker コンテナを使用したカーネル チューニング

  1. DockerコンテナにApacheを使用してModSecurityをインストールする

  2. LinodeにDockerを使用してnginxコンテナをデプロイする方法

  3. ダウンタイムなしでDockerコンテナを更新する方法