はじめに
この実験(Lab)では、Red Hat Enterprise Linux (RHEL) 上で Podman を使用して、マルチティア Web アプリケーションをデプロイする方法を学びます。バックエンドとして MariaDB データベースコンテナ、フロントエンドとして Apache Web サーバーコンテナをデプロイすることで、完全なソリューションを構築します。この実践的な経験を通して、初期設定からサービスの公開アクセスまで、コンテナ化されたアプリケーションのデプロイに必要な手順を習得できます。
まず、MariaDB コンテナを実行し、環境変数を使用して起動時に設定します。次に、データベースのデータ永続性を確保するために永続ストレージを構成し、コンテナ間の通信用のカスタムネットワークを作成します。その後、Apache Web サーバーをデプロイし、そのポートを公開して接続性をテストします。最後に、堅牢で自動化された操作のために、コンテナを systemd サービスとして管理する方法を学びます。
環境変数を使用して MariaDB データベースコンテナを実行する
このステップでは、コンテナ化されたアプリケーションを実行し、環境変数を使用して起動時に設定する方法を学びます。これは、コンテナ管理における基本的なスキルであり、柔軟で安全なデプロイを可能にします。データベースを初期化するためにいくつかの設定パラメータが必要なため、例として公式の MariaDB イメージを使用します。
まず、正しい作業ディレクトリにいることを確認してください。この実験(Lab)のすべての作業は、~/project ディレクトリ内で行われます。
cd ~/project
コンテナを実行する前に、レジストリからイメージを明示的にプルすることをお勧めします。これにより、ローカルに正しいバージョンがあることを確認できます。この実験(Lab)では、一貫性を確保するために mariadb:10.6 イメージを使用します。
podman pull mariadb:10.6
Docker レジストリから mariadb:10.6 イメージを選択します。
イメージがダウンロードされ、抽出されていることを示す出力が表示されます。
10.6: Pulling from library/mariadb
...
Status: Downloaded newer image for mariadb:10.6
docker.io/library/mariadb:10.6
これで、MariaDB コンテナを実行できます。podman run コマンドは、新しいコンテナを作成して起動します。いくつかのフラグを使用します。
-d: コンテナをデタッチモード(バックグラウンド)で実行します。--name mariadb_server: コンテナに覚えやすい名前を割り当てます。-e VARIABLE=value: コンテナ内に環境変数を設定します。MariaDB イメージは、最初の起動時にこれらを使用してデータベースを構成します。
次のコマンドを実行して、MariaDB コンテナを起動します。ルートパスワードを設定し、webappdb という名前の新しいデータベースを、専用のユーザー webappuser を使用して作成します。
podman run -d \
--name mariadb_server \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
mariadb:10.6
このコマンドは長いコンテナ ID を出力し、コンテナが作成されたことを確認します。
a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
コンテナが実行されていることを確認するには、podman ps コマンドを使用します。
podman ps
実行中のコンテナのリストに mariadb_server が表示されます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" 15 seconds ago Up 14 seconds 3306/tcp mariadb_server
最後に、コンテナのログをチェックして、提供した環境変数を使用してデータベースが正しく初期化されたことを確認しましょう。
podman logs mariadb_server
ログをスクロールします。サーバーが接続の準備ができていることを示す行を探します。これは、起動が成功したことを確認します。出力は長くなりますが、最後の方にある重要な成功メッセージは次のようになります。
...
2024-05-20 10:30:00+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/
...
2024-05-20 10:30:15+00:00 [Note] mariadbd: ready for connections.
Version: '10.6.x-MariaDB-1:10.6.x+maria~ubu2004' socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
環境変数を使用して、MariaDB コンテナを正常に起動および設定しました。
MariaDB コンテナの永続ストレージを構成する
このステップでは、コンテナの永続ストレージを設定する方法を学びます。デフォルトでは、コンテナ内で作成されたすべてのデータは、コンテナのライフサイクルに紐づく書き込み可能なレイヤーに保存されます。コンテナを削除すると、そのデータはすべて失われます。データベースのようなステートフルなアプリケーションにとって、これは理想的ではありません。これを解決するために、Podman ボリュームまたはバインドマウントを使用して、コンテナとは独立してホストファイルシステムにデータを保存します。
まず、新しいストレージ設定で再起動するため、前のステップで作成したコンテナを削除する必要があります。
実行中の mariadb_server コンテナを停止します。
podman stop mariadb_server
コマンドが受信されたことを確認するために、コンテナの名前が出力されます。
mariadb_server
次に、停止したコンテナを削除します。
podman rm mariadb_server
ここでも、コンテナの名前がエコーバックされます。
mariadb_server
次に、ホストマシン上の ~/project ディレクトリ内にディレクトリを作成します。このディレクトリは、MariaDB データベースファイルを保持します。
mkdir ~/project/mariadb_data
rootless モードで Podman を使用する場合、マウントされたディレクトリの正しい権限を設定する必要があります。MariaDB コンテナは特定のユーザー (UID 999) として実行されるため、ディレクトリにアクセスできることを確認する必要があります。--userns=keep-id フラグを使用し、適切な権限を設定します。
chmod 755 ~/project/mariadb_data
次に、MariaDB コンテナを再度実行します。このコマンドは、前のステップのコマンドと似ていますが、ユーザーネームスペースのマッピングを適切に処理するために、-v フラグと --userns=keep-id が追加されています。-v フラグは、ホストの ~/project/mariadb_data ディレクトリをコンテナ内の /var/lib/mysql ディレクトリにマウントします。これは、MariaDB がデータを保存する場所です。$(pwd)/mariadb_data を使用して、podman コマンドに必要な絶対パスを提供します。
podman run -d \
--name mariadb_server \
--userns=keep-id \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
-v $(pwd)/mariadb_data:/var/lib/mysql:Z \
mariadb:10.6
ボリュームマウントの :Z サフィックスは、Podman にコンテンツをプライベートな共有されていないラベルで再ラベル付けするように指示します。これは、SELinux の互換性にとって重要です。
コンテナが起動した後、データがホストマシンに保存されていることを確認できます。~/project/mariadb_data ディレクトリの内容を一覧表示します。
ls -l ~/project/mariadb_data
コンテナのデータベースエンジンが初期化されているため、~/project/mariadb_data 内にいくつかのファイルとディレクトリが作成されているのがわかります。これにより、データが永続的になったことが確認できます。コンテナを削除しても、このデータは残ります。
total 110632
-rw-rw---- 1 labex labex 16384 May 20 10:45 aria_log.00000001
-rw-rw---- 1 labex labex 52 May 20 10:45 aria_log_control
-rw-rw---- 1 labex labex 983 May 20 10:45 ib_buffer_pool
-rw-rw---- 1 labex labex 12582912 May 20 10:45 ibdata1
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile0
-rw-rw---- 1 labex labex 50331648 May 20 10:45 ib_logfile1
drwx------ 2 labex labex 4096 May 20 10:45 mysql
drwx------ 2 labex labex 4096 May 20 10:45 performance_schema
drwx------ 2 labex labex 4096 May 20 10:45 sys
drwx------ 2 labex labex 4096 May 20 10:45 webappdb
MariaDB コンテナが永続ストレージを使用するように正常に設定され、データベースデータがコンテナの再起動と削除後も保持されるようになりました。
カスタムネットワークの作成と Apache Web サーバーのデプロイ
このステップでは、コンテナ用のカスタムネットワークを作成し、Apache Web サーバーをデプロイします。Podman はデフォルトのネットワークを提供しますが、カスタムネットワークを使用することがベストプラクティスです。これらは、より優れた分離を提供し、最も重要なこととして、コンテナ間の自動 DNS 解決を可能にします。これにより、コンテナは名前を使用して互いに通信できるようになり、変更される可能性のある IP アドレスを使用するよりも信頼性が高くなります。
まず、アプリケーション用のカスタムブリッジネットワークを作成しましょう。webapp-network という名前を付けます。
podman network create webapp-network
このコマンドは、新しく作成されたネットワークの名前を出力します。
webapp-network
Podman ネットワークをすべて一覧表示して、自分のネットワークが正常に作成されたことを確認できます。
podman network ls
デフォルトのネットワークとともに、リストに webapp-network が表示されます。
NETWORK ID NAME DRIVER SCOPE
...
f1e2d3c4b5a6 webapp-network bridge local
...
次に、この新しいネットワークで mariadb_server コンテナを再作成する必要があります。この環境のネットワークバックエンド設定により、既存のコンテナを新しいネットワークに接続することはできません。代わりに、新しいネットワーク設定でコンテナを停止して再作成します。
実行中の mariadb_server コンテナを停止します。
podman stop mariadb_server
停止したコンテナを削除します。
podman rm mariadb_server
次に、新しいネットワークで MariaDB コンテナを再作成します。このコマンドは、前のステップのコマンドと似ていますが、--network webapp-network フラグが追加されています。
podman run -d \
--name mariadb_server \
--network webapp-network \
--userns=keep-id \
-e MARIADB_ROOT_PASSWORD=supersecret \
-e MARIADB_DATABASE=webappdb \
-e MARIADB_USER=webappuser \
-e MARIADB_PASSWORD=userpass \
-v $(pwd)/mariadb_data:/var/lib/mysql:Z \
mariadb:10.6
次に、Web サーバーをデプロイしましょう。公式の Apache httpd イメージを使用します。まず、Web サイトのファイルを保存するためのディレクトリをホスト上に作成します。
mkdir ~/project/webapp_content
この新しいディレクトリに、単純な index.html ファイルを作成します。これが Web アプリケーションのホームページになります。
echo "<h1>Welcome to My Web App</h1>" > ~/project/webapp_content/index.html
Apache コンテナがファイルにアクセスできるように、webapp コンテンツディレクトリの正しい権限を設定します。
chmod 755 ~/project/webapp_content
次に、Apache httpd コンテナを実行します。これを webapp-network に接続し、webapp_content ディレクトリをボリュームとしてマウントします。これにより、Web サーバーが作成したばかりの index.html ファイルを提供できるようになります。
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
httpd:2.4
オプションを分解してみましょう。
--network webapp-network: 新しいコンテナをカスタムネットワークに接続します。-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z: これにより、ローカルのwebapp_contentディレクトリがコンテナ内の/usr/local/apache2/htdocs/にマウントされます。これは、Apache がファイルを配信するデフォルトのディレクトリです。:Zサフィックスは、Podman に SELinux の互換性のためにコンテンツをプライベートな共有されていないラベルで再ラベル付けするように指示します。
両方のコンテナが実行されていることを確認します。
podman ps
これで、実行中のコンテナのリストに mariadb_server と web_server の両方が表示されます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a3f46c0ab3a docker.io/library/mariadb:10.6 mariadbd 29 seconds ago Up 29 seconds 3306/tcp mariadb_server
da5d52ce9c41 docker.io/library/httpd:2.4 httpd-foreground 7 seconds ago Up 7 seconds 80/tcp web_server
両方のコンテナが同じカスタムネットワーク上にあり、名前で互いに通信できるようになりました。
Web サーバーポートの公開と接続性のテスト
このステップでは、コンテナのポートをホストマシンに公開し、コンテナの分離されたネットワークの外部からサービスにアクセスできるようにする方法を学びます。Apache Web サーバーは実行されていますが、ホストのブラウザまたはコマンドラインからまだアクセスできません。コンテナのポートを公開することでこれを修正します。
ポートマッピングは、コンテナが作成されるときに定義されます。したがって、まず、前のステップで作成した web_server コンテナを停止して削除する必要があります。Web サイトのコンテンツについては心配ありません。バインドマウントを使用したため、ホストの ~/project/webapp_content ディレクトリに安全に保存されています。
まず、コンテナを停止します。
podman stop web_server
web_server
次に、停止したコンテナを削除します。
podman rm web_server
web_server
次に、web_server コンテナを再度実行しますが、今回は -p (または --publish) フラグを追加して、ホストのポートをコンテナのポートにマッピングします。ホストのポート 8080 をコンテナ内のポート 80 (デフォルトの HTTP ポート) にマッピングします。
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
-p 8080:80 \
httpd:2.4
新しいフラグ -p 8080:80 は、Podman にホストのポート 8080 からのすべてのトラフィックを web_server コンテナ内のポート 80 に転送するように指示します。
podman ps を使用して、コンテナが実行されており、ポートが正しくマッピングされていることを確認しましょう。
podman ps
web_server コンテナの PORTS 列に注目してください。0.0.0.0:8080 から 80/tcp へのマッピングが表示されるようになり、ポートが正常に公開されていることを示しています。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c5d4e3f2a1b6 httpd:2.4 "httpd-foreground" 10 seconds ago Up 9 seconds 0.0.0.0:8080->80/tcp web_server
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" 25 minutes ago Up 25 minutes 3306/tcp mariadb_server
最後に、curl コマンドを使用して、ホストマシンからの接続性をテストしましょう。これは、ポート 8080 の localhost に HTTP リクエストを送信します。
curl http://localhost:8080
index.html ファイルからの HTML コンテンツが出力として表示されるはずです。これにより、Web サーバーがホストからアクセスできるようになったことが確認できます。
<h1>Welcome to My Web App</h1>
コンテナ化された Web サーバーをホストマシンに正常に公開しました。これは、アプリケーションをユーザーが利用できるようにするための重要なステップです。
systemd サービスとしての Web サーバーコンテナの管理
この最終ステップでは、コンテナを自動的に起動するように構成し、サービスがクラッシュやシステムの再起動に対して回復力を持つようにする方法を学びます。標準的な Red Hat Enterprise Linux システムでは、systemd がサービスの管理に使用される主要なツールです。ただし、この実験の Podman 環境では、systemd を使用してコンテナを直接管理しません。
代わりに、Podman の組み込みの 再起動ポリシー を使用して、同じ結果 (自動サービス再起動) を実現します。これは、Podman デーモンによってコンテナが自動的に起動されるようにするための標準的なコンテナネイティブな方法です。何らかの理由で停止した場合に常に再起動するように web_server を構成します。
まず、既存のコンテナを削除する必要があります。再起動ポリシーは、コンテナが作成された場合にのみ適用できるためです。
web_server コンテナを停止します。
podman stop web_server
web_server
そして、それを削除します。
podman rm web_server
web_server
次に、以前と同じ構成で web_server コンテナを再作成しますが、--restart always フラグを追加します。このフラグは、Podman デーモンにコンテナを監視し、終了した場合は再起動するように指示します。
podman run -d \
--name web_server \
--network webapp-network \
-v $(pwd)/webapp_content:/usr/local/apache2/htdocs/:Z \
-p 8080:80 \
--restart always \
httpd:2.4
コンテナは通常どおり起動します。再起動ポリシーがアクティブであることを確認するには、コンテナの構成を検査します。
podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'
このコマンドは always を返し、ポリシーが設定されていることを確認します。
always
次に、システムの再起動またはコンテナの障害後に何が起こるかをシミュレートするために、再起動ポリシーがどのように機能するかを、コンテナを手動で再起動して示しましょう。
まず、現在の再起動ポリシー構成を確認しましょう。
podman inspect web_server --format '{{.HostConfig.RestartPolicy.Name}}'
これにより、always が表示され、再起動ポリシーが構成されていることが確認されます。
always
次に、障害後の回復をシミュレートするために、手動再起動をテストしましょう。
podman start web_server
web_server
コンテナが実行されていることを確認します。
podman ps
再起動ポリシーが適用された状態で、両方のコンテナが実行されていることがわかります。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e7f6g5h4i3j2 httpd:2.4 "httpd-foreground" About a minute ago Up 5 seconds 0.0.0.0:8080->80/tcp web_server
a1b2c3d4e5f6 mariadb:10.6 "docker-entrypoint.s…" About an hour ago Up About an hour 3306/tcp mariadb_server
最後に、サービスにアクセスできることを確認します。
curl http://localhost:8080
<h1>Welcome to My Web App</h1>
再起動ポリシーの理解:
構成した --restart always ポリシーにより、次のことが保証されます。
- コンテナは、予期せず終了した場合に自動的に再起動します。
- コンテナは、Podman サービスが起動したとき (システムの再起動後など) に自動的に起動します。
- これにより、本番環境へのデプロイの回復力が向上します。
注:一部の実験環境では、自動再起動の動作は、Podman の構成と、Podman システムサービスが実行されているかどうかによって異なる場合があります。重要な学習目標は、本番環境へのデプロイの再起動ポリシーを構成する方法を理解することです。
サービスのように管理されるようにコンテナを正常に構成し、自動的に利用できるようにしました。これにより、コンテナ化されたアプリケーションの基本的なライフサイクル管理が完了します。
まとめ
この実験では、Podman を使用して RHEL 上にマルチコンテナ Web アプリケーションをデプロイする基本的なプロセスを学びました。まず、MariaDB データベースコンテナを実行し、実行時に環境変数を渡すことで、ルートパスワード、新しいデータベース、および専用ユーザーを含む初期状態を構成しました。次に、データベースコンテナの永続ストレージを構成し、コンテナの再起動後も重要なデータが保持されるようにしました。
アプリケーションスタックを完成させるために、コンテナ間の安全で分離された通信を可能にするカスタムネットワークを作成しました。このネットワーク上に Apache Web サーバーコンテナをデプロイし、そのポートを公開して外部ユーザーアクセスを許可しました。最後に、Web サーバーコンテナを systemd と統合し、システムサービスとして管理して、起動時に自動的に起動し、確実に実行されるようにし、本番環境対応のデプロイパターンを示しました。



