Overview
Podman の基本的な使い方を記載します。Docker とかなり似ていますので、あまり迷うことはないでしょう。
コンテナイメージ
コンテナイメージに関する操作です。
docker search
入手可能なコンテナイメージを確認するには podman search を使用します。下記の例ではキーワードとして docker.io/nginx を指定しています。Docker はデフォルトのレジストリが Docker Hub になっているため、イメージ名だけで検索結果が出力されますが、Podman のレジストリ設定ファイルである /etc/containers/registries.conf は全てコメントアウトされており、/etc/containers/registries.conf.d/shortnames.conf で定義されているイメージのみがレジストリの指定なしに検索できるようになっています。nginx は shortnames.conf で定義されていないため、レジストリを明示的に指定する必要があります。shortnames.conf を確認すると分かりますが、例えば centos のレジストリは quay.io が指定されているなど、OS 毎に適切(正式)なレジストリが定義されているようです。また OS イメージだけの定義であり、ミドルウェア単位の定義はされていません。
myadmin@ubuntu:~$ podman search docker.io/nginx
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/library/nginx Official build of Nginx. 18732 [OK]
docker.io docker.io/library/unit Official build of NGINX Unit: Universal Web ... 6 [OK]
docker.io docker.io/nginxproxy/nginx-proxy Automated Nginx reverse proxy for docker con... 92
docker.io docker.io/nginxproxy/acme-companion Automated ACME SSL certificate generation fo... 116
docker.io docker.io/bitnami/nginx Bitnami nginx Docker Image 168 [OK]
docker.io docker.io/bitnami/nginx-ingress-controller Bitnami Docker Image for NGINX Ingress Contr... 29 [OK]
docker.io docker.io/ubuntu/nginx Nginx, a high-performance reverse proxy & we... 96
docker.io docker.io/nginxproxy/docker-gen Generate files from docker container meta-da... 12
docker.io docker.io/kasmweb/nginx An Nginx image based off nginx:alpine and in... 6
docker.io docker.io/rancher/nginx-ingress-controller 11
docker.io docker.io/rancher/nginx-ingress-controller-defaultbackend 2
docker.io docker.io/bitnami/nginx-exporter 5
docker.io docker.io/rancher/nginx 2
docker.io docker.io/rapidfort/nginx-ib RapidFort optimized, hardened image for NGIN... 10
docker.io docker.io/rapidfort/nginx RapidFort optimized, hardened image for NGIN... 14
docker.io docker.io/vmware/nginx-photon 1
docker.io docker.io/rapidfort/nginx-official RapidFort optimized, hardened image for NGIN... 10
docker.io docker.io/nginxproxy/forego Foreman in Go 0
docker.io docker.io/vmware/nginx 2
docker.io docker.io/rancher/nginx-conf 0
docker.io docker.io/linuxserver/nginx An Nginx container, brought to you by LinuxS... 204
docker.io docker.io/bitnamicharts/nginx 0
docker.io docker.io/privatebin/nginx-fpm-alpine PrivateBin running on an Nginx, php-fpm & Al... 76 [OK]
docker.io docker.io/elestio/nginx-auto-ssl The simpliest solution to add SSL cert to yo... 0
docker.io docker.io/rancher/nginx-ssl 0
podman pull
コンテナイメージをダウンロードするには podman pull を使用します。下記の例では nginx をダウンロードしています。この例ではタグに latest を指定していますが、タグが未指定の場合でも latest になります。
myadmin@ubuntu:~$ podman pull docker.io/library/nginx:latest
podman images
ローカルに存在するコンテナイメージを表示するには podman images を使用します。前のコマンドでnginxをダウンロードしている為、それが表示されています。
myadmin@ubuntu:~$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest 2002d33a54f7 4 days ago 196 MB
podman image inspect
コンテナイメージの詳細を確認するには podman image inspect を使用します。出力は省略しますが、主に Env, Entrypoint, Cmd 等が確認個所になると思います。
myadmin@ubuntu:~$ podman image inspect docker.io/library/nginx
podman rmi
コンテナイメージを削除するには podman rmi を使用します。稀に依存関係で削除できない場合もありますが、-f オプションで強制削除が可能です。
myadmin@ubuntu:~$ podman rmi docker.io/library/nginx myadmin@ubuntu:~$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE
Pod
Podman の Docker との主な違いとして、Pod の有無があります(Docker に Pod の概念は存在しない)。Pod はコンテナの集合体であり、Pod 内に含まれるコンテナはネットワークを共有しているため、コンテナ同士は 127.0.0.1 でアクセスできます。補足として、Pod はプロセスではありません。コンテナがプロセスであり、Pod は設定値に過ぎず、コンテナを Pod に所属させて起動することにより、はじめて Pod の設定がホスト上のステータスに現れます。
podman pod create
Pod を作成するには podman pod create を使用します。下記の例では Nginx 用の Pod を作成しています。コマンドの内容の通りですが、-p 8080:80 により、外部から 8080 アクセスすると、この Pod に含まれる 80 で Listen しているコンテナに接続されます。デフォルトではホスト上の全てのインターフェイスが対象となり、且つ TCP です。尚、root 以外で実行する場合は、Well Known Port を使用できません。
myadmin@ubuntu:~$ podman pod create -p 8080:80 --name nginx-pod
UDP の場合は下記の通りです。
myadmin@ubuntu:~$ podman pod create -p 8080:80/udp --name nginx-pod-udp
ポートのマッピングは複数指定することができます。
myadmin@ubuntu:~$ podman pod create -p 8080:80 -p 8080:80/udp -p 9090:90 --name nginx-pod-test1
Listen するホストの IP アドレスを指定することもできます。以下では 8080:80 のポートマッピングは、10.1.0.89 の IP アドレスでのみ有効になります。これは、稀にホスト側がデフォルトで使用しているポート番号と重複して起動できないケースの場合に有効な手法です。
myadmin@ubuntu:~$ podman pod create -p 10.1.0.89:8080:80 -p 8080:80/udp -p 9090:90 --name nginx-pod-test2
podman pod ps
Pod の一覧を確認するには podman pod ps を使用します。
myadmin@ubuntu:~$ podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
b4599a7dfef9 nginx-pod Created 5 minutes ago 7eb849f796b8 1
podman pod inspect
Pod の詳細を確認するには podman pod inspect を使用します。出力は省略しますが、前述のコマンドで指定したポートのマッピング等が確認できます。
myadmin@ubuntu:~$ podman pod inspect nginx-pod
podman pod rm
Pod を削除するには podman pod rm を使用します。
myadmin@ubuntu:~$ podman pod rm nginx-pod myadmin@ubuntu:~$ podman pod ps POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
コンテナの実行
コンテナを実行します。Podman は Docker と同じように、コンテナ単体でも実行できますが、本稿では Pod の使用を前提とします。
podman run
コンテナを起動するには podman run を使用します。この例では、コンテナを Pod に所属させて起動することで、外部からアクセス可能なコンテナとして起動しています。尚、事前に podman pull でイメージをダウンロードしておく必要はなく、run の実行時に自動的に pull も行われます。
各オプションは、-d: コンテナをデタッチモードで実行(コンテナをバックグラウンドで実行)、--pod nginx-pod: 前述で作成した Pod を指定、--name nginx: コンテナ名を指定、docker.io/library/nginx:latest: 前述で Pull したイメージを指定、となります。起動後は、外部から htttp://xxx.xxx.xxx.xxx:8080 でアクセスすることで、Nginx のテストページが表示されます。
myadmin@ubuntu:~$ podman run -d --pod nginx-pod --name nginx docker.io/library/nginx:latest
-it オプションを付けて、コマンドに /bin/bash を指定して実行するとコンテナの bash が起動し、そのままコンテナ内の操作ができます。 -it オプションは -i:interactive, -t:tty であり、コンテナ内でインタラクティブに操作を行う場合は必須のオプションです。両方を指定しないとコンテナ内の操作ができません。--rm オプションにより exit すると同時にコンテナも削除されます。
myadmin@ubuntu:~$ podman run -it --rm docker.io/library/nginx:latest /bin/bash
root@496eeef03eb5:/#
下記は、コンテナ内で実行したコマンドの出力結果を返し、実行後はコンテナを削除しています。最後の echo test コマンドにより、コンテナのデフォルトの Entrypoint を上書きしています。あまり使い道は無いかもしれません。
myadmin@ubuntu:~$ podman run --rm docker.io/library/nginx:latest echo test
test
podman ps
コンテナを一覧を確認するには podman ps を使用します。停止中のコンテナも含めて表示するには -a オプションを付けます。1507caa1d24d-infra コンテナは Pod を使用してコンテナを起動した場合に、自動的に起動される特殊なコンテナです。infra コンテナと呼ばれます。infra コンテナは、他のコンテナを削除しても残り続けます。
myadmin@ubuntu:~$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d30b10683be k8s.gcr.io/pause:3.5 43 minutes ago Up 41 minutes ago 0.0.0.0:8080->80/tcp 1507caa1d24d-infra
a14792d94f89 docker.io/library/nginx:latest nginx -g daemon o... 32 minutes ago Up 32 minutes ago 0.0.0.0:8080->80/tcp nginx
podman exec
稼働中のコンテナ内でコマンドを実行するには podman exec を使用します。
myadmin@ubuntu:~$ podman exec nginx echo test
podman stop / start
コンテナを停止するには podman stop を使用します。これは削除 (rm) ではないためコンテナ内で変更した内容は保持されています。コンテナを起動するには podman start を使用します。start と run を混同している状況をたまに見かけますが、run はコンテナを生成(インスタンス化という意味でも近い)しており、stop/start はその生成されたコンテナを停止・起動します。
myadmin@ubuntu:~$ podman stop nginx myadmin@ubuntu:~$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d30b10683be k8s.gcr.io/pause:3.5 53 minutes ago Up 51 minutes ago 0.0.0.0:8080->80/tcp 1507caa1d24d-infra a14792d94f89 docker.io/library/nginx:latest nginx -g daemon o... 42 minutes ago Exited (0) 11 seconds ago 0.0.0.0:8080->80/tcp nginx myadmin@ubuntu:~$ podman start nginx myadmin@ubuntu:~$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d30b10683be k8s.gcr.io/pause:3.5 55 minutes ago Up 52 minutes ago 0.0.0.0:8080->80/tcp 1507caa1d24d-infra a14792d94f89 docker.io/library/nginx:latest nginx -g daemon o... 44 minutes ago Up 18 seconds ago 0.0.0.0:8080->80/tcp nginx
podman rm
コンテナを起動するには podman rm を使用します。対象のコンテナが停止している必要がありますが、-f オプションを付けることで、強制的に削除することも可能です。
myadmin@ubuntu:~$ podman stop nginx myadmin@ubuntu:~$ podman rm nginx myadmin@ubuntu:~$ podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d30b10683be k8s.gcr.io/pause:3.5 57 minutes ago Up 54 minutes ago 0.0.0.0:8080->80/tcp 1507caa1d24d-infra
ストレージ
Podman に限らず、コンテナを削除すると起動中に変更を加えた内容は無くなります( podman stop/start では無くなりません)。例えば WordPress のような CMS は稼働中に動的にデータが更新されるため、コンテナの作り直しや別ホストでの稼働でデータを再利用する場合、コンテナの外部にデータを保持する必要があります。選択肢としては Volume か Bind mount の 2 択になります。
Volume
Volume は Podman の標準的なストレージ機能です。Volume の管理はホスト OS から分離されており、データの移行なども含め、Podman コマンドで完結します。Volume の管理は podman volume で行います。
podman volume create / ls
Volume の作成は create を使用します。名前を付けないとランダムな文字列になります。作成した Volume を確認するには ls を使用します。
myadmin@ubuntu:~$ podman volume create test-vol1 myadmin@ubuntu:~$ podman volume ls DRIVER VOLUME NAME local test-vol1
podman volume inspect
volume inspect で詳細を確認できます。出力の通り、Volume の OS 上の実体は ~/.local/share/containers/storage/volumes/test-vol1/_data に格納されます。sudo (root) で実行した場合は、/var/lib/containers/storage/volumes に格納されます。
myadmin@ubuntu:~$ podman volume inspect test-vol1 [ { "Name": "test-vol1", "Driver": "local", "Mountpoint": "/home/myadmin/.local/share/containers/storage/volumes/test-vol1/_data", "CreatedAt": "2023-07-30T20:34:47.626355123+09:00", "Labels": {}, "Scope": "local", "Options": {} } ] myadmin@ubuntu:~$ ls -l ~/.local/share/containers/storage/volumes 合計 4 drwx------ 3 myadmin myadmin 4096 7月 30 20:34 test-vol1
Volume の利用確認
Volume が利用できるか確認します。ここでは、Ubuntu のイメージを使用し、前述の test-vol1 を /data1 にマウントして一時的に起動し、/data1/test1 ファイルを作成して、実行後にコンテナを削除しています。その後、~/.local/share/containers/storage/volumes/test-vol1/_data 内に test1 ファイルが存在するため、データが永続化できていることが分かります。尚、Volume は事前に作成しておかなくても、run の実行時に指定することで自動的に作成されます。
myadmin@ubuntu:~$ podman run --rm -v test-vol1:/data1 docker.io/library/ubuntu:22.04 touch /data1/test1 myadmin@ubuntu:~$ ls -l ~/.local/share/containers/storage/volumes/test-vol1/_data 合計 0 -rw-r--r-- 1 myadmin myadmin 0 7月 30 21:04 test1
Volume の複製
これまでの通り、Volume の実体はホスト OS 上のディレクトリであり、Podman コマンドを使わずとも、そのまま cp で複製できます。ですがせっかくなので Podman コマンドを使用して Volume を複製してみます(結局はコンテナ内のコマンドを使用していますが)。今回は -v test-vol2:/data2 を追加し、/data1/* を /data2 にコピーしています。Podman コマンド上でコンテナ内でコマンドを実行する際、* がうまく解釈されないようなので、sh -c “cp /data1/* /data2” のように実行するコマンドを文字列として指定し、展開されないようにしています。
myadmin@ubuntu:~$ podman run --rm -v test-vol1:/data1 -v test-vol2:/data2 docker.io/library/ubuntu:22.04 sh -c "cp /data1/* /data2" myadmin@ubuntu:~$ ls -l ~/.local/share/containers/storage/volumes/test-vol2/_data 合計 0 -rw-r--r-- 1 myadmin myadmin 0 7月 30 21:37 test1
Volume の削除
Volume の削除は rm を使用します。コンテナから利用中は削除できません。
myadmin@ubuntu:~$ podman volume ls DRIVER VOLUME NAME local test-vol1 local test-vol2 myadmin@ubuntu:~$ podman volume rm test-vol1 test-vol2 myadmin@ubuntu:~$ podman volume ls
NFS
Volume に NFS を使用することができます。デフォルトは NFSv3 ですが、下記では NFSv4 を使用しています。
myadmin@ubuntu:~$ podman volume create --opt type=nfs4 --opt o=rw --opt device=172.16.1.10:/home/nfs nfs-test-vol1
Bind mount
Bind mount はホスト OS 上のディレクトリを直接マウントする方法です。一見、管理しやすそうにも感じますが、デメリットとしては、① Podman コマンドで管理ができない、②ディレクトリ構造を考える必要がある、③セキュリティ(パーミッション)を考える必要がある、が挙げられると思います。一方で Volume を使用する場合は、Podman コマンドで管理でき、ディレクトリ構造も所定の場所に限定されており、パーミッションも適切に管理されています。コンテナの扱いに慣れないうちは良い場合もあるかもしれませんが、基本的には使わないほうが良いでしょう。
Bind mount の利用確認
最初に ~/test-vol1 を作成し、それをマウントしてコンテナを起動し、/data1/test1 ファイルの作成後にコンテナを削除しています。Volume と異なり、run の実行時にマウント対象のディレクトリは作成されませんが、もしかすると root であれば作成されるかもしれません。
myadmin@ubuntu:~$ mkdir ~/test-vol1 myadmin@ubuntu:~$ podman run --rm -v ~/test-vol1:/data1 docker.io/library/ubuntu:22.04 touch /data1/test1 myadmin@ubuntu:~$ ls -l ~/test-vol1 合計 0 -rw-r--r-- 1 myadmin myadmin 0 7月 30 22:26 test1