1 はじめに
Podmanはデーモンとして動作しないため、サーバのブート時にコンテナを自動起動するには、Podman をデーモンとして使用できません。サーバブート時のコンテナの自動起動は、systemd を通じて起動する必要があります。このことを確認するため、まず、httpd コンテナの起動方法を確認し、その後にsystemdを使用したコンテナの自動起動を確認します。
・httpd コンテナの起動方法の確認
・サーバ起動時のhttpd コンテナの自動起動
2 検証環境
構成は以下のとおりです。
httpdコンテナ (80) | | | PC ------------ (192.168.1.200:8080) サーバ(AlmaLinux 9.2)
サーバのAlmaLinux版数は以下のとおりです。
[user1@server ~]$ cat /etc/redhat-release AlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[user1@server ~]$ uname -r 5.14.0-284.11.1.el9_2.x86_64
3 コンテナの起動方法
サーバでhttpdのイメージをダウンロードします。レジストリの検索方法は、コンテナイメージのレジストリ検索方法(Podman編) - hana_shinのLinux技術ブログを参照してください。
[user1@server ~]$ podman pull docker.io/library/httpd
ダウンロードしたイメージを確認します。httpd イメージの最新版がダウンロードされたことが確認できます。
[user1@server ~]$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/httpd latest 19c71fbb7140 2 weeks ago 152 MB
test1 という名前の httpd コンテナを起動します。このとき、-p オプションを指定して、サーバの 8080 番ポートへのパケットをコンテナの 80 番ポートに転送するように設定します。
[user1@server ~]$ podman run -d -p 8080:80 --rm --name test1 httpd 73482f0731f7002a416e20aae490836e82f1d25136f796981b83ac7e6532e057
ポート番号のマッピングを確認します。サーバの任意(0.0.0.0.)の IP アドレス宛の 8080 番ポートへのパケットを、コンテナ内の 80 番ポートに転送する設定になっていることが確認できます。
[user1@server ~]$ podman port test1 80/tcp -> 0.0.0.0:8080
curlコマンドを実行すると、HTTPサーバからの応答が確認できます。
[user1@server ~]$ curl http://192.168.1.200:8080 <html><body><h1>It works!</h1></body></html>
podman top コマンドを実行して、test1 という名前のコンテナ内で実行中のプロセスを確認します。
[user1@server ~]$ podman top test1 USER PID PPID %CPU ELAPSED TTY TIME COMMAND root 1 0 0.000 1m37.434702295s ? 0s httpd -DFOREGROUND www-data 3 1 0.000 1m37.435169864s ? 0s httpd -DFOREGROUND www-data 4 1 0.000 1m37.43535964s ? 0s httpd -DFOREGROUND www-data 5 1 0.000 1m37.435440962s ? 0s httpd -DFOREGROUND
TCPの8080番ポートへのアクセスを許可します。
[user1@server ~]$ sudo firewall-cmd --add-port=8080/tcp success
許可しているポート番号のリストを確認します。TCPの8080番ポートへのアクセスが許可されていることが確認できます。
[user1@server ~]$ sudo firewall-cmd --list-ports 8080/tcp
PCのブラウザで以下のURLにアクセスすると、HTTPサーバから応答が返ってくることが確認できます。
http://192.168.1.200:8080/
あと始末をします。コンテナを削除します。
[root@server ~]# podman rm test1 --force test1
あと始末をします。イメージを削除します。
[root@server ~]# podman rmi httpd Untagged: docker.io/library/httpd:latest Deleted: 19c71fbb71404e06730aa9bc4ec079eefc63d84d46fa0fa1c768263669adb0d3
4 コンテナを自動起動する方法
次は、サーバを再起動した際にコンテナを自動で起動する方法を説明します。コンテナを自動起動するには、コンテナ用のユニットファイルを作成する必要があります。
コンテナを作成します。
[user1@server ~]$ podman create -p 8080:80 --name test1 docker.io/library/httpd a327394e0a68d0495ed72e8099bcfd99274e99a238df6916928c89282c76d6ca
作成したコンテナを確認します。test1 の状態が「Created」であることから、このコンテナは作成されたものの、まだ起動していないことがわかります。
[user1@server ~]$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a327394e0a68 docker.io/library/httpd:latest httpd-foreground 10 seconds ago Created 0.0.0.0:8080->80/tcp test1
podman generate コマンドを実行して、httpd コンテナーの systemd ユニットファイルを生成します。
[user1@server ~]$ podman generate systemd --new --files --name test1 /home/user1/container-test1.service
作成したユニットファイルのSELinuxコンテキストを確認します。
[user1@server ~]$ ls -lZ container-test1.service -rw-r--r--. 1 user1 user1 unconfined_u:object_r:user_home_t:s0 757 8月 4 21:02 container-test1.service
作成したユニットファイルを確認します。
[user1@server ~]$ cat /home/user1/container-test1.service # container-test1.service # autogenerated by Podman 4.4.1 # Sun Aug 4 21:02:56 JST 2024 [Unit] Description=Podman container-test1.service Documentation=man:podman-generate-systemd(1) Wants=network-online.target After=network-online.target RequiresMountsFor=%t/containers [Service] Environment=PODMAN_SYSTEMD_UNIT=%n Restart=on-failure TimeoutStopSec=70 ExecStart=/usr/bin/podman run \ --cidfile=%t/%n.ctr-id \ --cgroups=no-conmon \ --rm \ --sdnotify=conmon \ -d \ --replace \ -p 8080:80 \ --name test1 docker.io/library/httpd ExecStop=/usr/bin/podman stop \ --ignore -t 10 \ --cidfile=%t/%n.ctr-id ExecStopPost=/usr/bin/podman rm \ -f \ --ignore -t 10 \ --cidfile=%t/%n.ctr-id Type=notify NotifyAccess=all [Install] WantedBy=default.target
作成したユニットファイルを /etc/systemd/system にコピーします。
[user1@server ~]$ sudo cp -Z container-test1.service /etc/systemd/system
コピーしたユニットファイルの SELinuxコンテキストを確認します。/etc/systemd/systemのデフォルトのSELinuxコンテキストであることが確認できます。
[user1@server ~]$ ls -lZ /etc/systemd/system/container-test1.service -rw-r--r--. 1 root root unconfined_u:object_r:systemd_unit_file_t:s0 757 8月 4 21:07 /etc/systemd/system/container-test1.service
systemctl daemon-reload コマンドを実行して、systemdにユニットファイルの作成を通知し、ユニットファイルの再読み込みを指示します。
[user1@server ~]$ systemctl daemon-reload
システム起動時に自動的に起動(enable)するように設定して、サービスを即時起動(--now)します。これにより、サービスがすぐに開始されます。
[user1@server ~]$ sudo systemctl enable --now container-test1.service
サービスの状態を確認します。サービスが動作していることが確認できます。
[user1@server ~]$ systemctl status container-test1.service ● container-test1.service - Podman container-test1.service Loaded: loaded (/etc/systemd/system/container-test1.service; enabled; preset: disabled) Active: active (running) since Sun 2024-08-04 21:12:21 JST; 31s ago Docs: man:podman-generate-systemd(1) Main PID: 4791 (conmon) Tasks: 1 (limit: 22895) Memory: 168.1M CPU: 13.844s CGroup: /system.slice/container-test1.service mq4791 /usr/bin/conmon --api-version 1 -c 3803b2b1bf5c4a7e8a6a740f9fcc9ba10267e166248d470329758e88289e6bc5 > [user1@server ~]$
サーバを再起動します。
[user1@server ~]$ shutdown -r now
サーバが再起動したあと、サービスの状態を確認します。サービスが自動的に起動していることが確認できます。
[user1@server ~]$ systemctl status container-test1.service ● container-test1.service - Podman container-test1.service Loaded: loaded (/etc/systemd/system/container-test1.service; enabled; preset: disabled) Active: active (running) since Sun 2024-08-04 21:14:25 JST; 6min ago Docs: man:podman-generate-systemd(1) Main PID: 1831 (conmon) Tasks: 1 (limit: 22895) Memory: 51.3M CPU: 878ms CGroup: /system.slice/container-test1.service mq1831 /usr/bin/conmon --api-version 1 -c ef1e2a77f99e88fd0f2a97279bad86ce2678d5ca57b995c417106f439485cb85 > [user1@server ~]$
curlコマンドを実行すると、HTTPサーバからの応答が確認できます。
[user1@server ~]$ curl http://192.168.1.200:8080 <html><body><h1>It works!</h1></body></html>
後始末します。サービス(httpdコンテナ)を停止します。
[user1@server ~]$ sudo systemctl stop container-test1.service [user1@server ~]$
サービスを停止したので、curl コマンドを実行すると、HTTPサーバに接続拒否されていることがわかります。
[user1@server ~]$ curl http://192.168.1.200:8080 curl: (7) Failed to connect to 192.168.1.200 port 8080: 接続を拒否されました
Y 参考図書
今回の記事執筆にあたり参考にした図書は以下のものです。