web-dev-qa-db-ja.com

CapistranoをDockerと統合してデプロイするにはどうすればよいですか?

混合すべきでないツール(CapistranoとDocker)を混合しようとする可能性があるため、質問が関連しているかどうかはわかりません。

私は最近、Capistranoでデプロイされるアプリケーションをドッキングしました。 Docker composeは、開発環境とステージング環境の両方で使用されます。

これは私のプロジェクトのようです(アプリケーションファイルは表示されていません)。

Capfile
docker-compose.yml
docker-compose.staging.yml
config/
    deploy.rb
    deploy
        staging.rb

Docker Composeファイルは、開発環境またはステージング環境でアプリを実行するために必要なすべてのコンテナー(Nginx、PHP、MongoDB、Elasticsearchなど)を作成します(したがって、docker-compose.staging.ymlで定義されているいくつかの特定のパラメーター)。

アプリは、次のコマンドでステージング環境にデプロイされます。

cap staging deploy

サーバー上のフォルダーアーキテクチャは、カピストラーノの1つです。

current
releases
    20160912150720
    20160912151003
    20160912153905
shared

次のコマンドは、ステージングサーバーのcurrentディレクトリで実行され、アプリの実行に必要なすべてのコンテナーをインスタンス化しています。

docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d

ここまでは順調ですね。次のデプロイでは状況がさらに複雑になります。current symlinkはreleasesディレクトリの新しいディレクトリをポイントします。

  • deploy.rbがコンテナー内で実行する必要があるコマンドを定義している場合(PHPのdocker-compose exec php composer installなど)、Dockerはコンテナーがまだ存在しないことを通知します(既存のコンテナーは以前のリリースフォルダーで作成されたため)。
  • Capistranoデプロイメントプロセスでdocker-compose up -dコマンドを実行すると、ポートの競合が原因でいくつかのエラーが発生します(以前のコンテナーはまだ存在しています)。

この問題を解決する方法についてのアイデアはありますか?カピストラーノから離れて何か違うことをすべきでしょうか?

アイデアは、Capistranoが提供する(ほぼ)ダウンタイムゼロのデプロイメントをDockerコンテナーの柔軟性で維持することです(たとえば、同じサーバー上のさまざまなアプリにいくつかのPHPバージョンを提供))。

21
Michaël Perrin

私が理解している限り、アプリケーションスタック全体を再デプロイするために、ホストでcapistranoを使用しています。つまり、コンテナーです。つまり、カピストラーノを使用して、ビルド、コンテナーの作成、そしてデプロイメントを調整しています。

あなたがそうする間、基本的に、cap deployを実行するとき

  • アプリをビルドします(ホストでプルした現在のベースに基づいて)-おそらくgulp/grunt/buildタスクも含まれます
  • 次に、「ボリュームマウント」を使用してコンテナに「パッケージ」します
  • その間にあなたはコンテナを起動/交換します

これにより、「ほぼ」ゼロのダウンタイム展開を実現できます。

本当にダウンタイムに気を配り、導入プロセスをそれほど形式化することに関心がある場合は、適切なパイプライン実装を使用して正しく実行する必要があります。

  • 包装/ ci
  • 展開/配布

Capistranoは、この戦略で使用できるツールの1つになることができる/すべきではないと思います。 Capistranoは、トランスポートとしてsshとgitを使用してサーバーに直接アプリケーションをデプロイするためのものです。 capを使用してターゲットサーバー上にイメージ全体を構築し、それらをコンテナーとして開始することは、実際には私見です。

梱包/建物

Jenkins/bamboo/gocdのようなCI/CDサーバーを使用して、アプリケーションのリリースイメージをビルドします。アプリのみが「リリース」に関してカスタマイズされていると仮定すると、コンテナーとサービスとしてdbとアプリがあるとすると、アプリにはソースコードが含まれ、リリース中に定期的に変更されます。

したがって、CIサーバー上に新しいアプリイメージ(リリース)オフサイトを構築するためのCD/CIプロセスです。 COPYを使用してアプリケーションのソースコードをプルし、イメージにパッケージ化してから、RUNステートメントを使用してアセットをコンパイルします(npm/gulp/grunt何でも)。これはすべて本番サーバーではなく、CI/CDエージェントで行われます。

次に、このリリースイメージをプッシュし、このイメージを呼び出しますyourregistry.com/yourapp into your private registry as a new 'version' for deployment。

配備

ダウンタイムあり(簡単)

ダウンタイムを使用して本番サーバーまたはステージングサーバーにデプロイするには、単にdocker-composer stop && docker-composer up-これにより、新しいイメージが自動的にプルされ、スタックで開始されます-アプリがアップグレードされます

もちろん、サーバーはプライベートリポジトリからプルできる必要があります。

ダウンタイムなし(より多くの努力)

ダウンタイムなしのデプロイメントを実現するには、 blue-greenデプロイメントの概念 を使用する必要があります。したがって、設定にプロキシを追加し、アプリからパブリックポートを公開せず、このプロキシパブリックポートを使用します。現在のライブシステムがランダムなポート21231で実行されている可能性があります。プロキシは443から21231に転送しています。

私たちはランダムなポートを使用して、「2番目の」システムの展開中の競合を回避し、あなたが言及した問題の1つをカバーしています。

再デプロイするときは、(古いものに加えて)新しいapp-imageに基づいて「新しい」コンテナのみを開始し、新しいランダムポート12312を取得します-必要に応じて、統合テストを直接12312に再度実行します(しないでください)プロキシを使用してください)。完了したら、プロキシを再構成して12312に転送し、古いコンテナ(21231)を削除します。

詳細がこの質問の範囲外であるプロキシ再構成を自動化する場合は、service-discoveryと、ランダムなポートの方がはるかに実用的であり、プロキシの再構成を簡単にします。実行中にnginx/haproxyにします。ツールは、例えばでしょう。

19
Eugen Mayer

カピストラーノは仕事に適したツールではないと思います。これは最近、Capistranoの基礎となるSSHKitのPRで議論されました。

https://github.com/capistrano/sshkit/pull/368

@EugenMayerは、Dockerを使用する「通常の」方法を説明するより優れた仕事をします。

4
will_in_wi