Podmanをやってみよう
Podman(Podマネージャ)は、Redhat社が中心となって開発し、2019年のバージョン1.0.0からオープンソースとして提供されているコンテナ管理ツールです。
コンテナ管理ツールと言えばDockerが有名ですが、RHEL8以降ではDockerのサポートが廃止され、Redhat社はPodmanの利用を推奨しています。
Podmanの基本コマンドは「podman」であり、Dockerの基本コマンド「docker」と互換性があります。例えばコンテナの実行状況を確認する「docker ps」コマンドは「podman ps」のようになります。この他のコマンドもほぼ同様であるため、PodmanはDockerのナレッジを活用できる点で取り組みやすさがあります。
PodmanとDockerの違いについては、大きく2つが挙げられます。
1つ目は「デーモンレス」であることです。Dockerはrootで実行されているデーモン(daemon)を介してカーネル(Kernel)にアクセスしています。
一方、Podmanは直接カーネルにアクセスできるため、デーモンを必要としていません。
そのため、Dockerはデーモンに異常が発生した場合は、全てのコンテナが悪影響を受けてしまいますが、デーモンレスのPodmanにおいては、そのようなことは起こらないため、Redhat社がPodmanの利用を推奨しています。
2つ目は「ルートレスモード」です。Dockerのコンテナはrootで実行されるDockerデーモンによって制御されているため、もしDockerにセキュリティ上の脆弱性があった場合は、システム全体に悪影響を及ぼす可能性が考えられます。
一方、Podmanはユーザ権限下で実行されており、Linuxの機能であるユーザ名前空間によりユーザの権限以上の操作を抑制することで、rootのようなホストの特権を利用せずにコンテナ管理できる点でセキュリティが高いと言われています。
ただし、Dockerもバージョン19.03からはルートレスモードが標準で利用できようになったので、実質は「デーモンレス」であることがPodmanとDockerの大きな違いと言えるのかもしれません。
目次
Podmanをやってみよう
Podmanの概要を理解したところで、さっそくPodmanをインストールしてみましょう。PodmanはRHEL 7.6及びCentOS 7.6以降でインストール可能です。また、MacやWindows版のPodman Desktopも存在しています。
今回は、以下のOSにPodmanをインストールしてみます。
$ cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
インストール
インストールは、yumで行います。
$ yum install podman
Podmanのインストールが完了したら、バージョンを確認してみます。
$ podman -v
podman version 1.6.4
バージョン情報が返ってきたらインストールは成功です。
ルートレスモードで起動する
CentOS 7.8にインストールしたPodmanを、ユーザ(testuser)から操作すると以下のようなエラーに遭遇します。
$ podman ps
cannot clone: Invalid argument
user namespaces are not enabled in /proc/sys/user/max_user_namespaces
Error: could not get runtime: cannot re-exec process
これは、Podmanがルートレスモードで起動するためにLinuxカーネルに実装されている「ユーザー名前空間」を使用しているために発生します。通常、「user.max_user_namespaces」というカーネルパラメータはデフォルトは0となっています。
このカーネルパラメータを0以外の数値に変更します。Redhatによると15,000などの大きな数値に変更することを推奨しています。
ユーザー名空間の完全なサポート
Red Hat Enterprise Linux 7.2 でテクノロジープレビューとして導入されたユーザーネームスペース (userns) が完全にサポートされるようになりました。この機能は、ホストとコンテナー間の分離を改善することにより、Linux コンテナーを実行しているサーバーに追加のセキュリティーを提供します。コンテナーの管理者は、ホスト上で管理操作を実行できなくなり、セキュリティーが向上します。
第12章 カーネル Red Hat Enterprise Linux 7 | Red Hat Customer Portal
user.max_user_namespaces
のデフォルト値は0
です。この値をゼロ以外の値に設定すると、誤動作するアプリケーションを停止できます。user.max_usernamespaces
は、15000
などの大きな値に設定することが推奨されます。これにより、通常の操作では値に再度アクセスする必要はありません。
CentOS 7.8では、以下のようにファイルを変更して
$ vi /etc/sysctl.d/42-rootless.conf
user.max_user_namespaces=15000 ← 値を0から15,000に修正
ファイルを修正し保存したら、以下のコマンドでカーネルパラメータの変更を適用します。
$ sysctl --system
* Applying /etc/sysctl.d/42-rootless.conf ...
user.max_user_namespaces = 15000
$ sysctl -a | grep user_namespace
user.max_user_namespaces = 15000
カ-ネルパラメータの修正が適用されましたので、再度、Podmanをユーザ(testuser)から操作してみます。今度は先ほどと異なるエラーが表示されます。
$ podman ps
ERRO[0000] cannot find mappings for user testuser: No subuid ranges found for user "testuser" in /etc/subuid
ERRO[0000] cannot find mappings for user testuser: No subuid ranges found for user "testuser" in /etc/subuid
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Podmanは、「/etc/subuid」と「/etc/subgid」で定義されている代替マッピングのUIDおよびGIDを使用してユーザのプロセスを実行します。RHELやCentOSなどのディストリビューションでは、「/etc/subuid」と「/etc/subgid」が自動的に追加されることがないため、以下のように手動でファイルを修正します。
$ vi /etc/subuid
testuser:100000:65536
$ vi /etc/subgid
testuser:100000:65536
再度、Podmanをユーザ(testuser)から操作してみます。上記の設定により、コンテナ内の特権(root)ユーザは100000というUIDとGIDを持つ一般ユーザとして動作し、ホストの特権(root)ユーザのUIDと別物として取り扱われるため、セキュリティ面で安全性が高くなります。
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
上記の設定が適用されエラーがなくなることで、podmanコマンドがルートレスモードにより正常に利用できるようになったことが確認できました。
Podmanのコンテナを起動してみる
ルートレスモードでPodmanのコンテナを起動してみます。
Podmanは、デフォルトではRedhatのレジストリ(registry.access.redhat.com又はregistry.redhat.io)及びDockerのレジストリ(docker.io)からイメージをpullすることができます。
Redhatのリポジトリを利用する場合はRedhatの認証情報が必要になるため、今回はDockerのレジストリ(docker.io)からnginxのコンテナイメージを取得してみます。
$ podman pull docker.io/library/nginx:latest
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
Copying blob 4f3256bdf66b done
Copying blob 8c767bdbc9ae done
Copying blob 78e14bb05fd3 done
Copying blob 2019c71d5655 done
Copying blob 75576236abf5 done
Copying blob 26c5c85e47da done
Copying config 6efc10a051 done
Writing manifest to image destination
Storing signatures
Error processing tar file(exit status 1): there might not be enough IDs available in the namespace (requested 0:42 for /etc/gshadow): lchown /etc/gshadow: invalid argument
Error: error pulling image "docker.io/library/nginx:latest": unable to pull docker.io/library/nginx:latest: unable to pull image: Error committing the finished image: error adding layer with blob "sha256:26c5c85e47da3022f1bdb9a112103646c5c29517d757e95426f16e4bd9533405": Error processing tar file(exit status 1): there might not be enough IDs available in the namespace (requested 0:42 for /etc/gshadow): lchown /etc/gshadow: invalid argument
何らかのエラーが発生していて、イメージをpullできませんでした。Podmanをルートレスモードで起動するために「/etc/subuid」と「/etc/subgid」を手動で修正した場合は、その設定を適用するためにpodman system migrateコマンドを実行する必要があります。
$ podman system migrate
特にメッセージが表示されなければ問題はありません。
コンテナイメージをpullする
コンテナイメージは、podman pullコマンドを使用して取得します。
$ podman pull docker.io/library/nginx:latest
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
Copying blob 78e14bb05fd3 done
Copying blob 75576236abf5 done
Copying blob 26c5c85e47da done
Copying blob 4f3256bdf66b done
Copying blob 8c767bdbc9ae done
Copying blob 2019c71d5655 done
Copying config 6efc10a051 done
Writing manifest to image destination
Storing signatures
6efc10a0510f143a90b69dc564a914574973223e88418d65c1f8809e08dc0a1f
コンテナイメージの取得が完了したら、ローカル上に格納されたコンテナイメージを一覧表示します。
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest 6efc10a0510f 2 weeks ago 147 MB
podman pullコマンドで取得したNginxのコンテナイメージがローカル上に格納されていることが確認できました。
Nginxをコンテナ起動してみる
NginxをPodmanのコンテナで起動してみます。
$ podman run -d -p 8080:80 --name test_nginx nginx
02596cf111d61469d0eca6d13ec1bea0ffc662697dbe71cd47b4ad3a09816873
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02596cf111d6 docker.io/library/nginx:latest nginx -g daemon o... 5 seconds ago Up 4 seconds ago 0.0.0.0:8080->80/tcp test_nginx
test_nginxというコンテナが起動しましたので、curlからアクセスしてみます。
$ curl http://localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Nginxのデフォルトのhtmlが返ってきました。
ルートレスモードで起動したPodmanのコンテナが問題なく動作していることが確認できました。
コンテナの停止とイメージの削除
稼働中のtest_nginxコンテナを停止します。コンテナの停止はpodman stopコマンドを使用します。
$ podman stop test_nginx
02596cf111d61469d0eca6d13ec1bea0ffc662697dbe71cd47b4ad3a09816873
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
02596cf111d6 docker.io/library/nginx:latest nginx -g daemon o... 25 minutes ago Exited (0) About a minute ago 0.0.0.0:8080->80/tcp test_nginx
$ podman rm test_nginx
02596cf111d61469d0eca6d13ec1bea0ffc662697dbe71cd47b4ad3a09816873
$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
最後にコンテナイメージを削除します。コンテナイメージの削除は、podman rmiコマンドを使用します。
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest 6efc10a0510f 2 weeks ago 147 MB
$ podman rmi 6efc10a0510f
Untagged: docker.io/library/nginx:latest
Deleted: 6efc10a0510f143a90b69dc564a914574973223e88418d65c1f8809e08dc0a1f
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
まとめ
いかがでしたでしょうか。Podmanのインストール、ルートレスモード(ユーザ空間名前)の設定、コンテナイメージの取得及びPodmanのコンテナに関する基本的な操作方法について解説しました。
今回の解説で登場したPodmanコマンドは、以下の表のとおりです。しっかりと理解しておきましょう。
Podmanコマンド | 概要 |
---|---|
podman -v | Podmanのバージョン表示 |
podman ps | Podmanのコンテナを一覧表示する |
podman ps -a | 停止中のPodmanのコンテナを含むすべてのコンテナを一覧表示する |
podman pull | レジストリからコンテナイメージをローカル上に取得する |
podman system migrate | ユーザ名前空間など設定変更した内容をPodmanに適用する |
podman images | ローカル上に格納されているコンテナイメージを一覧表示する |
podman run | コンテナイメージをコンテナ起動する |
podman stop | コンテナを停止する |
podman rm | 停止中のコンテナを削除する |
podman rmi | コンテナイメージをローカル上から削除する |
PodmanのコマンドはDockerとほとんど変わりがないため、Dockerを既に経験した人にとってPodmanの学習コストは低いと言えるかもしれません。
2023年5月時点における筆者の感想は、PodmanとDockerの大きな差はデーモンレスかどうかの差でしかないため、PodmanがDockerにとって代わるということではなく、両方のコンテナ管理ツールを自由に使いこなせることの方が重要だと感じました。
ただし、DockerとPodmanではリリースの頻度が異なり、Podmanの方が頻繁に最新リリースが提供されることを考えると、将来的にPodmanの市場が拡大してくる可能性が十分に考えられます。
使い勝手にほとんど差がないPodmanとDockerの行方に注目していきたいとおもいます。
参考になれば幸いです。
システムのお悩みについてご相談ください
SOHOのシステム運用管理に関するお悩みごとについて、なんでもお気兼ねなくご相談ください。
現役システムエンジニアのスタッフが、ボランティアでご相談にご対応させていただきます。