PR
PR

「Ubuntuで始めるPodman入門:Podman Composeで始めるマルチコンテナ運用(NginxとMariaDB連携を行ってみる)

記事内に広告が含まれています。

前回「Ubuntuで始めるPodman入門: Nginxコンテナ起動まで」 の記事で、Podmanの基本的な使い方を説明したので、次は複数のコンテナ「Webサーバー(Nginx)」と「データベース(MariaDB)」の連携環境を構築していきます。

podman-composeを使うことで、複数コンテナの連携を一つの設定ファイルで実現することができます。

開発時やテストの際には、すぐにコンテナの再起動やログを確認することが出来るのでとても便利です。

Podman Composeとは?

Podman Composeは、Docker ComposeのYAMLファイル形式を使って、Podmanで複数の連携するコンテナアプリケーションを定義・管理・実行するためのツールです。

Podmanを使う上で、Webサービスのようなマルチコンテナ環境をシンプルに構築することができる、とても便利な存在です。

Pod(コンテナのグループ)としてまとめて起動できるため、開発やテストの際にコンテナの再起動やログ確認が容易になります。

Podman Composeの主な特徴

  • Docker Compose互換性:

    既存のdocker-compose.ymlファイルをそのまま、または少しの修正でPodman環境で使用できます。

  • Podの活用(コンテナのグループ化):

    定義された複数のサービス(コンテナ)を、Podmanの機能である「Pod」(リソースを共有するコンテナのグループ)としてまとめて起動します。

  • デーモンレス/ルートレス:

    Podmanの利点である、デーモン(常駐プロセス)不要のアーキテクチャと、非rootユーザーでのコンテナ実行(ルートレス)を実現します。

これにより、開発者はDocker Composeと同じ感覚で、より安全でシンプルなPodman環境で複雑なサービスを構築・運用できます。

Podman Composeのインストール

podman-composeをaptを使ってインストールします。

$ sudo apt install -y podman-compose

プロジェクトディレクトリの作成

作業を始めるために、メインとなるプロジェクトディレクトリを作成します。

今回はmy_projectというディレクトリを作成し、その中で設定ファイル(docker-compose.yml)を管理します。

$ mkdir my_project
$ cd my_project

これで、マルチコンテナ環境を定義・実行する準備が整いました。

設定ファイル(docker-compose.yml)の作成

それでは、NginxとMariaDBを連携させるための設定ファイル(docker-compose.yml)を作成します。

$ vi docker-compose.yml

今回は、以下の内容でファイルを作成します。

services:
  # 1. Webサーバ (Nginx)
  web:
    image: docker.io/library/nginx:latest
    ports:
      - "8080:80"      # ホストの8080ポートをNginxの80番に公開
    volumes:
      # ホストの./htmlディレクトリをコンテナにマウント
      - ./html:/usr/share/nginx/html:Z 
    depends_on:
      - db             # MariaDBが起動完了してから起動するように指定

  # 2. データベース (MariaDB)
  db:
    image: docker.io/library/mariadb:latest
    environment:
      # 必須設定: DBのrootパスワード
      MARIADB_ROOT_PASSWORD: my_secure_password
      # 初期データベース名
      MARIADB_DATABASE: my_app_db
    volumes:
      # DBデータを永続化するためのデータ領域をマウント
      - db_data:/var/lib/mysql:Z 
    restart: always

# 3. 永続化ボリュームの定義
volumes:
  db_data:

サービスの起動

docker-compose.ymlに登録したサービスを起動するためには、docker-compose.ymlファイルがあるディレクトリで、以下のコマンドを実行します。

$ podman-compose up -d

このコマンドにより、PodmanはNginxとMariaDBのイメージをプル(ダウンロード)し、2つのコンテナを連携させたPodを作成し、バックグラウンドで起動します。

起動ステータスの確認

「podman ps」コマンドで、両方のコンテナが正しく実行されていることとPodmanによって起動されたコンテナ名(例: my_project_web_1)が表示され、STATUSが Up であれば起動成功です。

$ podman ps
CONTAINER ID  IMAGE                             COMMAND               CREATED         STATUS         PORTS                 NAMES
658e913f57af  docker.io/library/mariadb:latest  mariadbd              13 seconds ago  Up 13 seconds                        my_project_db_1
f8ae16e61bc8  docker.io/library/nginx:latest    nginx -g daemon o...  11 seconds ago  Up 11 seconds  0.0.0.0:8080->80/tcp  my_project_web_1

停止と削除

作業を終える際は、podman-compose downコマンドを実行することで、すべてのコンテナを停止・削除できます。

「podman ps -a」コマンドで確認すると、コンテナが削除されていることが確認できます。

$ podman-compose down
$ podman ps -a
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

データの永続化:ボリューム入門

コンテナ運用で重要な概念である「ボリューム」について解説します。

問題点:コンテナは"使い捨て"

コンテナは、隔離された環境でアプリケーションを実行するための非常に便利な技術ですが、その基本設計は「一時的」で「使い捨て」であるという思想に基づいています。

「podman-compose down」コマンドを実行すると、コンテナは完全に削除され、コンテナの中で作成・保存されたファイル(例:アップロードされた画像、Nginxのアクセスログなど)も一緒に消えてしまいます。

では、データベースのデータや、変更した設定ファイルのように、コンテナを停止・削除しても永続的に残しておきたいデータは、どのように扱えばよいのでしょうか?

解決策:ボリュームでデータをコンテナから分離する

その答えがボリューム (Volume)です。

ボリュームは、コンテナのライフサイクル(作成、起動、停止、削除)から独立してデータを管理するための仕組みです。

これにより、データをコンテナの外、つまりホストマシン上やPodmanが管理する専用領域に保存できます。

Podmanでは、主に以下の2種類のボリュームが使われるので、それぞれの特徴をたとえで説明してみます。

1.バインドマウント (Bind Mount)

バインドマウントは、ホストマシン上の特定のファイルやディレクトリを、そのままコンテナ内の特定の場所に「見せる」技術です。

  • たとえ:デスクトップにあるフォルダへの「ショートカット」をイメージしてください。
  • 仕組み:コンテナがショートカットを通じてファイルを編集すると、実際にはホスト上の元のファイルが直接変更されます。
  • データの場所:ホスト上のユーザーが指定した特定のファイル/ディレクトリに保存されます。
  • 用途:ホストマシン側で直接編集したいファイル、例えば設定ファイル(Nginxの.confファイルなど)や、開発中のソースコードをコンテナに読み込ませるのに最適です。

2. 名前付きボリューム (Named Volume)

名前付きボリュームは、Podman自体にデータ管理を「おまかせ」する方式です。

こちらはボリュームに名前を付けるだけで、Podmanがホストマシン上の最適な場所に専用のデータ領域を作成・管理してくれます。

  • たとえ:Podmanが管理してくれる「専用の外付けUSBドライブ」をイメージしてください。
  • 仕組み:コンテナに「このUSBドライブを接続して、大事なデータは全部ここに保存してね」と指示することで、この場所に保存されたデータは、コンテナがなくなっても、Podmanが安全に保管してくれます。
  • データの場所:Podmanが管理する専用領域(例: ~/.local/share/containers/storage/volumes/...)に保存されます。(ホスト上のパスを意識する必要はありません。)
  • 用途:データベースのデータファイルや、ユーザがアップロードしたコンテンツなど、ホスト側から直接編集する必要はないが、永続化が必須のデータに適しています。

実践:ボリュームの活用

ここからは、先ほど説明をしたボリュームの概念を、NginxとMariaDBの環境構築に具体的に適用していきます。

Nginxの設定とログ:バインドマウントの活用

NginxのWebコンテンツ(HTMLファイル)や設定ファイルは、ホストマシンで直接編集できると便利です。

また、アクセスログやエラーログ等をホストマシンに残しておきたい場合は「バインドマウント」が最適です。

今回はNginxコンテナにボリュームの設定として、以下の設定を行ってみました。

  • ./nginx/conf.d:/etc/nginx/conf.d/:ro

    ホストの./nginx/conf.dディレクトリを、コンテナ内の/etc/nginx/conf.d/にマウントして、そこにNginx設定ファイルを作成します。

  • ./html:/usr/share/nginx/html:Z

    ホストの./htmlディレクトリを、コンテナ内の/usr/share/nginx/htmlにマウントして、そこに格納されているhtmlファイルなどのコンテツを読み込ませます。

  • ./nginx/logs:/var/log/nginx:Z

    ホストの./nginx/logsディレクトリをコンテナ内の/var/log/nginxにマウントして、Nginxのログファイルがホスト側に残り続けるようにします。

  • /etc/localtime:/etc/localtime:ro

    コンテナのタイムゾーン設定は「UTC」になっています。

    そのままではログの時刻とかが日本の時刻と異なってしまうので、ホストのタイムゾーン設定ファイル「/etc/localtime」を、コンテナ内の「/etc/localtime」にマウントして、タイムゾーンをホスト側の設定に合わせるようにします。

services:
  # 1. Webサーバ (Nginx)
  web:
    image: docker.io/library/nginx:latest
    ports:
      - "8080:80"      # ホストの8080ポートをNginxの80番に公開
    volumes:
      # Nginx設定ファイルを格納するホストのディレクトリ (読み取り専用)
      - ./nginx/conf.d/:/etc/nginx/conf.d/:ro
      # Webコンテンツを格納するホストのディレクトリ
      - ./html:/usr/share/nginx/html:Z
      # Nginxのログを永続化するためのホストのディレクトリ
      - ./nginx/logs:/var/log/nginx:Z
      # タイムゾーンをホストと同期
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - db             # MariaDBサービスが起動完了してから起動するように指定

### MariaDBの設定は省略

マウントオプションについて

ボリュームを設定する際、パスの末尾にオプションを追加できます。

ホストのパス:コンテナ内のパス:オプション
  • ro: 読み込み専用(Read Only)
  • rw: 読み書き可能(Read and Write)
  • Z: SELinuxが有効な環境でアクセス許可を与えるために使用

    他のコンテナからこのボリュームアクセスすることができなくなります。
    マルチコンテナでは通常「Z」を使用します。

  • z: SELinuxが有効な環境でアクセス許可を与えるために使用

    こちらは複数のコンテナが同じボリュームを共有する必要がある場合に利用します。

SELinuxを使用していない環境では「Z」や「z」は必要ありません。

MariaDBのデータ:名前付きボリュームの活用

MariaDBのデータベースファイルは、アプリケーションによって頻繁に書き換えられますが、私たちが直接ファイルを編集することはほとんどありません。

このようなデータは、コンテナが消えても安全に保持される必要があります。

こういった場合は、Podmanに管理を任せる「名前付きボリューム」が最適です。

docker-compose.ymlの末尾でボリュームに名前を付け(例 volumes: db_data:)、サービス定義の中でその名前を指定してマウントします。

名前付きボリュームの実際のデータは、「~/.local/share/containers/storage/volumes/プロジェクト名_ボリューム名/_data」のようなPodman管理下のディレクトリに保存されます。

services:

### Nginxの設定部分は省略

  # 2. データベース (MariaDB)
  db:
    image: docker.io/library/mariadb:latest
    environment:
      # 必須設定: DBのrootパスワード
      MARIADB_ROOT_PASSWORD: my_secure_password
      # 初期データベース名
      MARIADB_DATABASE: my_app_db
    volumes:
      # DBデータを永続化するための名前付きボリュームをマウント
      - db_data:/var/lib/mysql:Z
    restart: always              # コンテナが停止しても自動で再起動する設定

# 3. 永続化ボリュームの定義 (Podmanが管理)
volumes:
  db_data:

最終的な構成

NginxとMariaDBのボリューム設定をすべて反映した、最終的な構成図とdocker-compose.ymlファイルです。

名前付きボリューム「db_data」の実際のデータは、Podmanの管理領域「~/.local/share/containers/storage/volumes/my_project_db_data/_data」に保存されます。

構成図

[ホームディレクトリ]
    |-- my_project/
    |   |-- docker-compose.yml
    |   |-- html/             # Nginxコンテナ:/usr/share/nginx/html (バインドマウント)
    |   `-- nginx/
    |       |-- conf.d/ (ro)- # Nginxコンテナ:/etc/nginx/conf.d (バインドマウント)
    |       `-- logs/         # Nginxコンテナ:/var/log/nginx (バインドマウント)
    |
    `-- [名前付きボリューム: db_data] # MariaDBコンテナ:/var/lib/mysql (名前付きボリューム)

docker-compose.yml

services:
  # 1. Webサーバ (Nginx)
  web:
    image: docker.io/library/nginx:latest
    ports:
      - "8080:80"      # ホストの8080ポートをNginxの80番に公開
    volumes:
      # Nginx設定ファイルを格納するホストのディレクトリ (読み取り専用)
      - ./nginx/conf.d/:/etc/nginx/conf.d/:ro
      # Webコンテンツを格納するホストのディレクトリ
      - ./html:/usr/share/nginx/html:Z
      # Nginxのログを永続化するためのホストのディレクトリ
      - ./nginx/logs:/var/log/nginx:Z
      # タイムゾーンをホストと同期
      - /etc/localtime:/etc/localtime:ro
    depends_on:
      - db             # MariaDBサービスが起動完了してから起動するように指定

  # 2. データベース (MariaDB)
  db:
    image: docker.io/library/mariadb:latest
    environment:
      # 必須設定: DBのrootパスワード
      MARIADB_ROOT_PASSWORD: my_secure_password
      # 初期データベース名
      MARIADB_DATABASE: my_app_db
    volumes:
      # DBデータを永続化するための名前付きボリュームをマウント
      - db_data:/var/lib/mysql:Z
    restart: always              # コンテナが停止しても自動で再起動する設定

# 3. 永続化ボリュームの定義 (Podmanが管理)
volumes:
  db_data:

Nginxの設定反映と動作確認

ここでは、ホスト側で作成したバーチャルホスト設定(.confファイル)がNginxコンテナに正しくマウントされ、実際に機能しているかを確認します。

NginxをWebサーバーとして動作させるために、ホストOS側に以下の設定ファイルとコンテンツファイルを作成します。

バーチャルホスト設定(./nginx/conf.d/podman_server-memo.conf)

Nginxにバーチャルホストの設定を以下のように作成しました。

$ cat ./nginx/conf.d/podman_server-memo.conf 
server {
    listen 80;
    server_name podman.server-memo.net;
    root /usr/share/nginx/html;
    index index.html;
}

ホストのhostsファイルにドメインを登録

名前解決できるように、ホストの「/etc/hosts」にテスト用のドメインを登録しました。

$ cat /etc/hosts | grep podman
127.0.0.1 podman.server-memo.net

ウェブコンテンツ (./html/index.html) の作成

以下のようなindex.htmlを作成しました。

$ cat ./html/index.html
podman nginx test page !!

設定の反映と動作確認

コンテナが起動されいない場合は、以下のコマンドでコンテナを起動させて設定を反映させます。

$ podman-compose up -d

すでにコンテナが起動している場合は、以下のコマンドでコンテナを再起動させて、設定を反映させることができます。

$ podman-compose restart

curlコマンドで設定の反映を確認

curlコマンドでホストOSの8080番ポート経由でバーチャルホストにアクセスし、正しくコンテンツが返ってくるか確認します。

$ curl -L http://podman.server-memo.net:8080
podman nginx test page !!

作成したindex.htmlの内容が表示されれば、Nginxコンテナがホストの設定ファイルを正しく読み込んでいることが確認できます。

ログファイルとタイムゾーンの確認

Nginxログのボリュームとして指定したディレクトリ(./nginx/logs/)にアクセスログとエラーログが残っているか、またタイムゾーンが日本時間(JST)になっているかを確認します。

$ ls -l nginx/logs/
合計 16
-rw-r--r-- 1 tamohiko tamohiko 4212 10月 24 15:30 access.log
-rw-r--r-- 1 tamohiko tamohiko 6923 10月 24 15:29 error.log

コメント

タイトルとURLをコピーしました