この広告は、90日以上更新していないブログに表示しています。
イメージは時間が経つとバグや脆弱性の修正が必要になることがあります。修正が必要な場合、リポジトリから最新のイメージをプルし、コンテナを再作成する必要があります。io.containers.autoupdate は、コンテナの自動更新に関する設定を行うためのラベルです。このラベルには、コンテナの更新方法を指定する値を設定できます。具体的な設定値は以下の2つです。
io.containers.autoupdateの値 | 意味 |
---|---|
registry | リモートレジストリのイメージが更新されると、コンテナが自動的に更新されます |
local | ローカルに保存されているイメージが更新されると、コンテナが自動的に更新されます |
io.containers.autoupdate を使うことで、コンテナの自動更新を効率的に管理し、常に最新の状態を維持することができます。本記事では、io.containers.autoupdate に local を指定した際の動作について確認します。
サーバのAlmaLinux版数は以下のとおりです。
[user1@server ~]$ cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[user1@server ~]$ uname -r5.14.0-284.11.1.el9_2.x86_64
タグは何を使ってもかまいませんが、ここでは、タグが2.4のhttpd イメージをダウンロードします。
[user1@server ~]$ podman pull docker.io/library/httpd:2.4
ダウンロードしたイメージを確認します。httpd イメージのタグが2.4であることが確認できます。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/library/httpd 2.4 a49fd2c04c02 5 weeks ago 152 MB
podman create コマンドを使用して、my-httpd という名前のコンテナを作成し、自動更新の設定を行います。ラベルに "io.containers.autoupdate=local" を指定することで、このコンテナはローカルのイメージが更新された際に自動的に再作成されるようになります。
[user1@server ~]$ podman create --name my-httpd --label "io.containers.autoupdate=local" docker.io/library/httpd:2.48649fb16b03903842fb4ba2486c35375f6f5d8db1ec4733428d8161244f04a78
コンテナの状態を確認すると 「Created」 になっています。この状態は、コンテナが作成されたがまだ実行されていないことを示しています。コンテナは停止しており、実際に動作していません。
[user1@server ~]$ podman ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES8649fb16b039 docker.io/library/httpd:2.4 httpd-foreground 9 seconds ago Created my-httpd
ユニットファイルを格納するディレクトリを作成します。
[user1@server ~]$ mkdir -p /home/user1/config/systemd/user
ユニットファイルを生成します。
[user1@server ~]$ podman generate systemd my-httpd --new > /home/user1/.config/systemd/user/my-httpd.service
新しく作成したユニットファイルを systemd が認識できるようにします。
[user1@server ~]$ systemctl --user daemon-reload
サービスを有効化し、サービスを起動(--now)します。
[user1@server ~]$ systemctl --user enable --now my-httpd.serviceCreated symlink /home/user1/.config/systemd/user/default.target.wants/my-httpd.service → /home/user1/.config/systemd/user/my-httpd.service.
サービスの状態を確認すると、Active であることが確認できます。
[user1@server ~]$ systemctl --user status my-httpd.service● my-httpd.service - Podman container-8649fb16b03903842fb4ba2486c35375f6f5d8db1ec4733428d8161244f04a78.service Loaded: loaded (/home/user1/.config/systemd/user/my-httpd.service; enabled; preset: disabled) Active: active (running) since Tue 2024-08-27 22:23:40 JST; 3s ago Docs: man:podman-generate-systemd(1) Main PID: 9891 (conmon) Tasks: 2 (limit: 22895) Memory: 1.6M CPU: 201ms CGroup: /user.slice/user-1001.slice/user@1001.service/app.slice/my-httpd.service tq9886 /usr/bin/slirp4netns --disable-host-loopback --mtu=65520 --enable-sandbox --enable-seccomp --enable-ipv6 -c -e 3 -r 4 --netns-type> mq9891 /usr/bin/conmon --api-version 1 -c b885329c56abf5f6ebc297b09df2eabb327023b81d6989dc9431a29da8a29ed2 -u b885329c56abf5f6ebc297b09df>[user1@server ~]$
コンテナのラベルを確認します。
[user1@server ~]$ podman inspect my-httpd --format '{{json .Config.Labels}}' | jq{ "PODMAN_SYSTEMD_UNIT": "my-httpd.service", "io.containers.autoupdate": "local"}
podman auto-update コマンドを実行してコンテナの更新をしてみます。この時点ではイメージが更新されていないため、UPDATED の値が 「false」 となっています。これにより、コンテナがまだ更新されていないことが確認できます。
[user1@server ~]$ podman auto-update UNIT CONTAINER IMAGE POLICY UPDATED my-httpd.service b885329c56ab (my-httpd) docker.io/library/httpd:2.4 local false
LABELディレクティブを使って、イメージにラベルをつける Containerfile を作成します。ラベルをつけることで、ローカルに保存されているイメージを更新することができます。Containerfile の作成方法は、コンテナイメージの作り方(Containerfile 編) - hana_shinのLinux技術ブログを参照してください。
[user1@server ~]$ vi Containerfile[user1@server ~]$ cat ContainerfileFROM docker.io/library/httpd:2.4LABEL maintainer="hana_shin@example.com"
イメージをビルドします。
[user1@server ~]$ podman build -t docker.io/library/httpd:2.4 .
ビルドしたイメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/library/httpd 2.4 dd47d65b4c2f 4 seconds ago 152 MB
podman auto-update コマンドを実行すると、今度は UPDATED の値が true となりました。これは、更新されたイメージを検知した結果、コンテナが自動的に更新されたことを示しています。つまり、自動更新が正常に動作していることが確認できました。
[user1@server ~]$ podman auto-update UNIT CONTAINER IMAGE POLICY UPDATED my-httpd.service b885329c56ab (my-httpd) docker.io/library/httpd:2.4 local true
コンテナのラベルを確認すると、Containerfile で指定したラベル("maintainer": "hana_shin@example.com")が付加されていることが確認できます。つまり更新したイメージでコンテナが動作していることがわかります。
[user1@server ~]$ podman inspect my-httpd --format '{{json .Config.Labels}}' | jq{ "PODMAN_SYSTEMD_UNIT": "my-httpd.service", "io.buildah.version": "1.29.0", "io.containers.autoupdate": "local", "maintainer": "hana_shin@example.com"}
サービスを停止します。
[user1@server ~]$ systemctl --user stop my-httpd.service
サービスを無効化します。
[user1@server ~]$ systemctl --user disable my-httpd.serviceRemoved "/home/user1/.config/systemd/user/default.target.wants/my-httpd.service".
ユニットファイルを削除します。
[user1@server ~]$ rm /home/user1/.config/systemd/user/my-httpd.service
ユニットファイルが削除されたことを systemd が認識できるようにします。
[user1@server ~]$ systemctl --user daemon-reload
イメージを削除します。
[user1@server ~]$ podman rmi a49fd2c04c02
Docker Hub のhttpd イメージのタグを確認するには、次のコマンドを使用します。
[user1@server ~]$ curl -s https://registry.hub.docker.com/v2/repositories/library/httpd/tags/ | jq '.results[].name'"latest""bookworm""2.4.62-bookworm""2.4.62""2.4-bookworm""2.4""2-bookworm""2""alpine3.20""alpine"
今回の記事執筆にあたり参考にした図書は以下のものです。
Podmanはデーモンとして動作しないため、サーバのブート時にコンテナを自動起動するには、Podman をデーモンとして使用できません。サーバブート時のコンテナの自動起動は、systemd を通じて起動する必要があります。このことを確認するため、まず、httpd コンテナの起動方法を確認し、その後にsystemdを使用したコンテナの自動起動を確認します。
・httpd コンテナの起動方法の確認
・サーバ起動時のhttpd コンテナの自動起動
構成は以下のとおりです。
httpdコンテナ (80) | | |PC ------------ (192.168.1.200:8080) サーバ(AlmaLinux 9.2)
サーバのAlmaLinux版数は以下のとおりです。
[user1@server ~]$ cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[user1@server ~]$ uname -r5.14.0-284.11.1.el9_2.x86_64
サーバでhttpdのイメージをダウンロードします。レジストリの検索方法は、コンテナイメージのレジストリ検索方法(Podman編) - hana_shinのLinux技術ブログを参照してください。
[user1@server ~]$ podman pull docker.io/library/httpd
ダウンロードしたイメージを確認します。httpd イメージの最新版がダウンロードされたことが確認できます。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.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 httpd73482f0731f7002a416e20aae490836e82f1d25136f796981b83ac7e6532e057
ポート番号のマッピングを確認します。サーバの任意(0.0.0.0.)の IP アドレス宛の 8080 番ポートへのパケットを、コンテナ内の 80 番ポートに転送する設定になっていることが確認できます。
[user1@server ~]$ podman port test180/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 test1USER PID PPID %CPU ELAPSED TTY TIME COMMANDroot 1 0 0.000 1m37.434702295s ? 0s httpd -DFOREGROUNDwww-data 3 1 0.000 1m37.435169864s ? 0s httpd -DFOREGROUNDwww-data 4 1 0.000 1m37.43535964s ? 0s httpd -DFOREGROUNDwww-data 5 1 0.000 1m37.435440962s ? 0s httpd -DFOREGROUND
TCPの8080番ポートへのアクセスを許可します。
[user1@server ~]$ sudo firewall-cmd --add-port=8080/tcpsuccess
許可しているポート番号のリストを確認します。TCPの8080番ポートへのアクセスが許可されていることが確認できます。
[user1@server ~]$ sudo firewall-cmd --list-ports8080/tcp
PCのブラウザで以下のURLにアクセスすると、HTTPサーバから応答が返ってくることが確認できます。
http://192.168.1.200:8080/
あと始末をします。コンテナを削除します。
[root@server ~]# podman rm test1 --forcetest1
あと始末をします。イメージを削除します。
[root@server ~]# podman rmi httpdUntagged: docker.io/library/httpd:latestDeleted: 19c71fbb71404e06730aa9bc4ec079eefc63d84d46fa0fa1c768263669adb0d3
次は、サーバを再起動した際にコンテナを自動で起動する方法を説明します。コンテナを自動起動するには、コンテナ用のユニットファイルを作成する必要があります。
コンテナを作成します。
[user1@server ~]$ podman create -p 8080:80 --name test1 docker.io/library/httpda327394e0a68d0495ed72e8099bcfd99274e99a238df6916928c89282c76d6ca
作成したコンテナを確認します。test1 の状態が「Created」であることから、このコンテナは作成されたものの、まだ起動していないことがわかります。
[user1@server ~]$ podman ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESa327394e0a68 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.serviceDocumentation=man:podman-generate-systemd(1)Wants=network-online.targetAfter=network-online.targetRequiresMountsFor=%t/containers[Service]Environment=PODMAN_SYSTEMD_UNIT=%nRestart=on-failureTimeoutStopSec=70ExecStart=/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/httpdExecStop=/usr/bin/podman stop \ --ignore -t 10 \ --cidfile=%t/%n.ctr-idExecStopPost=/usr/bin/podman rm \ -f \ --ignore -t 10 \ --cidfile=%t/%n.ctr-idType=notifyNotifyAccess=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
systemctldaemon-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:8080curl: (7) Failed to connect to 192.168.1.200 port 8080: 接続を拒否されました
今回の記事執筆にあたり参考にした図書は以下のものです。
コンテナがホストの仮想ファイルシステムへの参照を禁止または許可する方法について説明します。仮想ファイルシステムとは、/proc、/sys、/dev などを指します。コンテナが動作するのに必要のない仮想ファイルシステムは、コンテナから見えないようにマスクすることで、セキュリティを向上させることができます。例えば、以下に抜粋したマニュアルを参照すると、/proc/acpi や /proc/kcore などはデフォルトでマスクされています。つまり、コンテナからこれらのファイルシステムをデフォルトで参照することはできません。
[root@kvm-host ~]# man podman-run ~ unmask=ALL or /path/1:/path/2, or shell expanded paths (/proc/*): Paths to unmask separated by a colon. If set to ALL, it unmasks all the paths that are masked or made read-only by default. The de‐ fault masked paths are /proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux. The default paths that are read-only are /proc/asound, /proc/bus, /proc/fs, /proc/irq, /proc/sys, /proc/sysrq- trigger, /sys/fs/cgroup.-snip-
サーバのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r5.14.0-284.11.1.el9_2.x86_64
podmanパッケージをインストールします。
[root@server ~]# dnf -y install podman
podmanコマンドの版数を確認します。
[root@server ~]# podman -vpodman version 4.9.4-rhel
コンテナを起動するイメージを確認します。ここでは、almalinux イメージを使用します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/library/almalinux latest fe9652e6c62e 5 days ago 191 MB
デフォルトの状態を確認するため、--security-opt オプションを指定せずコンテナを起動します。
[user1@server ~]$ podman run -it --rm --name test1 almalinux[root@1b1a123822ef /]#
ls コマンドで /proc/scsi を確認します。マニュアルに記載されている通り、/proc/scsi はデフォルトでマスクされているため、/proc/scsi 配下には何も表示されないことが確認できます。
[root@1b1a123822ef /]# ls /proc/scsi/[root@1b1a123822ef /]#
コンテナ内でマウントしているファイルシステムを確認します。/proc/scsi には tmpfs がマウントされていることがわかります。つまり、/proc/scsi にアクセスすると、ホストのメモリを参照することになります。これにより、ホストの /proc/scsi へのアクセスが制限されていることが確認できます。
[root@c8db3cd3c364 /]# findmnt -a | grep /proc/scsi| |-/proc/scsi tmpfs tmpfs ro,relatime,context="system_u:object_r:container_file_t:s0:c63,c112",size=0k,uid=1000,gid=1000,inode64
コンテナから抜けます。
[root@c8db3cd3c364 /]# exitexit
次に、--security-opt オプションを使用して /proc/scsi をアンマスクしてみます。アンマスクを指定すると、コンテナからホストの /proc/scsi を参照できるようになります。
[user1@server ~]$ podman run -it --rm --security-opt unmask=/proc/scsi --name test1 almalinux[root@99e528143a44 /]#
lsコマンドで/proc/scsi 配下を確認すると、各種ファイルを確認することができます。
[root@326649924a35 /]# ls -l /proc/scsi/total 0-r--r--r--. 1 nobody nobody 0 Jul 28 12:35 device_info-r--r--r--. 1 nobody nobody 0 Jul 28 12:35 scsidr-xr-xr-x. 9 nobody nobody 0 Jul 28 12:35 sg
コンテナ内でマウントしているファイルシステムを確認します。/proc/scsi には tmpfsはマウントされていません。つまり、ホストの/proc/scsi を参照できることがわかります。
[root@326649924a35 /]# findmnt -a | grep /proc/scsi[root@326649924a35 /]#
コンテナから抜けます。
[root@326649924a35 /]# exitexit
コンテナに特定の仮想ファイルシステムを参照できないようにするには、マスクするパスを --security-opt オプションで指定します。例えば、コンテナから /proc/sys/net を参照できないようにする場合は、次のように実行します。
まず初期状態を確認するため、--security-opt オプションを指定せずコンテナを起動してみます。
[user1@server ~]$ podman run -it --rm --name test1 almalinux[root@96ac14e1d2a3 /]#
lsコマンドで /proc/sys/net 配下を確認してみます。
[root@96ac14e1d2a3 /]# ls -l /proc/sys/nettotal 0dr-xr-xr-x. 1 root root 0 Jul 28 12:36 coredr-xr-xr-x. 1 root root 0 Jul 28 12:36 ipv4dr-xr-xr-x. 1 root root 0 Jul 28 12:36 ipv6dr-xr-xr-x. 1 root root 0 Jul 28 12:36 mptcpdr-xr-xr-x. 1 root root 0 Jul 28 12:36 netfilterdr-xr-xr-x. 1 root root 0 Jul 28 12:36 unix
コンテナから抜けます。
[root@d42f33ba2d95 /]# exitexit
次に、--security-opt オプションを使用して /proc/sys/net をマスクしてみます。マスクを指定すると、コンテナからホストの /proc/sys/net を参照できなくなります。
[user1@server ~]$ podman run -it --rm --security-opt mask=/proc/sys/net --name test1 almalinux[root@0c40734feca6 /]#
lsコマンドで /proc/sys/net 配下を確認すると、何も表示されないことが確認できます。
[root@0c40734feca6 /]# ls -l /proc/sys/nettotal 0
コンテナから抜けます。
[root@0c40734feca6 /]# exitexit
マスク、アンマスクするパスを複数同時に指定する場合は、パスを「:」で区切ります。ここでは、コンテナからホストの以下の仮想ファイルシステムをマスクしてみます。
・/proc/sys/net/ipv4
・/proc/sys/net/ipv6
[user1@server ~]$ podman run -it --rm --security-opt mask=/proc/sys/net/ipv4:/proc/sys/net/ipv6 --name test1 almalinux
コンテナ内で /proc/sys/net/ipv4 配下を確認してみます。/proc/sys/net/ipv4 がマスクされているため、ls コマンドで /proc/sys/net/ipv4 配下を確認すると、何も表示されないことが確認できます。
[root@598c9f73964c /]# ls -l /proc/sys/net/ipv4/total 0
コンテナ内で /proc/sys/net/ipv6 配下を確認してみます。/proc/sys/net/ipv6 がマスクされているため、ls コマンドで /proc/sys/net/ipv6/ 配下を確認すると、何も表示されないことが確認できます。
[root@598c9f73964c /]# ls -l /proc/sys/net/ipv6/total 0
今回の記事執筆にあたり参考にした図書は以下のものです。
コンテナを実行する際、コンテナ内で稼働するサービスに機密情報を渡す場合があります。例えば、データベースを操作するサービスの場合、管理者ユーザー名とパスワードが必要です。これらを環境変数としてコンテナに渡すこともできますが、その場合、稼働中のコンテナのイメージをcommitすると、機密情報がイメージに書き込まれてしまいます。これを防ぐために、secretコマンドがあります。secretコマンドを使うと、機密情報をコンテナに渡しても、これらはコンテナをcommitしてもイメージに書き込まれません。そのため、イメージから機密情報を盗まれる心配がありません。
サーバのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r5.14.0-284.11.1.el9_2.x86_64
podmanパッケージをインストールします。
[root@server ~]# dnf -y install podman
podmanコマンドの版数を確認します。
[root@server ~]# podman -vpodman version 4.9.4-rhel
secret コマンドのオプション一覧は以下のとおりです。
[user1@server ~]$ podman secret --helpManage secretsDescription: Manage secretsUsage: podman secret [command]Available Commands: create Create a new secret exists Check if a secret exists in local storage inspect Inspect a secret ls List secrets rm Remove one or more secrets
秘密情報をファイルに書き込みます。
[user1@server ~]$ echo "This is my secret" > /tmp/secret
秘密情報からシークレットを作成します。
[user1@server ~]$ podman secret create my_secret /tmp/secret316775a474faa7e8fd7d02ae9
作成したシークレットを確認します。my_secret という名前のシークレットが作成できたことが確認できます。
[user1@server ~]$ podman secret lsID NAME DRIVER CREATED UPDATED316775a474faa7e8fd7d02ae9 my_secret file 30 seconds ago 30 seconds ago
シークレットを削除します。
[user1@server ~]$ podman secret rm my_secret316775a474faa7e8fd7d02ae9
シークレットを確認します。シークレットが削除されたことが確認できます。
[user1@server ~]$ podman secret lsID NAME DRIVER CREATED UPDATED
コンテナに秘密情報(IDやパスワード等)をシークレットとして渡す方法について説明します。
秘密情報(ID/パスワード)をファイルに書き込みます。
[user1@server ~]$ echo "My_ID" > /tmp/ID[user1@server ~]$ echo "My_PASS" > /tmp/PASS
秘密情報のシークレットを作成します。
[user1@server ~]$ podman secret create my_id /tmp/ID[user1@server ~]$ podman secret create my_pass /tmp/PASS
作成したシークレットを確認します。
[user1@server ~]$ podman secret lsID NAME DRIVER CREATED UPDATED7e2ee29c41b71ad99f1ae6ff8 my_pass file 3 seconds ago 3 seconds ago40e84374a2b5845bf8409aa92 my_id file 7 seconds ago 7 seconds ago
イメージ(almalinux)からコンテナ(test1 )を起動します。このとき、--secretオプションを使用して、シークレットをコンテナ内で使用できるようにします。
[user1@server ~]$ podman run -dit --secret my_id --secret my_pass --name test1 almalinux
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@e369a7f4a5ab /]#
/run/secrets 配下を確認すると、ホストからコンテナにシークレットが渡されていることがわかります。
[root@e369a7f4a5ab /]# cat /run/secrets/my_idMy_ID[root@e369a7f4a5ab /]# cat /run/secrets/my_passMy_PASS
コンテナからぬけます。
[root@e369a7f4a5ab /]# exitexit
コンテナを確認します。test1という名前のコンテナが動作していることが確認できます。
[user1@server ~]$ podman psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESe369a7f4a5ab docker.io/library/almalinux:latest /bin/bash 47 seconds ago Up 47 seconds test1
commit コマンドを実行して、コンテナをイメージ(secret_img)に保存します。
[user1@server ~]$ podman commit test1 secret_img
イメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/secret_img latest a6524b1eb359 9 seconds ago 191 MBdocker.io/library/almalinux latest 8109fa501eaf 6 weeks ago 191 MB
シークレットイメージ(secret_img)でコンテナを起動します。
[user1@server ~]$ podman run -dit --name test2 secret_img
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test2 bash[root@0b2d003707e0 /]#
コンテナを起動したイメージにシークレットが含まれないので、/run/secrets 配下にシークレットが存在しないことが確認できます。
[root@0b2d003707e0 /]# ls /run/secrets/*ls: cannot access '/run/secrets/*': No such file or directory
コンテナからぬけます。
[root@0b2d003707e0 /]# exitexit
次の検証のため、コンテナとイメージを削除します。
[user1@server ~]$ podman rm -f $(podman ps -aq)[user1@server ~]$ podman rmi -f $(podman images -q)
前回の検証でalmalinuxのイメージを削除したので、あたらめてalmalinuxイメージをダウンロードします。
[user1@server ~]$ podman pull docker.io/library/almalinux
シークレットは前回作成したものを使います。
[user1@server ~]$ podman secret lsID NAME DRIVER CREATED UPDATED40e84374a2b5845bf8409aa92 my_id file 57 minutes ago 57 minutes ago7e2ee29c41b71ad99f1ae6ff8 my_pass file 57 minutes ago 57 minutes ago
イメージからコンテナを起動します。このとき、コンテナにシークレットを環境変数(type=env)として渡します。
[user1@server ~]$ podman run -dit --secret my_id,type=env --secret my_pass,type=env --name test1 almalinux
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
コンテナで環境変数my_id、my_passの値を確認すると、環境変数に値が設定されていることが確認できます。
[root@53262a122865 /]# echo $my_idMy_ID[root@53262a122865 /]# echo $my_passMy_PASS[root@53262a122865 /]#
コンテナからぬけます。
[root@53262a122865 /]# exitexit
commit コマンドを実行して、コンテナをイメージ(secret_img)に保存します。
[user1@server ~]$ podman commit test1 secret_img
イメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/secret_img latest 9a6defa8a539 42 seconds ago 191 MBdocker.io/library/almalinux latest 8109fa501eaf 6 weeks ago 191 MB
シークレットイメージ(secret_img)でコンテナを起動します。
[user1@server ~]$ podman run -dit --name test2 secret_img
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test2 bash
コンテナを起動したイメージにシークレットが含まれないので、環境変数には値が何も設定されていないことが確認できます。
[root@eb48fee287cc /]# echo $my_id[root@eb48fee287cc /]# echo $my_pass[root@eb48fee287cc /]#
コンテナからぬけます。
[root@eb48fee287cc /]# exitexit
今回の記事執筆にあたり参考にした図書は以下のものです。
イメージの作成は、以下の方法があります。
ここでは、Containerfileを使用したイメージの作り方について説明します。Containerfileでイメージを作成する際には、buildコマンドを使用します。書式は以下の通りです。
$ podman build -t Podmanイメージ名 Containerfile格納ディレクトリ
サーバのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r5.14.0-284.11.1.el9_2.x86_64
podmanパッケージをインストールします。
[root@server ~]# dnf -y install podman
podmanコマンドの版数を確認します。
[root@server ~]# podman -vpodman version 4.9.4-rhel
ディレクティブとは、Containerfile内に記述するコマンドのことです。ディレクティブを使用すると、コンテナにソフトウェアをインストールしたり、ホストのファイルをコンテナ内にコピーしたりすることができます。
ディレクティブ | 概要 |
---|---|
FROM | ベースとなるコンテナイメージを指定します |
COPY | ホストのファイル、ディレクトリ、URLをコンテナにコピーします。ADD と異なる点は、リモートURL の指定不可、アーカイブファイルを自動で展開しません |
ADD | ホストのファイル、ディレクトリ、URLをコンテナにコピーします。ADDはCOPYに比べ多機能ですが、シンプルなコピーにはCOPYを使うことが推奨されているようです |
RUN | イメージのビルド中に実行するコマンドを指定します。具体的には、イメージの構築に必要なソフトウェアのインストール、設定変更、ファイルのダウンロードなどを行うことができます |
ENTRYPOINT | コンテナが起動したときに実行されるメインプロセスを指定するために使用します |
CMD | コンテナが起動するときに実行するコマンドのデフォルトのパラメータを指定します |
EXPOSE | コンテナがパケットを待ち受けるポート番号を指定するために使用します。パケットはlistenシステムコールを実行して待ち受けます |
ENV | コンテナ内で環境変数を設定するために使用します。これにより、コンテナ内のプロセスが利用する環境変数を定義できます。ENV ディレクティブで設定した環境変数は、結果として作成されたイメージから実行したコンテナでも維持されます |
LABEL | イメージに任意のラベル(キー・バリュー形式で指定)を付けるために使用します。ラベルは、プロジェクトでイメージを管理するために使用しま。例えば、誰が作成したイメージなのかといった情報をイメージに付けることができます |
WORKDIR | コンテナ内の作業ディレクトリを変更するために使用します |
USER | USERディレクティブで指定したユーザー権限でコンテナ内のプロセスやコマンドを実行します |
イメージの初期状態を確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZE
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
[user1@server ~]$ vi Containerfile[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinux
イメージをビルドします。-t(タグ)オプションは、ビルドするイメージの名前(test_image)を指定します。最後に指定するパラメータは、Containerfile を格納したディレクトリを示します。ここではピリオド(.)を指定しているため、podman コマンドを実行する場所と同じディレクトリに Containerfile があることを意味しています。
[user1@server ~]$ podman build -t test_image .STEP 1/1: FROM docker.io/library/almalinuxTrying to pull docker.io/library/almalinux:latest...Getting image source signaturesCopying blob 587e68e1d836 done |Copying config 8109fa501e done |Writing manifest to image destinationCOMMIT test_image--> 8109fa501eafSuccessfully tagged localhost/test_image:latestSuccessfully tagged docker.io/library/almalinux:latest8109fa501eaf5af622946e7c5c033cb7aef816c3267b1c17c7b62b34fea099a5
イメージを確認すると、イメージ(test_image)が作成されたことがわかります。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/test_image latest 8109fa501eaf 5 weeks ago 191 MBdocker.io/library/almalinux latest 8109fa501eaf 5 weeks ago 191 MB
次の検証のため、イメージを削除します。
[user1@server ~]$ podman rmi -f $(podman images -q)
ホストからコンテナにコピーするファイルを作成します。
[user1@server ~]$ vi test.sh[user1@server ~]$ cat test.txt12345
作成したファイルの所有者と所有グループを確認します。ホスト環境では、user1 でファイルを作成しているため、所有者および所有グループが user1 になっていることが確認できます。
[user1@server ~]$ ls -l test.txt-rw-r--r--. 1 user1 user1 6 7月 8 20:20 test.txt
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・ホストで作成したファイル(test.txt)をコンテナの /tmpにコピーする(COPY )
[user1@server ~]$ vi Containerfile[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxCOPY test.txt /tmp
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/test_image latest 4d4957e1ef46 2 seconds ago 191 MBdocker.io/library/almalinux latest 8109fa501eaf 6 weeks ago 191 MB
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_imagece501fb90adaa9828d45f3ad02fb2e24b242048228f42dbc095cfb4fa1265fcc
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@ce501fb90ada /]#
ホストからコンテナにコピーしたファイルを確認します。ファイルの所有者、所有グループはrootになっています。ファイルの所有者、所有グループの変更方法は後述します。
[root@ce501fb90ada /]# ls -l /tmp/test.txt-rw-r--r--. 1 root root 6 Jul 8 11:20 /tmp/test.txt
コンテナからぬけます。
[root@ce501fb90ada /]# exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
次は、コンテナ内にコピーしたファイルの所有者、所有グループをuser1に変更してみます。
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxRUN adduser user1COPY test.txt /tmpRUN chown user1:user1 /tmp/test.txt
コンテナを起動してファイル(/tmp/test.txt)の所有者および所有グループを確認すると user1 に変更されていることが確認できます。
[root@45abd84d6676 /]# ls -l /tmp/test.txt-rw-r--r--. 1 user1 user1 6 Jul 8 11:20 /tmp/test.txt
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
(1) 事前準備(圧縮ファイルの作成)
テスト用のファイルを作成します。
[user1@server ~]$ vi test.txt[user1@server ~]$ cat test.txt12345
テスト用の圧縮ファイルを作成します。
[user1@server ~]$ tar -zcvf test.tar.gz test.txttest.txt
(2) ADDディレクティブの動作確認
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・ホストで作成した圧縮ファイル(test.tar.gz )を解凍してコンテナの/tmpにコピーする(ADD)
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxADD test.tar.gz /tmp/
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image23fb9dc21856fd4dec4d02f1310a74d02468213c456dc66dd270bd39ed3b43ca
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@23fb9dc21856 /]#
ADD ディレクティブは圧縮ファイルを解凍してコンテナにコピーするため、ホストで作成した圧縮ファイルがコンテナ内で解凍されることが確認できます。
[root@23fb9dc21856 /]# cat /tmp/test.txt12345
コンテナからぬけます。
[root@23fb9dc21856 /]# exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
ホストでテスト用のディレクトリ、ファイルを作成します。
[user1@server ~]$ mkdir host_dir[user1@server ~]$ echo "12345" > host_dir/test1.txt[user1@server ~]$ echo "67890" > host_dir/test2.txt
Containerfileを使って、次の内容のイメージを作成します。
・(FROM )
・ホストで作成したディレクトリ(host_dir )をコンテナの/tmpにコピーする(ADD)
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxADD host_dir /tmp
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_imageba931b22c906117c514d604b1a556cbc933665b4e39e3500d8e081a0b0c37183
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@ba931b22c906 /]#
コンテナで/tmp配下のファイルを確認します。ホストのhost_dir 配下に作成したファイルがコンテナの/tmp配下にコピーされていることが確認できます。
[root@ba931b22c906 /]# ls -l /tmp/*-rw-r--r--. 1 root root 6 Jul 14 00:24 /tmp/test1.txt-rw-r--r--. 1 root root 6 Jul 14 00:24 /tmp/test2.txt
コンテナからぬけます。
[root@ba931b22c906 /]# exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・iprouteパッケージをイメージにインストールする(RUN )
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxRUN dnf -y install iproute
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/test_image latest f28aa2f7799c 54 seconds ago 238 MBdocker.io/library/almalinux latest 8109fa501eaf 5 weeks ago 191 MB
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_imagedb3023492a4caf5ce9b0b653bc5b2ecb6cba5065ccf68de12e6ed268bc44631c
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@db3023492a4c /]#
コンテナでパッケージを確認すると、iprouteパッケージがインストールされていることが確認できます。
[root@db3023492a4c /]# rpm -qa|grep iprouteiproute-6.2.0-6.el9_4.x86_64
コンテナからぬけます。
[root@db3023492a4c /]# exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
Dockerfile リファレンス — Docker-docs-ja 24.0 ドキュメントによると、ENTRYPOINTディレクティブは以下の書式があります。 exec 形式が推奨されているようです。ここでも、ディレクティブはexec 形式を使用します。
ENTRYPOINT ["実行ファイル", "パラメータ1", "パラメータ2"]
ENTRYPOINT コマンド パラメータ1 パラメータ2
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・コンテナ起動時に実行するプログラムを指定する(ENTRYPOINT )
・ENTRYPOINT で指定するコマンドのパラメータを指定する(CMD )
[user1@server ~]$ vi Containerfile[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxENTRYPOINT ["ping","-c","1"]CMD ["example.com"]
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
もう1つターミナルを開いてtcpdumpを実行します。-iはインタフェース名を指定します。お使いの環境に合わせて適宜変更してください。なお。、tcpdumpの詳細な使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# tcpdump -i enp1s0 icmp -n
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run --name test1 test_image
tcpdumpの実行結果を確認すると、example.com(93.184.215.14)宛てのping実行結果が確認できます。
[root@server ~]# tcpdump -i enp1s0 icmp -n22:21:10.429828 IP 192.168.122.87 > 93.184.215.14: ICMP echo request, id 20, seq 1, length 6422:21:10.524670 IP 93.184.215.14 > 192.168.122.87: ICMP echo reply, id 20, seq 1, length 64
digコマンドで確認すると、example.comのIPアドレスは93.184.215.14であることが確認できます。なお、digコマンドの使い方は、digコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# dig example.com +short93.184.215.14
次の検証のため、コンテナを削除します。
[user1@server ~]$ podman rm test1 --force
次に、コンテナ起動時にパラメータを明示的に指定します。指定するパラメータは、デフォルトゲートウェイのIPアドレス(192.168.122.1)です。
[user1@server ~]$ podman run --name test1 test_image 192.168.122.1
tcpdumpの実行結果を確認すると、example.comに対するpingの結果ではなく、デフォルトゲートウェイのIPアドレス(192.168.122.1)に対するpingの結果であることが確認できます。つまり、CMDで指定したパラメータがコンテナ起動時に指定したパラメータで上書きされたことがわかります。
[root@server ~]# tcpdump -i enp1s0 icmp -n22:27:21.353640 IP 192.168.122.87 > 192.168.122.1: ICMP echo request, id 24, seq 1, length 6422:27:21.353973 IP 192.168.122.1 > 192.168.122.87: ICMP echo reply, id 24, seq 1, length 64
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・コンテナのhttpdが80番ポートでリッスンする(EXPOSE )
[user1@server ~]$ vi Containerfile[user1@server ~]$ cat ContainerfileFROM httpd:latestEXPOSE 80
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
作成したイメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/test_image latest 72416f67c6ae 36 seconds ago 152 MBdocker.io/library/httpd latest c0c20df5e7be 5 days ago 152 MB
ビルドしたイメージ(test_image)からコンテナを起動します。このとき、-pオプションを使って、ホストの8080番ポートへのアクセスをコンテナの80番ポートにマッピングします。
[user1@server ~]$ podman run -d -p 8080:80 --name test1 test_image1f8a374faf80f2bd28b48710de04b74f8d2cdc2ef98489f4e6d027136fc271d4
ポートのマッピングを確認します。ホストの任意(0.0.0.0)のIPアドレスに対する8080番ポートへのアクセスが、コンテナの80番ポートへのアクセスに変換されることが確認できます。
[user1@server ~]$ podman port test180/tcp -> 0.0.0.0:8080
curlコマンドを実行してホストの8080番ポートにアクセスしてみます。コンテナのhttpdからの応答を確認することができます。
[user1@server ~]$ curl http://localhost:8080<html><body><h1>It works!</h1></body></html>
コンテナからぬけます。
[root@db3023492a4c /]# exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・環境変数(TEST)に文字列("Hello, World!")を設定する(ENV )
・環境変数に設定した文字列をechoコマンドで出力する(CMD )
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxENV TEST="Hello, World!"CMD echo $TEST
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。コンテナを起動する際に、環境変数TESTに設定した文字列が出力されることを確認できます。
[user1@server ~]$ podman run --name test1 test_imageHello, World!
あと始末をします。
[user1@server ~]$ podman rm test1test1
コンテナを実行する際に、設定された環境変数を上書きすることもできます。例えば、環境変数TESTに"bye"を設定してコンテナを起動してみます。この場合、コンテナが起動する際に、”Hello, World!”ではなく"bye"が出力されることを確認できます。
[user1@server ~]$ podman run -e TEST=bye --name test1 test_imagebye
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・イメージにラベルをつける(LABEL )。ラベルの内容は、作成者(maintainer)、イメージのバージョン(version)、イメージの作成日(2024/7/10)
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxLABEL maintainer="hana_shin@example.com"LABEL version="1.0"LABEL created="2024-07-10"
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
Podmanのinspectコマンドとjqコマンドを併用して、イメージに付けたラベルを確認してみます。なお、io.buildah.versionはBuildahのバージョン情報を示しており、ビルドツールが自動的に追加するものです。
[user1@server ~]$ podman inspect test_image --format '{{json .Config.Labels}}' | jq{ "created": "2024-07-10", "io.buildah.version": "1.33.7", "maintainer": "hana_shin@example.com", "version": "1.0"}
次の検証のため、イメージを削除します。
[user1@server ~]$ podman rmi -f $(podman images -q)
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・作業ディレクトリを /etc に変更する(WORKDIR )
・ファイル(test.conf)に文字列を書き込む(RUN )
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxWORKDIR /etcRUN echo "Hello" > test.conf
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image734466e173c07719688d9deb0304eacc4ece68bdb3cbc58685b47954142c8eae
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@734466e173c0 etc]#
作業ディレクトリを確認すると /etc であることが確認できます。
[root@734466e173c0 etc]# pwd/etc
ファイル(test.conf)に書き込んだ内容を確認すると、"Hello"であることが確認できます。
[root@734466e173c0 etc]# cat test.confHello
コンテナからぬけます。
[root@734466e173c0 etc]# exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・ユーザー(user2)を作成する(RUN )
・実行ユーザーをuser2に変更する(USER )
・作業ディレクトリを/home/user2に変更する(USER )
[user1@server ~]$ cat ContainerfileFROM docker.io/library/almalinuxRUN adduser user2USER user2WORKDIR /home/user2
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_imageae3345f70a53062894ff5b050ff48fe7225553d0799d97f2e38baddee92a1692
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash[user2@ae3345f70a53 ~]$
idコマンドを使用してユーザー名を確認してみます。ユーザ名がuser2であることが確認できます。
[user2@ae3345f70a53 ~]$ iduid=1000(user2) gid=1000(user2) groups=1000(user2)
次に、pwdコマンドを使用して現在の作業ディレクトリを確認すると、作業ディレクトリが/home/user2であることが確認できます。
[user2@ae3345f70a53 ~]$ pwd/home/user2
コンテナからぬけます。
[user2@ae3345f70a53 ~]$ exitexit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force[user1@server ~]$ podman rmi -f $(podman images -q)
今回の記事執筆にあたり参考にした図書は以下のものです。
サーバのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r5.14.0-284.11.1.el9_2.x86_64
SELinuxは有効にしておきます。
[root@server ~]# getenforceEnforcing
podmanパッケージをインストールします。
[root@server ~]# dnf -y install podman
podmanコマンドの版数を確認します。
[root@server ~]# podman -vpodman version 4.9.4-rhel
テスト用のユーザを作成します。
[root@server ~]# useradd user1
user1のパスワードを設定します。
[root@server ~]# passwd user1
以降の作業は、一般ユーザで実行します。
[user1@server ~]$ iduid=1000(user1) gid=1000(user1) groups=1000(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
almalinuxイメージをダウンロードします。
[user1@server ~]$ podman pull almalinux
ダウンロードしたイメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/library/almalinux latest 8109fa501eaf 4 weeks ago 191 MB
コンテナとホストの間でファイルをコピーする方法について説明します。
書式は以下のとおりです。
$ podman cp ホスト側パス コンテナ名:コンテナ側パス
$ podman cp コンテナ名:コンテナ側パス ホスト側パス
test1という名前のコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 almalinux06ed782d14df2a869b2a3b10eaee8a59c1e55a28f834ad7c4836eebed4bd222c
起動したコンテナを確認します。
[user1@server ~]$ podman psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES06ed782d14df docker.io/library/almalinux:latest /bin/bash 11 seconds ago Up 11 seconds test1
コンテナにコピーするファイルを作成します。
[user1@server ~]$ echo "test" > test.txt[user1@server ~]$ cat /home/user1/test.txttest
ファイルをコンテナの/tmpにコピーします。
[user1@server ~]$ podman cp /home/user1/test.txt test1:/tmp
コンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@06ed782d14df /]#
コピーしたファイルを確認します。ホストで作成したファイルがコンテナにコピーできていることが確認できます。
[root@06ed782d14df /]# cat /tmp/test.txttest
ホストにコピーするファイルを作成します。
[root@06ed782d14df /]# echo "12345" > /tmp/test.txt
作成したファイルの中身を確認します。
[root@06ed782d14df /]# cat /tmp/test.txt12345
コンテナから抜けます。
[root@06ed782d14df /]# exitexit
コンテナの /tmp/test.txt をホストの /home/user1/test2.txt にコピーします。
[user1@server ~]$ podman cp test1:/tmp/test.txt /home/user1/test2.txt
コピーしたファイルを確認します。コンテナで作成したファイルがホストにコピーできていることが確認できます。
[user1@server ~]$ cat /home/user1/test2.txt12345
ボリュームやファイル/ディレクトリのマウントについて説明します。
マウント方法 | 概要 |
---|---|
ボリュームマウント | ボリュームとは、ハードディスクの1つの領域です。作成したボリュームをコンテナ内にマウントする方法です。これにより、データを永続的に保存することができます。例えば、コンテナが削除されたり再起動されたりしても、ボリュームに保存されたデータは失われません。ボリュームは、コンテナ間でデータを共有するためにも使用されます。 |
バインドマウント | ホストの特定のファイルやディレクトリをコンテナ内にマウントする方法です。これにより、ホスト上のデータをコンテナ内から直接アクセスすることができます |
ボリューム(vol1)を作成します。
[user1@server ~]$ podman volume create vol1vol1
作成したボリュームを確認します。vol1という名前のボリュームが作成されたことがわかります。
[user1@server ~]$ podman volume lsDRIVER VOLUME NAMElocal vol1
コンテナ(test1)を起動します。このとき、作成したボリューム(vol1)をコンテナの/mntにマウントします。
[user1@server ~]$ podman run -dit --name test1 -v vol1:/mnt docker.io/library/almalinuxefe1bcf540fc2e947b1f22028b7a297798eccd3934951a0c76de55c2995ba5d1
起動したコンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@efe1bcf540fc /]#
マウントしたボリュームにファイルを作成します。
[root@efe1bcf540fc /]# echo "12345" > /mnt/file1.txt[root@efe1bcf540fc /]# cat /mnt/file1.txt12345
コンテナからぬけます。
[root@efe1bcf540fc /]# exitexit
コンテナ(test2)を起動します。このとき、作成したボリューム(vol1)をコンテナの/mntにマウントします。
[user1@server ~]$ podman run -dit --name test2 -v vol1:/mnt docker.io/library/almalinux2f54ed031bcae970db373f2a5e479db34e6f588c4a5b1ae179f60bfdfbffef5f
起動したコンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test2 bash[root@2f54ed031bca /]#
マウントしたボリューム内のファイルの内容を確認します。このファイルはtest1コンテナで作成されたものですが、test2コンテナでもその内容を参照できることが確認できます。
[root@2f54ed031bca /]# cat /mnt/file1.txt12345
コンテナからぬけます。
[root@2f54ed031bca /]# exitexit
コンテナを削除します。
[user1@server ~]$ podman rm test1 test2 --force
作成したボリュームを削除します。
[user1@server ~]$ podman volume rm vol1vol1
SELinuxが有効な場合、マウントしたボリュームやファイルにアクセスできません。マウントする際、状況に応じて z(小文字)または Z(大文字)を指定する必要があります。これらのオプションを指定すると、PodmanがボリュームやファイルのSELinuxコンテキストを再ラベルします。これにより、コンテナがマウントしたボリュームやファイルにアクセスできるようになります。
オプション | 概要 |
---|---|
z(小文字) | 複数のコンテナでボリュームやファイルを共有する場合 |
Z(大文字) | 他のコンテナとボリュームやファイルを共有しない場合 |
podman-run — Podman documentationよりオプションの説明を以下に引用します。
To change a label in the container context, add either of two suffixes :z or :Z to the volume mount. These suffixes tell Podman to relabel file objects on the shared volumes. The z option tells Podman that two or more containers share the volume content. As a result, Podman labels the content with a shared content label. Shared volume labels allow all containers to read/write content. The Z option tells Podman to label the content with a private unshared label Only the current container can use a private volume. Relabeling walks the file system under the volume and changes the label on each file, if the volume has thousands of inodes, this process takes a long time, delaying the start of the container. If the volume was previously relabeled with the z option, Podman is optimized to not relabel a second time. If files are moved into the volume, then the labels can be manually change with the chcon -Rt container_file_t PATH command.
コンテナがマウントするディレクトリを作成します。
[root@server ~]# mkdir /host_dir
作成したディレクトリの所有者(ユーザ、グループ)をrootからuser1に変更します。
[root@server ~]# chown user1:user1 /host_dir/
ディレクトリの所有者(ユーザ、グループ)を確認します。所有者がuser1に変更されたことがわかります。また、/host_dirのコンテキストは以下のようになっています。
[root@server ~]# ls -ldZ /host_dirdrwxr-xr-x. 2 user1 user1 unconfined_u:object_r:default_t:s0 6 7月 7 22:50 /host_dir
マウントするディレクトリにファイルを作成します。
[user1@server ~]$ echo "12345" > /host_dir/test.txt[user1@server ~]$ cat /host_dir/test.txt12345
コンテナを起動します。このとき、大文字のZを指定して、マウントするディレクトリを他のコンテナと共有しないようにしてみます。
[user1@server ~]$ podman run --name test1 -dit -v /host_dir:/var:Z docker.io/library/almalinux:latest265a303d3dcf22b80d21f90b34d5f283fcf40db273fb71a209588c7c37278c2e
起動したコンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test1 bash[root@265a303d3dcf /]#
マウントしたディレクトリのファイルの中身を確認します。
[root@265a303d3dcf /]# cat /var/test.txt12345
コンテナからぬけます。
[root@265a303d3dcf /]# exitexit
あと始末をします。
[user1@server ~]$ podman rm test1 --force
マウントしたディレクトリのSELinuxコンテキストを確認します。コンテキストのタイプがdefault_tからcontainer_file_tに変更されていることがわかります。これは、Zオプションを付けることで、コンテナが/host_dirにアクセスできるように、ディレクトリのコンテキストタイプがdefault_tからcontainer_file_tに変更されたためです。
[user1@server ~]$ ls -ldZ /host_dirdrwxr-xr-x. 2 user1 user1 system_u:object_r:container_file_t:s0:c168,c334 22 7月 7 22:53 /host_dir
タイプを元のdefault_t に戻す場合は、以下のようにchconコマンドを実行します。
[user1@server ~]$ chcon -t default_t /host_dir
ディレクトリのSELinuxコンテキストを確認します。コンテキストのタイプがdefault_tに戻ったことがわかります。
[user1@server ~]$ ls -ldZ /host_dir/drwxr-xr-x. 2 user1 user1 system_u:object_r:default_t:s0:c168,c334 22 7月 7 22:53 /host_dir/
イメージを作成する方法は2つあります。
1. podman commitコマンドでコンテナをイメージに書き出す方法
2. Containerfileからイメージを作成する方法
ここでは、1について説明します。2については別の記事で説明します。
イメージを確認します。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/library/almalinux latest 8109fa501eaf 4 weeks ago 191 MB
イメージ(almalinux)からコンテナ(test1)を起動します。
[user1@server ~]$ podman run -dit --name test1 almalinux9bfd0427bbdd1482f17ea78a9b717b9b3e6f86298c924ae4d99508ad0b2d118c
コンテナ(test1)に入り、bashシェルを起動します。
[user1@server ~]$ podman exec -it test1 bash[root@9bfd0427bbdd /]#
ipコマンドの版数を確認してみます。しかし、イメージ(almalinux)にはipコマンドが入っていないので、エラーになります。
[root@9bfd0427bbdd /]# ip -Vbash: ip: command not found
dnfコマンドを実行して、iprouteパッケージをインストールします。
[root@9bfd0427bbdd /]# dnf -y install iproute
ipコマンドの版数を確認します。
[root@9bfd0427bbdd /]# ip -Vip utility, iproute2-6.2.0, libbpf 1.3.0
コンテナから抜けます。
[root@9bfd0427bbdd /]# exitexit
もう1つターミナルを開いて、コンテナをイメージ(test-ip)に書き出します。
[user1@server ~]$ podman commit test1 test1-ipGetting image source signaturesCopying blob 926bdaa81747 skipped: already existsCopying blob 878b4f5d7422 done |Copying config f88cafa116 done |Writing manifest to image destinationf88cafa116a62a69141aed482e81a49280712084662cb5a4176202c5940231b1
イメージを確認すると、test1-ipという名前のイメージが作成できたことがわかります。
[user1@server ~]$ podman imagesREPOSITORY TAG IMAGE ID CREATED SIZElocalhost/test1-ip latest f88cafa116a6 About a minute ago 238 MBdocker.io/library/almalinux latest 8109fa501eaf 4 weeks ago 191 MB
イメージ(test1-ip)からコンテナ(test2)を起動します。
[user1@server ~]$ podman run -dit --name test2 test1-ipfe5e178feca69b92b753d7f7b3963080fdfb55792f5003e5de3a48c0fb3c1cd9
コンテナ(test2)に入り、bashシェルを起動します。
[user1@server ~]$ podman exec -it test2 bash[root@fe5e178feca6 /]#
ipコマンドのバージョンを確認します。イメージ(test1-ip)には最初からipコマンドが含まれているため、ipコマンドのバージョン確認をしてもエラーにならないことが確認できます。
[root@fe5e178feca6 /]# ip -Vip utility, iproute2-6.2.0, libbpf 1.3.0
今回の記事執筆にあたり参考にした図書は以下のものです。
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ
以下の項目について、コンテナに関する記事を作成しました。
ホストのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-releaseAlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r5.14.0-284.11.1.el9_2.x86_64
レジストリは、コンテナイメージを保存し配布する場所です。レジストリの中には複数のリポジトリがあり、それぞれのリポジトリでコンテナイメージを管理します。
レジストリ | 概要 |
---|---|
registry.access.redhat.com | Red Hat社が提供するレジストリです。レジストリを利用するさい、認証は不要です |
registry.redhat.io | Red Hat社が提供するレジストリです。レジストリを利用するさい、認証が必要です。あらかじめRedHatのアカウントを持っている必要があります。Red Hat社 の配布するコンテナーイメージは registry.redhat.io に移行しつつあるようです |
registry.connect.redhat.com | Red Hat社が提供するサードパーティ製品のレジストリです。レジストリを利用するさい、認証が必要です。あらかじめRedHatのアカウントを持っている必要があります |
docker.io | Docker社が提供するレジストリです |
quay.io | CoreOSによって開発されました。CoreOSは後にRed Hatによって買収され、現在はRed Hatが運営されています |
コンテナのイメージ名は以下の呼び方があります。
名前 | 概要 |
---|---|
FQIN(Fully Qualified Image Name) | レジストリ名/リポジトリ名/イメージ名で指定する名前です |
短縮名 | イメージ名で指定する名前です |
短縮名は以下のファイルに定義されています。例えば、短縮名 "almalinux" は、FQINでは "docker.io/library/almalinux" となります。
[root@server ~]# cat /etc/containers/registries.conf.d/000-shortnames.conf[aliases] # almalinux "almalinux" = "docker.io/library/almalinux" "almalinux-minimal" = "docker.io/library/almalinux-minimal"-snip-
短縮名(almalinux)を使ってイメージをダウンロードしてみます。ダウンロード中の様子を確認すると、1行目で短縮名をFQINに変換している旨が表示されているのがわかります。そして、2行目でFQINを指定してイメージをダウンロードしていることがわかります。
[root@server ~]# podman pull almalinuxResolved "almalinux" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)Trying to pull docker.io/library/almalinux:latest...Getting image source signaturesCopying blob 5f50a3278457 skipped: already existsCopying config ac7ec62599 done |Writing manifest to image destinationac7ec6259981906060844582e873ea43f41c6045fdbd8969d22bb6f0ec044219
ダウンロードしたイメージを確認すると、イメージの名前が FQIN であることがわかります。
[root@server ~]# podman imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/library/almalinux latest ac7ec6259981 3 weeks ago 191 MB
registries.conf の注意事項には、短縮名を使用すると偽装されたイメージをダウンロードする可能性があることが述べられています。そのため、短縮名ではなくFQINの使用が推奨されています。さらに、イメージをハッシュ値でダウンロードすることで、偽装されたイメージではなく、意図したイメージを確実にダウンロードすることができます。
[root@server ~]# cat /etc/containers/registries.conf# NOTE: RISK OF USING UNQUALIFIED IMAGE NAMES# We recommend always using fully qualified image names including the registry# server (full dns name), namespace, image name, and tag# (e.g., registry.redhat.io/ubi8/ubi:latest). Pulling by digest (i.e.,# quay.io/repository/name@digest) further eliminates the ambiguity of tags.# When using short names, there is always an inherent risk that the image being# pulled could be spoofed. For example, a user wants to pull an image named-snip
Podmanには、イメージの格納場所を検索する際のデフォルトのレジストリが定義されています。ただし、この定義はPodmanをパッケージ化したディストリビューションによって異なります。Podman infoコマンドを使用すると、以下の3つのレジストリがイメージの検索対象であることがわかります。
[root@server ~]# podman info-snip-registries: search: - registry.access.redhat.com - registry.redhat.io - docker.io
jqコマンドを使用して、Podmanに設定されているレジストリのリストを表示してみます。
[root@server ~]# podman info --format json | jq '.registries'{ "search": [ "registry.access.redhat.com", "registry.redhat.io", "docker.io" ]}
なお、デフォルトで検索するレジストリは、registries.confに定義されていることが確認できます。
[root@server ~]# cat /etc/containers/registries.conf-snip-unqualified-search-registries = ["registry.access.redhat.com", "registry.redhat.io", "docker.io"]
registry.redhat.ioからイメージをダウンロードする場合、ID/パスワードによるユーザ認証が必要になります。
以下のページにアクセスしてアカウントを作成します。ここで作成したアカウントは、registry.redhat.ioとregistry.connect.redhat.comの両方に使用できます。
https://sso.redhat.com/auth/realms/redhat-external/login-actions/registration?client_id=customer-portal&tab_id=c1freLsJpuA
レジストリ(registry.redhat.io)に存在するrsyslogイメージを検索してみます。この中から、rhel9リポジトリのrsyslogイメージをダウンロードしてみます(下記1行目のイメージ)。
[root@server ~]# podman search registry.redhat.io/rsyslogNAME DESCRIPTIONregistry.redhat.io/rhel9/rsyslog rhcc_registry.access.redhat.com_rhel9/rsyslo...registry.redhat.io/rhel7/rsyslog A containerized version of the rsyslog utili...registry.redhat.io/rhel8/rsyslog Rocket Fast System For Log Processing (rsysl...registry.redhat.io/rhosp-rhel8/openstack-rsyslog openstack-rsyslogregistry.redhat.io/rhosp-beta/openstack-rsyslog openstack-rsyslogregistry.redhat.io/rhosp-rhel8/openstack-rsyslog-base openstack-rsyslog-baseregistry.redhat.io/rhosp-dev-preview/openstack-rsyslog-rhel9 Red Hat Red Hat OpenStack image for openstac...registry.redhat.io/rhosp-rhel9/openstack-rsyslog rhcc_registry.access.redhat.com_rhosp-rhel9/...registry.redhat.io/rhoso-beta/openstack-rsyslog-rhel9 Red Hat Red Hat OpenStack Services on OpenSh...
rhel9のリポジトリからrsyslogイメージをダウンロードしようとしましたが、レジストリ(registry.redhat.io)にログインしていないため、認証に失敗し、イメージをダウンロードできませんでした。
[root@server ~]# podman pull registry.redhat.io/rhel9/rsyslogTrying to pull registry.redhat.io/rhel9/rsyslog:latest...Error: initializing source docker://registry.redhat.io/rhel9/rsyslog:latest: unable to retrieve auth token: invalid username/password: unauthorized: Please login to the Red Hat Registry using your Customer Portal credentials. Further instructions can be found here: https://access.redhat.com/RegistryAuthentication
レジストリ(registry.redhat.io)にログインします。
[root@server ~]# podman login registry.redhat.ioUsername: test_userPassword:Login Succeeded!
rhel9リポジトリからrsyslogイメージをダウンロードします。今回は、イメージをダウンロードすることができました。
[root@server ~]# podman pull registry.redhat.io/rhel9/rsyslogTrying to pull registry.redhat.io/rhel9/rsyslog:latest...Getting image source signaturesChecking if image destination supports signaturesCopying blob 7de73bed2a9f done |Copying blob edab65b863ae done |Copying config e3197b3b88 done |Writing manifest to image destinationStoring signaturese3197b3b884c5cd6b32a39801f1c21965cbbee63adc46df86ec8a56553a20f14
ダウンロードしたイメージを確認します。rhel9リポジトリからrsyslogイメージの最新版がダウンロードされたことが確認できます。
[root@server ~]# podman images rsyslogREPOSITORY TAG IMAGE ID CREATED SIZEregistry.redhat.io/rhel9/rsyslog latest e3197b3b884c 2 weeks ago 243 MB
レジストリ(registry.redhat.io)からログアウトします。
[root@server ~]# podman logout registry.redhat.ioRemoved login credentials for registry.redhat.io
今回の記事執筆にあたり参考にした図書は以下のものです。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。