ホームページ >バックエンド開発 >PHPチュートリアル >Docker 上で PHP プロジェクトを実行するためのいくつかの調査
Docker の出現以降、コンテナ技術はインターネット分野で空前の人気を博しており、大企業であろうとスタートアップであろうと、基本的にはスタートアップ企業として、関連する技術についてさまざまな技術コミュニティやさまざまな講演会で学ぶことになります。私たちも例外ではありません。昨年 Docker について学び、今年の前にいくつかのソリューションをテストしました。今日は、そのプロセスについて学んだ学生にとって参考になることを願っています。もちろん、この分野で豊富な経験を持つ学生は、提案や指導を歓迎します。
この記事では、Docker の理論的な知識や基本的な概念については触れません。Docker の基本的な使い方を理解したい場合は、Docker の公式ドキュメントを参照することをお勧めします。ブログ 複数の記事: Docker 基本技術: Linux 名前空間 (その 1)、Docker 基本技術: Linux 名前空間 (その 2)、Docker 基本技術: Linux CGroup、Docker 基本技術: AUFS、Docker 基本技術: DeviceMapper。
私たちのプロジェクトで使用される標準 PHP テクノロジー スタック: PHP-FPM + Nginx、Alibaba Cloud の ECS 上で実行され、データベースも Alibaba Cloud サービスです。
一般的な貂蝉スタートアップ企業の貂蝉プロジェクトでは、理論上、あまり複雑な技術を使用する必要はなく、新しい技術を抑制することはプログラマーの職業倫理でもあります。しかし、私がこのプロジェクトに挑戦したのは、新しい技術を試したかったからではなく、前回の記事で述べたlaravelのパフォーマンスの問題やHHVMなど、プロジェクト立ち上げ以来さまざまな問題に遭遇したためです。または、PHP7 などの新しいテクノロジはパフォーマンスについて大きく言及しています。それらをすべて一度に切り替えるのは危険すぎるため、コンテナを使用して特定のサービスを実行してテストすることができます。別の例としては、以前にバグがあり、特定のインターフェイスにバグがあった場合があります。問題が発生して、システム全体の応答がタイムアウトになりました。別の例として、さまざまな技術カンファレンスで他の人が共有した経験を読んだ後、私も実際に試してみたくなりました (笑)。
Docker の哲学によれば、各コンテナは独立したサービスであり、サービスはインターフェイスを通じて相互に連携します。私たちが採用したソリューションは、PHP-FPM と Nginx が異なるコンテナーで実行され、PHP-FPM コンテナーがポートを Nginx コンテナーに公開するというものです。
コンテナ間のネットワーク通信は最初は Docker に付属のリンクを使用していましたが、リンクはコンテナの起動時に /etc/hosts ファイルを変更することで実装されます。発生した問題は、リンクされたコンテナーが再起動された後、コンテナー IP が変更されたが、リンクされたコンテナーが更新されていないことです (バージョン 1.10 ではリンク メカニズムが変更されました。この問題が解決されたかどうかはわかりませんが、まだ解決されていません)詳細はまだ見ていません)、もう 1 つの問題は、同じサービスが複数のコンテナーを開く必要がある場合の処理が難しいことです。したがって、クラスター内で実行する場合はさらに処理が難しくなります。ローカル開発中および運用環境でのみ再生できます。この最後の部分で使用される解決策は、サービス検出に consul を使用することです。ここでは consul については説明しません。興味のある方は、Consul と Registrator を使用した Docker コンテナーのサービス検出を参照してください。
その後、コードがホスト上に配置され、コンテナーの起動時にコードのディレクトリがマウントされます。インターフェースの使用シナリオに従って、インターフェースをいくつかの異なるコンテナーに分割して実行し、リソースの分離に関するストレス テストを実施しました。これは期待どおりであり、非常に満足しています。次に、2 つのコンテナを選択し、テストのために HHVM を実行しました。確かにパフォーマンスは大幅に向上しました。全体の構造は次の図に示されています。
これは通常どおりに使用できます。次に、ログの処理があります。最初は、ログを保存するためにホスト上のディレクトリがマウントされていましたが、これは整合していませんでした。 Docker の概念を取り入れたので、logstash コンテナーも作成し、さまざまなコンテナーのログを logstash コンテナーに書き込みました。
次に、oneapm が提供するサービスを使用しました。これは悪くありません。他のオープンソース ツールのオプションもありますが、oneapm のサービスを使用する方が便利です。
このようにして完全な技術スタックが完成し、数日間実行しても問題はありませんでした。もちろん、プログラマーを目指す私には、より高い要件が必要です。そこで、次の質問を思いつきました。Docker の概念は、コンテナーが完全なサービスであるということですが、私たちの用途は、コンテナー内で PHP-FPM を実行することです。は含まれていませんが、ディレクトリ マウントを通じて実装されます。このように、コードをホストにデプロイする必要があります。サービスとしてのコンテナーの概念を完全に実装することはできません。よし、完璧を追求しよう!
実際、コードをコンテナーに入れるのは、概念的な完璧さを追求するためだけではなく、Docker ベースの CI という別の目的もあります。基本的な考え方は、リリースごとに新しいバージョンのイメージがビルドされ、ビルド プロセス中にコードを最新バージョンに更新し、依存するサードパーティ ライブラリやその他のビジネス関連の前処理を行う必要があるということです。ビルドが完了したら、それをレジストリにプッシュし、各ノードをプルダウンしてコンテナを再起動します。プロセス全体を以下の図に示します。
どうですか?これで完璧です!現実が完璧であればいいのですが、現実には常にさまざまな落とし穴が待っています。
まず、この仕組みが使用される前は、ブランチをマージして各ノードからコードをプルするだけでコードをリリースするのに数秒しかかかりませんでしたが、Docker を使用した後は、マージ後にイメージをビルドする必要があります。ブランチを作成し、ビルド後にレジストリにプッシュし、各ノードに移動してイメージをプルダウンします。少なくとも数分かかります。現時点では、Docker ミラーリングの原理はレイヤー メカニズムではない、と言う学生もいるかもしれません。確かに、各ビルドは更新する必要があるレイヤーを更新するだけで済みますが、更新する方法はまだありません。 git ファイルのようないくつかのファイルだけが、少なくともプロジェクトのコード ディレクトリ全体を更新します。
次に、以前はコードを更新するだけで済みましたが、今はコンテナを再起動する必要があります。コンテナの再起動は高速ですが、コンテナ内での PHP-FPM の実行は非常に遅くなります。docker stop が実行されると、SIGTERM シグナルがコンテナ内のプロセスに送信され、PHP-FPM が SIGTERM シグナルを処理することになると思います。掃除が終わってください。ノード上には少なくとも数十のコンテナがあり、各コンテナを再起動するには非常に時間がかかります。
このようなリリースは、もともと非常に単純でしたが、この「完璧な」メカニズムを使用した後は数分かかります。プロセス全体は完全に自動化されていますが、完璧を期すためにそのような妥協をする必要はありません。
さらに、別の非常に奇妙な問題にも遭遇しました。1.10 にアップグレードした後、コンテナに入って、いずれかのネットワーク リクエストを開始すると、ポートがブロックされることがよくあります。次のIP、ポートは通常に戻ります。さまざまなツールを使って長い間デバッグを続けましたが、依然として問題が何であるかを突き止めることができませんでした。ディアオシの新興企業には、そのような深刻な問題を研究するエネルギーがなかったため、当面は脇に置いておかなければなりませんでした。 。
長い間苦労した後、ようやく以前のやり方に戻りました。
6. 探索を続けます
アーキテクチャの観点から、プロセス全体についての私の考えを簡単にまとめておきます。完璧なアーキテクチャは存在しません。唯一、あなたに最適なアーキテクチャがあります。プログラマーの観点から見ると、テクノロジーを選択するときに最も重要なことは、現在のプロジェクトのニーズ、さまざまなテクノロジーに対するチームの理解、テクノロジーの選択によってもたらされる複雑さを比較検討することです。数人の専門家による技術アーキテクチャの共有を読んだ後は、自分のプロジェクトに積極的に挑戦しないでください。最終的には、自分で処理することさえできず、他の人に後始末を任せなければなりません。最後に、プロジェクトの反復中にプロジェクトをシンプルに保つ能力は、コーダーの技術レベルを測る上で常に重要な基準となります。