RHEL で Podman を使用してコンテナを実行する

Red Hat Enterprise LinuxBeginner
オンラインで実践に進む

はじめに

この実験(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_serverweb_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 コマンドを使用して、ホストマシンからの接続性をテストしましょう。これは、ポート 8080localhost に 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 と統合し、システムサービスとして管理して、起動時に自動的に起動し、確実に実行されるようにし、本番環境対応のデプロイパターンを示しました。