インストール - Podman
概要
コンテナとは、ソフトウェアプロセスやマイクロサービスをパッケージ化して、あらゆるコンピューティング環境で実行可能にするソフトウェアソリューションである。
コンテナに含まれるファイルには、アプリケーションコード、環境変数、設定コード、バイナリプログラム、ソフトウェアの依存関係、ライブラリ等がある。
これらのコンポーネントをバンドルするプロセスはコンテナ化と呼ばれ、最終的な製品はコンテナイメージとして知られている。
このイメージは、クラウド、オンプレミスのデータシステム、ローカルシステム等、あらゆるプラットフォームにデプロイされる。
Podman (Pod Manage) は、Open Container Initiatives (OCI) のコンテナイメージを開発、管理、本番環境で実行する時に使用するコンテナエンジンである。
OCIは、コンテナフォーマットとランタイムに関するOSレベルの仮想化ソフトウェアコンテナのオープンなガバナンス構造を実装するために設計された。
Podmanコンテナは、スーパユーザ / 非スーパーユーザのいずれでも実行可能である。
Podmanのソケットアクティベーション
ソケットアクティベーションは、systemdがソケット (TCP、UDP、Unixソケット等) を作成することで機能する。
クライアントがソケットに接続する時、systemdはソケット用に設定されたsystemdサービスを起動する。
新しく起動されたプログラムは、ソケットのファイルディスクリプタを継承して、着信した接続を受け付けることができる。 (システムコールのaccept()
を実行する)
これにより、デフォルトのsystemdソケット設定であるAccept=no
に対応し、サービスがソケットを受け付けるようになる。
Podmanは、2種類のソケットアクティベーションをサポートしている。
- APIサービスのソケットアクティベーション
- コンテナのソケット起動
Podmanのインストール
パッケージ管理システムからインストール
# RHEL sudo yum install epel-release sudo dnf install podman # SUSE sudo zypper install podman
スタティックビルド済みのPodmanの使用
Podmanのダウンロード
※注意
スタティックビルド済みのPodmanを使用する場合は、Podman Desktopが使用できないことに注意する。
PodmanのGithubにアクセスして、スタティックビルド済みのPodmanをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf podman-remote-static-linux_<アーキテクチャ名>.tar.gz cd bin mv podman-remote-static-linux_<アーキテクチャ名> podman
必要ならば、Podmanを任意のインストールディレクトリに配置する。
mkdir -p <任意のインストールディレクトリ> mv podman <任意のインストールディレクトリ>
~/.profileファイル等に、環境変数PATH
およびソケットの設定を記述する。
vi ~/.profile
# ~/.profileファイル
export PATH="<Podmanのインストールディレクトリ>:$PATH"
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
gvproxyのダウンロード
SUSEにおいて、パッケージ管理システムにgvproxyパッケージが存在しないため、手動でgvproxyをインストールする必要がある。
まず、gvproxyのGithubにアクセスして、gvproxyをダウンロードする。
ダウンロードしたgvproxyのファイル名を変更して、/usr/libexec/podmanディレクトリまたは/usr/local/libexec/podmanディレクトリにコピーする。
# ファイル名を変更 mv gvproxy-linux-<アーキテクチャ名> gvproxy # 実行権限を付加 (非スーパーユーザでも実行できるようにする) chmod +x gvproxy # gvproxyを配置するディレクトリを作成 sudo mkdir -p /usr/libexec/podman ## または sudo mkdir -p /usr/local/libexec/podman ## または sudo mkdir -p /usr/local/lib/podman ## または sudo mkdir -p /usr/lib/podman # gvproxyを配置する sudo mv gvproxy /usr/local/libexec/podman
ソースコードからインストール
Goのバージョンが1.16未満の場合
もし、パッケージ管理システムのGoのバージョンが1.16未満の場合は、Goの公式Webサイトにアクセスして、Goをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf go<バージョン>.linux-<アーキテクチャ名>.tar.gz mv go<バージョン>.linux-<アーキテクチャ名> Go
必要ならば、Goを任意のインストールディクトリに配置する。
mv Go <任意のインストールディレクトリ>
~/.profileファイル等に、環境変数PATH
を追記する。
export GOPATH=<Goのインストールディレクトリ>
export PATH=/<Goのインストールディレクトリ>/bin:$PATH
最新のconmonが必要な場合
最新バージョンのconmonがシステムにインストールされていることが期待される。
conmonは、OCIランタイムをモニタリングするために使用される。
conmonのビルドに必要なライブラリをインストールする。
# SUSE sudo zypper install meson ninja glib2-devel libseccomp-devel
conmonのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf conmon-<バージョン>.tar.gz cd conmon-<バージョン>
または、git clone
コマンドを実行して、ソースコードをダウンロードする。
git clone https://github.com/containers/conmon cd conmon
conmonをビルドおよびインストールする。
meson --prefix=<Podmanのインストールディレクトリ> ./build ninja -C ./build ninja -C ./build install
conmonファイルは/<Podmanのインストールディレクトリ>/liexec/podmanディレクトリにインストールされるため、binディレクトリへのシンボリックリンクを作成する。
ln -s /<Podmanのインストールディレクトリ>/liexec/podman/conmon /<Podmanのインストールディレクトリ>/bin/conmon
最新のcrun /runcが必要な場合
最新バージョンのcrun /runcがシステムにインストールされていることが期待される。
crun /runcは、Podmanによりその1つがデフォルトのランタイムとしてピックアップされる。(crunはruncよりも優先される)
crun /runcのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf runc-<バージョン>.tar.gz cd runc-<バージョン>
または、git clone
コマンドを実行して、ソースコードをダウンロードする。
git clone https://github.com/opencontainers/runc.git cd runc
crun /runcをビルドおよびインストールする。
# SELinux, SECcompを有効にする場合 make BUILDTAGS="selinux seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) # SELinux, SECcompを無効にする場合 make BUILDTAGS="" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) make PREFIX=<Podmanのインストールディレクトリ> install
slirp4netnsのインストール
slirp4netnsのビルドに必要なライブラリをインストールする。
# RHEL sudo dnf install glib2-devel libslirp-devel libcap-devel libseccomp-devel # SUSE sudo zypper install glib2-devel libslirp-devel libcap-devel libseccomp-devel
slirp4netnsのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf slirp4netns-<バージョン>.tar.gz cd slirp4netns-<バージョン>
slirp4netnsをビルドおよびインストールする。
./autogen.sh mkdir build && cd build ../configure --prefix=<Podmanのインストールディレクトリ> make -j $(nproc) make install
CNIネットワークの設定
※注意
CNIバックエンドは非推奨であり、Podman 5.0以降ではNetavarkが優先されるため、CNIネットワークは削除される予定である。
CNIネットワーキングの基本的な設定は、Podmanのビルド時で行われており、Podmanを使用するために他の設定は必要ない。
追加の設定を行う場合は、CNIネットワークの設定ファイルをダウンロードして、/etc/containersディレクトリに配置する。
sudo mkdir -p /etc/containers sudo curl -L -o /etc/containers/registries.conf https://src.fedoraproject.org/rpms/containers-common/raw/main/f/registries.conf sudo curl -L -o /etc/containers/policy.json https://src.fedoraproject.org/rpms/containers-common/raw/main/f/default-policy.json
CNIネットワークの設定の詳細は、PodmanのGithubに記載されている。
ユーザネームスペースの有効化
Linuxカーネルがユーザネームスペースをサポートしているかどうかを確認する。
zgrep CONFIG_USER_NS /proc/config.gz # 出力例: ユーザネームスペースをサポートしている場合 CONFIG_USER_NS=y
もし、ユーザネームスペースが無効の場合は有効にする。
# ユーザネームスペースを一時的に有効にする sudo sysctl kernel.unprivileged_userns_clone=1 # ユーザネームスペースを恒久的に有効にする echo 'kernel.unprivileged_userns_clone=1' > /etc/sysctl.d/userns.conf
Podmanのビルド
Podmanのビルドに必要なライブラリをインストールする。
# RHEL sudo dnf install 'dnf-command(builddep)' sudo dnf builddep rpm/podman.spec --enablerepo=codeready-builder-for-rhel-$(rpm --eval %{?rhel})-$(uname -m)-rpms sudo dnf install conmon containers-common crun iptables netavark nftables slirp4netns # SUSE sudo zypper install pkg-config libseccomp-devel libgpgme-devel libbtrfs-devel device-mapper-devel systemd-devel libapparmor-devel protobuf-devel # Raspberry Pi / Mobian sudo apt install btrfs-progs git uidmap pkg-config crun golang-go go-md2man iptables libassuan-dev libbtrfs-dev libc6-dev libdevmapper-dev libglib2.0-dev \ libgpgme-dev libgpg-error-dev libprotobuf-dev libprotobuf-c-dev libseccomp-dev libselinux1-dev libsystemd-dev libapparmor-dev \ netavark # 古いバージョンのRaspbian OSの場合、netavarkパッケージが利用できない場合がある # その場合、containernetworking-pluginsパッケージをインストールする
PodmanのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf podman-<バージョン>.tar.gz cd podman-<バージョン>
または、git clone
コマンドを実行して、Podmanのソースコードをダウンロードすることもできる。
git clone https://github.com/containers/podman/ cd podman
Podmanをビルドおよびインストールする。
# SELinux, SECcomp (syscall filtering) を有効にする場合 make BUILDTAGS="selinux seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) # AppArmor, SECcomp (syscall filtering) を有効にする場合 make BUILDTAGS="apparmor seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) # SELinux, SECcomp (syscall filtering) を無効にする場合 make BUILDTAGS="" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) make install PREFIX=<Podmanのインストールディレクトリ>
~/.profileファイル等に、環境変数PATH
およびPodmanソケットの設定を記述する。
vi ~/.profile
# ~/.profileファイル
export PATH="/<Podmanのインストールディレクトリ>/bin:$PATH"
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
最新のnetavarkが必要な場合
最新バージョンのnetavarkをインストールする場合、ソースコードからインストールする。
netavarkはコンテナ用のRustベースのコンテナネットワークスタックである。
Podmanで動作するように設計されているが、他のOCIコンテナ管理アプリケーションにも適用できる。
netavarkのビルドに必要なライブラリをインストールする。
# SUSE sudo zypper install rust cargo protobuf-devel go-md2man
netavarkのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf netavark-<バージョン>.tar.gz cd netavark-<バージョン>
netavarkをビルドおよびインストールする。
make PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) make PREFIX=<Podmanのインストールディレクトリ> install
エラー関連
Seccompエラー
Podmanイメージのビルド時において、以下に示すようなエラーが出力される場合がある。
Error: loading seccomp profile () failed: seccomp not enabled in this build
Podmanイメージでは、Seccompを無効にしている場合はコンテナを作成できないイメージが存在する。
この時、runc / crunおよびPodmanのビルド時において、BUILDTAGS
オプションにseccomp
を指定する必要がある。
gvproxy
gvproxyとは
gvproxyは、libslirpおよびVPNKitを置き換えるものであり、Golangで記述されている。
gVisorのネットワークスタックをベースにしている。
libslirpと比較して、gvisor-tap-vsockは設定可能なDNSサーバと動的なポート転送を提供する。
また、QEMU、Hyperkit、Hyper-V、User Mode Linuxで使用することができる。
※注意 1
SUSEにおいて、パッケージ管理システムにgvproxyパッケージが存在しないため、手動でgvproxyをインストールする必要がある。
※注意 2
podman machine start
コマンドを実行して仮想マシンを起動する時、gvproxyが無いためホストネットワークを起動できない場合がある。
この時、以下に示すセクションを参照して、gvproxyをインストールする必要がある。
Staticビルド済みのバイナリをインストール
まず、gvproxyのGithubにアクセスして、gvproxyをダウンロードする。
ダウンロードしたgvproxyのファイル名を変更して、/usr/libexec/podmanディレクトリまたは/usr/local/libexec/podmanディレクトリにコピーする。
# ファイル名を変更 mv gvproxy-linux-<アーキテクチャ名> gvproxy # 実行権限を付加 (非スーパーユーザでも実行できるようにする) chmod +x gvproxy # gvproxyを配置するディレクトリを作成 sudo mkdir -p /usr/libexec/podman ## または sudo mkdir -p /usr/local/libexec/podman ## または sudo mkdir -p /usr/local/lib/podman ## または sudo mkdir -p /usr/lib/podman # gvproxyを配置する sudo mv gvproxy /usr/local/libexec/podman
ソースコードからインストール
gvproxyのビルドに必要なライブラリをインストールする。
# SUSE sudo zypper install rust cargo protobuf-devel go-md2man
gvproxyのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf gvisor-tap-vsock-<バージョン>.tar.gz cd gvisor-tap-vsock-<バージョン>
gvproxyをビルドする。
make -j $(nproc)
binディレクトリに実行バイナリ群が生成される。
そのため、それらの実行バイナリ群をPodmanのインストールディレクトリに配置する。
cd bin mv ./* /<Podmanのインストールディレクトリ>/bin
Podmanの設定
Dockerから移行する場合
DockerからPodman Desktopに透過的に移行するため、環境変数DOCKER_HOST
を使用することができる。
- 使い慣れたDockerコマンドを使い続けることが可能である。
- Podmanの利点を活用できる。
- GradleやTestcontainers等のツールは、再設定なしでPodmanと通信することができる。
Podmanソケットファイルの場所を確認する。
podman info --format '{{.Host.RemoteSocket.Path}}'
Podmanソケットの場所を設定するため、~/.profileファイル等に環境変数DOCKER_HOST
に記述する。
vi ~/.profile
# ~/.profileファイル
export DOCKER_HOST="unix://<Podmanソケットファイルのパス>"
Linux仮想マシンの作成と開始
Linux仮想マシンの初期化
コンテナが実行される新しいLinux仮想マシンを初期化する。
VMにアクセスするためのSSHキーが自動的に生成されて、VM内のスーパーユーザアカウントとユーザアカウントへのシステム接続が追加される。
podman machine init
デフォルトでは、VMのディストリビューションはカスタムFedoraイメージに基づくWSLを除き、Fedora CoreOSである。
一般的なFedora CoreOSのアップグレードは14日ごとに行われるが、自動アップデートのZincataはPodmanマシンでは無効になっている。
Linux仮想マシンの編集
Podmanをソースコードから任意のディレクトリにインストールした場合、
~/.config/containers/containers.confファイル内の[engine]
セクションの直下にhelper_binaries_dir
キーを追加して、ヘルパーバイナリのあるディレクトリを設定する。
vi ~/.config/containers/containers.conf
# ~/.config/containers/containers.confファイル
[engine]
helper_binaries_dir = ["/<Podmanのインストールディレクトリ>/bin", "/<Podmanのインストールディレクトリ>/libexec/podman", "/usr/local/libexec/podman", "/usr/local/lib/podman", "/usr/libexec/podman", "/usr/lib/podman"]
Linux仮想マシンの開始
Linux仮想マシンを開始する。
podman machine start
開始後、Docker APIに関するメッセージが表示される。
これは、Docker APIフォワーディングがリッスンしているため、環境変数DOCKER_HOST
を設定することにより、Docker APIクライアントに接続することができることを表す。
API forwarding listening on: /home/user-name/.local/share/containers/podman/machine/qemu/podman.sock You can connect Docker API clients by setting DOCKER_HOST using the following command in your terminal session: export DOCKER_HOST='unix:///home/user-name/.local/share/containers/podman/machine/qemu/podman.sock'
Podmanマシンの接続の設定
各Podmanマシンは2つのデフォルト接続を公開する。
Podmanのデフォルト接続は1つのみ選択することができる。
- ルートレス
- ルートフル
Podman DesktopやKind等の他のツールはデフォルト接続に接続する。
もし、別のPodmanマシンの作成等により、デフォルトのPodmanマシン接続が変更された可能性があるイベントが発生した場合、デフォルト接続の確認と設定を検討すること。
まず、Podmanマシンの接続を確認する。
podman system connection ls
次に、Podmanマシンのデフォルト接続を任意の接続に設定する。
podman system connection default podman-machine-default # または podman system connection default podman-machine-default-root
Podmanマシンのデフォルト接続が変更されているかどうかを確認する。
podman system connection ls
デフォルト接続を持つPodmanマシンを再起動する。
podman machine stop podman machine start
Podman DesktopとPodmanの接続を更新する。
Podman Desktopのメイン画面右下にある[電球]アイコンを選択して[トラブルシューティング]ページを開き、[プロバイダーを再接続]ボタンを押下する。
Podmanの動作確認
Podmanの動作を確認するため、テストイメージをダウンロードして実行する。
podman run hello-world
Podmanコマンド
ログイン
podman loguin -u <ユーザ名> -v <登録するURL> # 例: Docker Hubにログインする場合 podman login -u <Docker Hubのユーザ名> -v https://docker.io podman login -u <Docker Hubのユーザ名> -v https://index.docker.io/v2/
認証情報は、/run/user/$UID/containers/auth.jsonファイルに保存される。
Docker Hubにログインすることにより、PodmanコマンドでDocker Hubからイメージを検索およびダウンロードすることができる。
Podmanイメージの検索
Quay (デフォルト) および他のWebサイト (登録している場合) からイメージを検索およびダウンロードする。
podman search <イメージ名>
Podmanイメージのダウンロード
podman pull <イメージ名> # 例: Ubuntuの公式イメージをダウンロード podman pull ubuntu # 例: Docker HubからApache2のイメージをダウンロード podman pull docker.io/httpd:latest
ダウンロードしたPodmanイメージの一覧の表示
podman images
Podmanイメージの削除
podman image rm <イメージID>
Podmanイメージを全て削除する。
podman image rm -f $(podman images -q)
Podmanコンテナの削除
podman container rm <コンテナID>
Podmanコンテナを全て削除する。
podman container rm -f $(podman container ps -a -q)
コンテナの作成
# コンテナを作成して、フォアグラウンドで起動 podman run --name <コンテナ名> <イメージ名> # <code>-d</code>オプションを付加して、コンテナをバックグラウンドで起動 podman run --name <コンテナ名> -d <イメージ名> # 例: イメージ名はopensuse、コンテナ名はsuse01として起動 podman run --name suse01 -itd opensuse /bin/bash # 例: イメージ名はhttpd、コンテナ名はwwwとして起動 # また、コンテナ内の80番ポートをホスト側の8080番にポートフォワーディングしている podman run --name www -p 8080:80 -d httpd
コンテナのプロセス確認
# 動作中のコンテナのみ表示 podman ps # 全てのコンテナを表示 podman ps -a または podman ps --all
コンテナの停止
コンテナが停止している時は、STATUSでExitedとなる。
podman stop <コンテナ名> または podman stop <コンテナID>
コンテナのログ確認
例えば、コンテナが起動せずに失敗する (exited) する場合、ログを確認する。
podman logs <コンテナID>
コンテナに名前を付ける
podman commit <コンテナID> <任意のコンテナ名>
コマンドの実行
起動中のコンテナにコマンドを実行する。
podman exec -it <コンテナ名> /bin/bash
コンテナとホスト間のファイルコピー
ホストからコンテナにファイルをコピーする。
podman cp <ホストのファイルパス> <コンテナ名>:<コンテナ内の保存先のパス> # または podman cp <ホストのファイルパス> <コンテナID>:<コンテナ内の保存先のパス> # 例: podman cp sample.txt my_suse:/tmp # コンテナを実行 podman exec -it my_suse /bin/bash # cd /tmp && lsコマンドを実行してファイルを確認
コンテナからホストにファイルをコピーする。
podman cp <コンテナ名>:<コンテナ内のファイルパス> <ホストの保存先のパス> # または podman cp <コンテナID>:<コンテナ内のファイルパス> <ホストの保存先のパス> # 例: podman cp my_suse:/tmp/sample.txt ~/Downloads
ボリュームのマウント
コンテナにボリュームをマウントする。
-v
オプションの代わりに--mount
オプションを付加することが推奨されている。
--mount
オプションは、キーバリュー形式で各要素が指定できる。
podman container run -it --mount type=<volume, bind, tmpfsのいずれかを指定>,src=<ボリューム名>,dst=<コンテナ内のパス> <コンテナ名/イメージ名:タグ名>
--rm
オプションを付加することにより、匿名ボリュームの場合はコンテナ停止と同時にボリュームも破棄される。
名前付きボリュームの場合は、--rm
オプションを付加しても、ボリュームは破棄されない。
mountオプションで指定できる種類 | 説明 |
---|---|
type | volume 、bind 、tmpfs を指定する。
|
src | source と記述することもできる。匿名ボリュームの場合は、省略する。 名前付きボリュームの場合は、その名前を記述する。 バインドマウントの場合は、ホスト側のディレクトリを指定する。 |
dst | destination 、target と記述することもできる。コンテナ側のディレクトリを指定する。 |
- 匿名ボリューム
- ホスト側に/var/lib/podman/volumesディレクトリ内に領域が確保されて、指定したコンテナ内のディレクトリと共有される。
- 識別のためにハッシュ値が振られており、同一のネットワークからそのハッシュ値でアクセスすることができる。
podman container run --mount type=volume,dst=<コンテナ内のディレクトリパス 例: /tmp/sample> <コンテナ名/イメージ名:タグ名>
- 名前付きボリューム
- 匿名ボリュームと同様、ホスト側には/var/lib/podman/volumesディレクトリ内に領域が確保されて、指定したコンテナ内のディレクトリと共有される。
- ホスト名を指定するため、同一のネットワークからそのホスト名でアクセスすることができる。
podman container run --mount type=volume,src=<ボリューム名>,dst=<ホスト名>:<コンテナ内のディレクトリパス 例: /tmp/sample> <コンテナ名/イメージ名:タグ名>
- バインドマウント
- ホスト側のカレントディレクトリ内にある指定したディレクトリとコンテナ側の指定したディレクトリが共有される。
podman container run --mount type=bind,src=<ホスト側のディレクトリパス 例: $PWD/host-sample>,dst=<コンテナ内のディレクトリパス 例: /tmp/container-sample> <コンテナ名/イメージ名:タグ名>
ホスト側がSELinuxを使用している場合は、ボリュームのマウントに:Z
オプションを付加する必要がある。
これは、Podmanにボリュームのコンテンツをコンテナ内のラベルと一致するようにラベルを変更するよう指示するものである。
podman run -d --rm -v /<ホスト側のディレクトリのパス 1>/:/<コンテナ側のディレクトリのパス 1>:Z -v /<ホスト側のディレクトリのパス 2>/:/<コンテナ側のディレクトリのパス 2>:Z
ボリュームのアンマウント
podman volume umount <ボリューム名>
特定のコンテナにマウントされているボリュームをアンマウントする。
podman volume umount <コンテナID>
ボリュームの削除
podman volume rm <ボリューム名>
使用されていないボリュームを削除する。
podman volume prune
ボリュームを全て削除する。
podman volume rm $(podman volume ls -q)
コンテナのバックアップ
コンテナをイメージ化してバックアップする。
- コンテナを新しいメージとして作成する。
podman commit <コンテナID> <任意のイメージ名>
- 作成したイメージをファイルとして保存する。
podman save <上記で入力した任意のイメージ名> > <バックアップするファイル名>.tar
バックアップしたコンテナの復元
podman load -i <バックアップしたファイル名>.tar
正常に復元されているかどうかを確認する。
podman images
Podmanに関するプロセスを全て終了する
pkill
コマンドは、Linuxの基本コマンドであり、プロセスの名前や他の属性に基づいてプロセスを終了するために使用する。
これにより、podmanという名前のプロセス (Podmanが起動しているプロセス) を全て終了することができる。
pkill podman
例えば、問題が発生した場合や特定の操作が必要な場合、全てのPodmanプロセスを終了させる手段として使用されることがある。
ただし、注意が必要であり、実行中のコンテナが強制的に停止される可能性がある点に留意する必要がある。
Podmanのストレージ
コンテナ内で発生したデータは同じコンテナ内のどこかに書き込まれるが、コンテナを破棄すると同時に削除される。
コンテナを破棄してもデータは保存する場合、または、他のコンテナで再利用する場合は、コンテナ外にデータ保存領域を作成する機能を提供している。
- ボリューム
- Podmanの管理下でストレージ領域を確保する。
- ルートレスモードのデフォルトでは、~/.local/share/containersディレクトリである。
- 名前付きボリュームと匿名ボリュームがあり、名前付きの場合はホスト内で名前解決できるため簡単にアクセスすることができる。
- 匿名ボリュームは任意のハッシュ値が振られる。
- 他のプロセスからはアクセスできないため安全に使用できる。
- バインドマウント
- ホスト側のディレクトリをコンテナ内のディレクトリと共有する。
- tmpfs
- メモリ上に一時的なストレージ領域を確保する。
- 使用用途としては、機密性の高い情報を一時的にマウントする場合等がある。
-v
オプション、VOLUME
、volumes
で指定する場合に関しても、基本的には上記のいずれかを扱っている。
Containerfile
Containerfileとは
Containerfileは、コンテナイメージの作成手順を自動化する設定ファイルである。
コンテナエンジン (Podman、Buildah、Docker) は、Containerfileから指示を読み取り、イメージの作成に必要なステップを自動化する。
イメージを構築を自動化するには、Containerfileというファイルを作成する必要がある。
Containerfileには、コンテナを構築するためのベースになる環境、実行するコマンド、配置するファイル等が記述されている。
Containerfileには、Containerfileを含むコンテキストディレクトリのパスを引数として、buildah bud
、podman build
コマンドを呼び出す。
PodmanおよびBuildahのデフォルトはContainerfileであり、Dockerfileにフォールバックする。
Containerfileは、Dockerfileと同じシンタックスをサポートしている。
Containerfileで作成したPodmanイメージをQuay.ioにアップロードすることも可能である。
イメージの構築
podman build -t <任意のリポジトリ名>/<任意のタグ名> . # Containerfileのパスを指定する場合 podman build -t <任意のリポジトリ名>/<任意のタグ名> -f <Containerfileのパス>
シンタックス
FROM
FROM <pullするイメージ名>:<タグ名> # 別名を指定する場合 FROM <pullするイメージ名>:<タグ名> AS <別名> # FROM <pullするイメージ名>@<ダイジェスト名> # 別名を指定する場合 FROM <pullするイメージ名>@<ダイジェスト名> AS <別名>
MAINTAINER
MAINTAINERは生成されたイメージの作者フィールドを設定する。
ユーザにサポートのためのEメールもしくはURLを提供する場合に使用する。
MAINTAINER <作者名> <メールアドレス>
USER
コンテナ内のユーザを指定する。
# ユーザをrootにする USER root
WORKDIR
作業ディレクトリを追加する。
WORKDIR <作業ディレクトリパス>
ARG
Containerfile内で使用する変数を定義する。
# 変数を定義する場合 ARG <変数名> # 変数を定義して値を代入する場合 ARG <変数名>=<値>
ENV
環境変数を定義する。
ENV <環境変数名> <値> # または ENV <環境変数名>=<値>
ADD
イメージにファイルやディレクトリを追加する。
# ファイルまたはディレクトリを1つ追加する場合 ADD <ホスト側のファイルまたはディレクトリのパス> <コンテナ側のファイルまたはディレクトリのパス> # ファイルまたはディレクトリを複数追加する場合 ADD <ホスト側のファイルまたはディレクトリのパス 1> <ホスト側のファイルまたはディレクトリのパス 2> ... <コンテナ側のファイルまたはディレクトリのパス> # []で囲むこともできる ADD ["<ホスト側のファイルまたはディレクトリのパス 1>", "<ホスト側のファイルまたはディレクトリのパス 2>" ... "<コンテナ側のファイルまたはディレクトリのパス>"]
COPY
ホスト側のファイルおよびディレクトリをイメージに複製する。
# ファイルまたはディレクトリを1つ追加する場合 COPY <ホスト側のファイルまたはディレクトリのパス> <コンテナ側のファイルまたはディレクトリのパス> # ファイルまたはディレクトリを複数追加する場合 COPY <ホスト側のファイルまたはディレクトリのパス 1> <ホスト側のファイルまたはディレクトリのパス 2> ... <コンテナ側のファイルまたはディレクトリのパス> # []で囲むこともできる COPY ["<ホスト側のファイルまたはディレクトリのパス 1>", "<ホスト側のファイルまたはディレクトリのパス 2>" ... "<コンテナ側のファイルまたはディレクトリのパス>"]
EXPOSE
コンテナ実行時にリッスンするポート番号を指定する。
# ポートを1つ開放する場合 EXPOSE <ポート番号> # ポートを複数開放する場合 EXPOSE <ポート番号 1> <ポート番号 2> ...
ENTRYPOINT
コンテナの起動時に実行する処理を指定する。
# 実行可能コマンドを指定する # 実行可能コマンドは、フルパスを指定しなければならない。 ENTRYPOINT ["<実行可能コマンド>", "<引数 1>", "<引数 2>", "<引数...>"] # シェルで実行するコマンドを指定する : /bin/sh -c "<コマンド> <引数 1> <引数 2> <引数...>" ENTRYPOINT <コマンド> <引数 1> <引数 2> <引数...>
RUN
RUNには2つのシンタックスがある。
# 実行可能コマンドを指定する # 実行可能コマンドは、フルパスを指定しなければならない。 RUN ["<実行可能コマンド>", "<引数 1>", "<引数 2>", "<引数...>"] # シェルで実行するコマンドを指定する : /bin/sh -c "<コマンド> <引数 1> <引数 2> <引数...>" RUN <コマンド> <引数 1> <引数 2> <引数...>
RUN mounts
コンテナにファイルシステムをマウントする。
現在サポートされているマウントの種類は、bind、cache、secret、tmpfsである。
- RUN mountsの全体のオプション
- src / source
- ボリュームおよびbindのマウント元のパスを指定する。 (bindでは必須である)
from
を指定する場合、src
はfrom
フィールドのサブパスになる。
- dst / destination / target
- マウント先の指定する。
- ro / read-only
true
(デフォルト) またはfalse
を指定する。
- src / source
- マウントの種類がbindのみの設定
- bind-propagation
shared
、slave
、private
、rshared
、rslave
、rprivate
(デフォルト)
- bind-nonrecursive
- 再帰的なバインドマウントを設定しない。
- デフォルトでは再帰的である。
- from
- src / sourceのルートのステージ名またはイメージ名を指定する。
- デフォルトはビルドコンテキスト。
- rw / read-write
- マウントへの書き込みを許可する。
- bind-propagation
- マウントの種類がtmpfsのみの設定
- tmpfs-size
- tmpfsマウントのサイズ (バイト)。
- Linuxのデフォルトでは無制限である。
- tmpfs-mode
- tmpfsのファイルモードを8進数で指定する。
- Linuxのデフォルトは1777である。
- tmpcopyup
- tmpfsマウントによりシャドウされるパスは、tmpfs自体に再帰的にコピーされる。
- tmpfs-size
- マウントの種類がcacheのみの設定
- id
- 特定のidに対して、個別のキャッシュディレクトリを作成する。
- mode
- 新しいキャッシュディレクトリのファイルモード (8進数) を指定する。
- デフォルトは0755である。
- ro / readonly
- キャッシュの読み取り専用となる。
- uid
- キャッシュディレクトリのuid。
- gid
- キャッシュディレクトリのgid。
- from
- src / sourceのルートのステージ名を指定する。
- デフォルトはホストキャッシュディレクトリである。
- rw / read-write
- マウントへの書き込みを許可する。
- id
RUN mounts type=<マウントの種類>,<ホスト側のパス>:<コンテナ側のパス> # マウントの種類はbind、ホスト側のパスは/tmp/sample1、コンテナ側のパスは/tmp/sample2の場合 RUN mounts type=bind,source=/tmp/sample1,destination=/tmp/sample2 # マウントの種類はtmpfs、サイズは512[MB]、コンテナ側のパスは/tmp/directoryの場合 RUN mounts type=tmpfs,tmpfs-size=512M,destination=/tmp/directory # マウントの種類はsecret、IDはmysecret、コンテナ側のsecretのパスは/tmp/secret/mysecretの場合 RUN mounts type=secret,id=mysecret cat /run/secrets/mysecret
CMD
ContainerfileのCMDは1つのみ指定できる。
複数のCMDが記述されている場合は、最後のCMDのみが有効になる。
CMDには3つのシンタックスがある。
# 実行可能コマンドを指定する # 実行可能コマンドは、フルパスを指定しなければならない。 # 例: CMD ["/usr/bin/wc","--help"] CMD ["<実行可能コマンド>", "<引数 1>", "<引数 2>", "<引数...>"] # 実行可能ファイルを省略する場合は、ENTRYPOINTにデフォルトの引数を指定する CMD ["<引数 1>", "<引数 2>", "<引数...>"] # シェルで実行するコマンドを指定する : /bin/sh -c "<コマンド> <引数 1> <引数 2> <引数...>" # 例: CMD echo "This is a test." | wc - CMD <コマンド> <引数 1> <引数 2> <引数...>
Podman Desktop
Podman Desktopのインストール
Podman Desktopの公式Webサイト、または、Githubにアクセスして、Podman Desktopをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf podman-desktop-<バージョン>.tar.gz mv podman-desktop-<バージョン> Podman-Desktop
必要ならば、任意のインストールディレクトリに配置する。
mv Podman-Desktop <任意のインストールディレクトリ>
Podman Desktopのデスクトップエントリファイルを作成する。
vi ~/.local/share/applications/Podman-Desktop.desktop
# ~/.local/share/applications/Podman-Desktop.desktopファイル
[Desktop Entry]
Type=Application
Name=Podman Desktop
Exec=/<Podman Desktopのインストールディレクトリ>/podman-desktop %F
Icon=io.podman_desktop.PodmanDesktop
Categories=Development;
StartupWMClass=Podman Desktop
Terminal=false
Docker Hubの使用
Docker Hubにログインする。
podman login -u <Docker Hubのユーザ名> -v https://docker.io podman login -u <Docker Hubのユーザ名> -v https://index.docker.io/v2/
Podman Desktopを再起動する。
認証情報は、/run/user/$UID/containers/auth.jsonファイルに保存される。
ルートレスモード
ルートレスモードとは
Podmanはsetuidパッケージが不要であり、一般ユーザとしてコンテナを実行することができる。
ルートレスモードで実行する場合、Podmanコンテナはユーザネームスペースを使用して、コンテナ内のrootをPodmanを実行しているユーザに設定する。
ルートレスモードのPodmanは、コンテナを実行しているユーザには無い特権は持たず、ロックダウンされたコンテナを実行する。
これらの制限の一部は (例えば、--privileged
オプションを付加して) 解除できるが、ルートレスコンテナが起動したユーザ以上の権限を持つことはない。
一般ユーザとしてPodmanを実行する時、ホストから/etc/passwdにマウントした場合でも、一般ユーザには権限が無いため変更することはできない。
PodmanとDockerの違い
DockerとPodmanの違いの1つは、コンテナの扱い方である。
Dockerは、コンテナを実行するためにスーパーユーザ権限を必要とする。
Podmanは、スーパーユーザ権限無しでコンテナを実行することができる。
例えば、ルートレスモードのPodmanでは、ポート番号が1024番未満のポートでコンテナを起動することはできないため、1024番以上のポートを使用する必要がある。
もし、1024番未満のポートでコンテナを作成する必要がある場合は、ルートレスモードを解除してスーパーユーザ権限で実行する。
podman machine set --rootful
ルートレスモードに戻す場合は、以下に示すコマンドを実行する。
podman machine set --rootful=false
しかし、Dockerには、コンテナを作成および管理するためDocker Composeが存在する。
幸運なことに、PodmanはDocker CLIをエミュレートできるため、Docker Composeと連携することができる。
ルートレスコンテナの保存先
ルートレスコンテナのイメージは、~/.local/share/containers/storage
ディレクトリに保存される。
ルートレスコンテナの設定ファイルは、~/.config/containers
ディレクトリに保存される。
firewalldの設定 (ポートフォワード)
ルートレスコンテナにおいて、一般ユーザは、ルートレスコンテナのWebサーバをホスト側の80番ポートで公開することができない。
(1024番未満のポートを公開することができない)
そのため、1024番未満のポートでサービスを公開する場合は、firewalldでポートフォワードを設定して、ポートをマッピングする必要がある。
sudo firewall-cmd --permanent --add-forward-port=port=<ホスト側のフォワード先のポート番号>:proto=tcp:toport=<Podmanのコンテナで設定したフォワード先のポート番号> sudo firewall-cmd --permanent --add-port=<ホスト側のフォワード先のポート番号>/tcp sudo firewall-cmd --reload
k8sマニフェストとの連携
Podmanは、k8sマニフェストを作成および実行することも可能である。
これは、k8s Podの開発に有効である。
k8sマニフェストの作成
k8sマニフェストを作成元となるPodmanのコンテナを実行する。
podman container start <コンテナ名 または コンテナID>
k8sマニフェストを生成する。
podman generate kube <コンテナ名 または コンテナID> > <k8sマニフェストのファイル名>.yml
k8s Podの作成
k8sマニフェストを使用して、k8s Podを作成する。
kubectl create -f <k8sマニフェストのファイル名>.yml
k8sマニフェストの実行
k8sマニフェストの作成元のコンテナを削除する。
podman container stop <コンテナ名 または コンテナID> podman container rm <コンテナ名 または コンテナID>
k8sマニフェストを実行して、コンテナを実行する。
podman play kube <k8sマニフェストのファイル名>.yml
k8sマニフェストを作成したコンテナが実行されているかどうかを確認する。
podman ps
エラー関連
実行権限エラー
containerfileファイルまたはcontainer-compose.ymlファイルを使用する時、以下に示すようなエラーが出力される場合がある。
error checking context: 'no permission 〜'
この時、Containerfileファイルまたはcontainer-compose.ymlファイルに実行権限を付加する。
chmod 755 containerfile # または container-compose.yml
Systemdエラー
openSUSEコンテナをPodmanコンテナとして動作する時、以下のようなエラーが出力されてSystemdサービスが起動できない。
Failed to connect to bus: No such file or directory.
これは、Podmanコンテナを実行する時、initシステムを実行していないからである。
systemctl
コマンドは、dbusを介してsystemdと通信するプロセスである。
openSUSEコンテナでは、dbusとsysvinitがインストールされていないため(dbusやsystemdが動作していない)、systemctl
コマンドは失敗する。
Podmanコンテナでsystemctl
を実行するには、その依存関係をインストールして、特殊なコマンドを実行する必要がある。
containerfileを作成および使用して解決する手順を、以下に記載する。
まず、以下のようなdockerfileを作成する。
FROM opensuse/leap:15.3 MAINTAINER Annonymas RUN zypper update -y RUN zypper install -y dbus-1 systemd-sysvinit RUN cp /usr/lib/systemd/system/dbus.service /etc/systemd/system/; \ sed -i 's/OOMScoreAdjust=-900//' /etc/systemd/system/dbus.service VOLUME ["/sys/fs/cgroup", "/run"] CMD ["/sbin/init"] EXPOSE 22 EXPOSE 80
次に、作成したcontainerfileからPodmanイメージを作成する。
podman build -t <イメージ名>:<タグ名> -f <containerfile名> . # イメージ名:タグ名およびDockerfile名(Dockerfile名がdockerfileの場合のみ)は省略できる 例. podman build -t suse153i .
Podmanコンテナを実行する。
podman run -d --name=<コンテナ名> --hostname <コンテナのホスト名> <ポートマッピングする場合: -p <ホストのポート番号>:<コンテナのポート番号>> --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro <イメージ名> 例. podman run -d --name=suse153c --hostname suse153 -p 50080:80 --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro suse153i # 開始しているコンテナ内にアクセスする場合 podman exec -it <コンテナ名> /bin/bash 例. podman exec -it suse153c /bin/bash # 停止したコンテナを開始する場合 podman container start <コンテナ名> 例. podman container start suse153c
openSUSEコンテナにおいて、systemctl
コマンドが実行できるかどうかを確認する。
# Podmanコンテナ内に入る podman exec -it <コンテナIDまたはコンテナ名> /bin/bash # systemctlコマンドが実行できるかどうかを確認 systemctl list-units
Systemdサービスのサポート
openSUSEコンテナリポジトリで公開されているコンテナイメージは、containers-systemdパッケージがインストールされている。
例えば、Systemdサービスを使用してNginXコンテナを設定して、自動的に起動するためのSystemdサービスファイルとSysconfigファイルが含まれている。