hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

httpd コンテナを自動起動する方法



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 参考図書

今回の記事執筆にあたり参考にした図書は以下のものです。

単行本


Docker実践ガイド 第3版 (impress top gear)

電子書籍



Software Design (ソフトウェアデザイン) 2023年11月号 [雑誌]


Docker実践ガイド 第3版 impress top gearシリーズ