「インストール - Podman」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
 
(同じ利用者による、間の41版が非表示)
1行目: 1行目:
== 概要 ==
== 概要 ==
コンテナとは、ソフトウェアプロセスやマイクロサービスをパッケージ化して、あらゆるコンピューティング環境で実行可能にするソフトウェアソリューションである。<br>
コンテナとは、Linuxシステム上で実行される、互いに隔離されたプロセス群のことである。<br>
また、ソフトウェアプロセスやマイクロサービスをパッケージ化して、あらゆるコンピューティング環境で実行可能にするソフトウェアソリューションである。<br>
<br>
コンテナは、1つのプロセス・グループがシステム上の他のプロセスに干渉しないようにする。<br>
<br>
<br>
コンテナに含まれるファイルには、アプリケーションコード、環境変数、設定コード、バイナリプログラム、ソフトウェアの依存関係、ライブラリ等がある。<br>
コンテナに含まれるファイルには、アプリケーションコード、環境変数、設定コード、バイナリプログラム、ソフトウェアの依存関係、ライブラリ等がある。<br>
7行目: 10行目:
このイメージは、クラウド、オンプレミスのデータシステム、ローカルシステム等、あらゆるプラットフォームにデプロイされる。<br>
このイメージは、クラウド、オンプレミスのデータシステム、ローカルシステム等、あらゆるプラットフォームにデプロイされる。<br>
<br>
<br>
Podman (Pod Manage) は、Open Container Initiatives (OCI) のコンテナイメージを開発、管理、本番環境で実行する時に使用するコンテナエンジンである。<br>
また、不正なプロセスがシステム・リソースを独占することはできず、他のプロセスがタスクを実行するのを妨げることもできる。<br>
悪意のあるコンテナであったとしても、他のコンテナを攻撃したり、データを盗んだり、サービス拒否攻撃を引き起こしたりすることもできない。<br>
<br>
コンテナの最終的な目標は、同じライブラリの異なるバージョンを必要とするアプリケーションと競合しないように、<br>
共有ライブラリの独自のバージョンでアプリケーションをインストールできるようにすることある。<br>
その代わり、コンテナによってアプリケーションは仮想化された環境に住むことができ、あたかもシステム全体を所有しているかのような印象を与えることができる。<br>
<br>
Podman (Pod Manager) は、Open Container Initiatives (OCI) のコンテナイメージを開発、管理、本番環境で実行する時に使用するコンテナエンジンである。<br>
Podmanプロジェクトは、Podmanを<u>Linuxシステム上でOCIコンテナを開発、管理、実行するためのデーモンレス・コンテナ・エンジン</u>と説明している。<br>
<br>
OCIは、コンテナフォーマットとランタイムに関するOSレベルの仮想化ソフトウェアコンテナのオープンなガバナンス構造を実装するために設計された。<br>
OCIは、コンテナフォーマットとランタイムに関するOSレベルの仮想化ソフトウェアコンテナのオープンなガバナンス構造を実装するために設計された。<br>
<br>
<br>
Podmanコンテナは、スーパユーザ / 非スーパーユーザのいずれでも実行可能である。<br>
Podmanコンテナは、スーパユーザ / 非スーパーユーザのいずれでも実行可能である。<br>
<br>
PodmanはDockerと同じコマンドラインでDockerができることのほとんど全てを行うことができるため、Docker = Podmanという単純な行のエイリアスで要約されることが多い。<br>
しかし、Podmanはそれ以上のことができる。<br>
<br>
Dockerを理解することはPodmanを理解する上で重要ではないが役立つこともある。<br>
<br><br>
== コンテナ・オーケストレータ / コンテナ・エンジン / コンテナ・ランタイム ==
コンテナの世界では、コンテナ・オーケストレータ、コンテナ・エンジン、コンテナ・ランタイムといった用語が同じ意味で用いられることがよくある。<br>
<br>
==== コンテナ・オーケストレータ ====
コンテナを複数の異なるマシンやノードにオーケストレートするソフトウェアプロジェクトや製品のことである。<br>
これらのオーケストレータは、コンテナを実行するためにコンテナエンジンと通信する。<br>
<br>
主要なコンテナ・オーケストレータはKubernetesで、元々はDockerデーモンのコンテナ・エンジンと通信するように設計されていたが、<br>
Kubernetesはコンテナ・エンジンとして主にCRI-Oまたはcontainerdを使用しているため、Dockerを使用することは時代遅れになりつつある。<br>
<br>
CRI-Oとcontainerdは、オーケストレーションされたKubernetesコンテナを実行するために構築されている。<br>
<br>
Docker SwarmおよびApache Mesosも、コンテナ・オーケストレータである。<br>
<br>
==== コンテナ・エンジン ====
主に、コンテナ化されたアプリケーションを単一のローカル・ノードで実行するように構成するために使用される。<br>
ユーザ、管理者、開発者が直接起動できる。<br>
<br>
また、ブート時にSystemdユニットファイルから起動したり、Kubernetesのようなコンテナ・オーケストレータから起動することもできる。<br>
<br>
前述したように、CRI-Oとcontainerdは、Kubernetesがコンテナをローカルで管理するために使用するコンテナエンジンである。<br>
一般的に、ユーザが直接使用することは想定されていない。<br>
<br>
DockerとPodmanは、コンテナ化されたアプリケーションを1台のマシンで開発、管理、実行するためにユーザが使用する主要なコンテナエンジンである。<br>
<br>
PodmanがKubernetesのコンテナ起動に使われることはほとんどない。<br>
<br>
Buildahもコンテナエンジンの1つであるが、コンテナイメージの構築にしか使用されない。<br>
<br>
==== Open Container Initiative (OCI) コンテナ・ランタイム ====
Linuxカーネルの様々な部分を設定して、最後にコンテナ化されたアプリケーションを起動する。<br>
最も一般的に使用される2つのコンテナ・ランタイムは、runcとcrunである。<br>
<br>
KataとgVisorも、コンテナ・ランタイムである。<br>
<br>
<u>※注意</u><br>
<u>Open Container Initiative (OCI) は、コンテナフォーマットとランタイムに関するオープンな業界標準を作成することを主な目的とした標準化団体である。</u><br>
<u>詳細を知りたい場合は、https://opencontainers.org を参照すること。</u><br>
<br>
下図は、オープンソース・コンテナ・プロジェクトがどのカテゴリーに当てはまるかを示している。<br>
[[ファイル:Container 1.png|中央]]
<br><br>
<br><br>


108行目: 168行目:
<br>
<br>
conmonのビルドに必要なライブラリをインストールする。<br>
conmonのビルドに必要なライブラリをインストールする。<br>
# RHEL
sudo dnf install meson ninja glib2-devel glibc-devel libseccomp-devel
  # SUSE
  # SUSE
  sudo zypper install meson ninja glib2-devel libseccomp-devel
  sudo zypper install meson ninja glib2-devel glibc-devel libseccomp-devel
<br>
<br>
[https://github.com/containers/conmon conmonのGithub]にアクセスして、ソースコードをダウンロードする。<br>
[https://github.com/containers/conmon conmonのGithub]にアクセスして、ソースコードをダウンロードする。<br>
132行目: 195行目:
最新バージョンのcrun /runcがシステムにインストールされていることが期待される。<br>
最新バージョンのcrun /runcがシステムにインストールされていることが期待される。<br>
crun /runcは、Podmanによりその1つがデフォルトのランタイムとしてピックアップされる。(crunはruncよりも優先される)<br>
crun /runcは、Podmanによりその1つがデフォルトのランタイムとしてピックアップされる。(crunはruncよりも優先される)<br>
<br>
crun / runcのビルドに必要なライブラリをインストールする。<br>
# SUSE
sudo zypper install libseccomp-devel libapparmor-devel libselinux-devel
<br>
<br>
[https://github.com/opencontainers/runc/ crun /runcのGithub]にアクセスして、ソースコードをダウンロードする。<br>
[https://github.com/opencontainers/runc/ crun /runcのGithub]にアクセスして、ソースコードをダウンロードする。<br>
143行目: 210行目:
<br>
<br>
crun /runcをビルドおよびインストールする。<br>
crun /runcをビルドおよびインストールする。<br>
# AppArmor, SECcompを有効にする場合
make BUILDTAGS="apparmor seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc)
  # SELinux, SECcompを有効にする場合
  # SELinux, SECcompを有効にする場合
  make BUILDTAGS="selinux seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc)  
  make BUILDTAGS="selinux seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc)  
151行目: 221行目:
  make PREFIX=<Podmanのインストールディレクトリ> install
  make PREFIX=<Podmanのインストールディレクトリ> install
<br>
<br>
===== slirp4netnsのインストール =====
===== slirp4netnsのインストール =====
slirp4netnsは、コンテナのネットワーク機能を提供するために使用されるライブラリである。<br>
<br>
Podmanがルートレス環境でコンテナのネットワーク機能を提供するために重要な役割を果たしている。<br>
これにより、ユーザはroot権限を必要とせずにコンテナを実行して、ネットワークを利用できるようになる。<br>
また、各コンテナが独立したネットワーク環境を持つことにより、セキュリティと分離性が向上する。<br>
<br>
主な役割を以下に示す。<br>
* ユーザ空間ネットワーキング
*: slirp4netnsは、カーネル空間ではなくユーザ空間でネットワーキングを実現する。
*: これにより、ルートレス環境でもコンテナがネットワーク機能を利用できるようになる。
*: <br>
* ネットワーク名前空間の分離
*: 各コンテナに独立したネットワーク名前空間を提供して、ホストから分離されたネットワーク環境を実現する。
*: <br>
* ネットワークアドレス変換 (NAT)
*: コンテナ内部のIPアドレスをホストのIPアドレスに変換することで、外部ネットワークとの通信を可能にする。
*: <br>
* ポートフォワーディング
*: コンテナ内部のポートをホストのポートに転送して、外部からコンテナが公開するサービスにアクセスできるようにする。
*: <br>
* DNS解決
*: コンテナ内部からDNSを利用してホスト名の解決ができるようにする。
<br>
slirp4netnsのビルドに必要なライブラリをインストールする。<br>
slirp4netnsのビルドに必要なライブラリをインストールする。<br>
  # RHEL
  # RHEL
251行目: 345行目:
  export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
  export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
  </syntaxhighlight>
  </syntaxhighlight>
<br>
===== catatonitのインストール =====
catatonitは、PodmanやDocker等のコンテナランタイムが、コンテナ内のプロセスを正しく管理するために使う補助的なツールである。<br>
ポッドは、Kubernetes等のオーケストレーションツールで使用される複数のコンテナを1つにまとめた単位であるが、ポッド自体の作成や管理はKubernetesの制御プレーンやAPIサーバが行う。<br>
<br>
catatonitは、コンテナのinitプロセスとして使用される小さなプログラムである。<br>
Podmanや他のコンテナランタイムでは、コンテナ内でプロセスが正しく動作および終了するためにinitプロセスを使用することが一般的である。<br>
catatonitはそのための軽量な選択肢の1つであり、特にリソースの少ない環境やシンプルなコンテナイメージでの使用に適している。<br>
<br>
コンテナのinitプロセスは、コンテナ内で最初に実行されるプロセスであり、次のような役割を果たす。<br>
* 孤児プロセスの回収
*: コンテナ内で起動されたプロセスが終了した時、その親プロセスが終了している場合、プロセスが孤児化される。
*: initプロセスはこれらの孤児プロセスを回収して、適切に終了させる。
*: <br>
* シグナルの管理
*: catatonitは、コンテナに送信されるシグナルをキャッチして、適切にハンドリングする。
*: これにより、コンテナ内で実行中のプロセスがシグナルを受信できるようにする。
*: <br>
* リソースのクリーンアップ
*: コンテナが終了する時、catatonitはシステムリソースを適切にクリーンアップする。
<br>
[https://github.com/openSUSE/catatonit catatonitのGithub]にアクセスして、ソースコードをダウンロードする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf catatonit.tar.xz
cd catatonit
<br>
または、<code>git clone</code>コマンドを実行してソースコードをダウンロードすることもできる。<br>
git clone https://github.com/openSUSE/catatonit.git
cd catatonit
<br>
catatonitをビルドおよびインストールする。<br>
./autogen.sh
mkdir build && cd build
../configure --prefix=<Podmanのインストールディレクトリ>
make -J $(nproc)
make install
<br>
===== 最新のnetavarkが必要な場合 =====
最新バージョンのnetavarkをインストールする場合、ソースコードからインストールする。<br>
<br>
netavarkはコンテナ用のRustベースのコンテナネットワークスタックである。<br>
Podmanで動作するように設計されているが、他のOCIコンテナ管理アプリケーションにも適用できる。<br>
<br>
netavarkのビルドに必要なライブラリをインストールする。<br>
# SUSE
sudo zypper install rust cargo protobuf-devel go-md2man
<br>
[https://github.com/containers/netavark netavark]のGithubにアクセスして、ソースコードをダウンロードする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf netavark-<バージョン>.tar.gz
cd netavark-<バージョン>
<br>
netavarkをビルドおよびインストールする。<br>
make PREFIX=<Podmanのインストールディレクトリ> -j $(nproc)
make PREFIX=<Podmanのインストールディレクトリ> install
<br>
==== エラー関連 ====
===== Seccompエラー =====
Podmanイメージのビルド時において、以下に示すようなエラーが出力される場合がある。<br>
Error: loading seccomp profile () failed: seccomp not enabled in this build
<br>
Podmanイメージでは、Seccompを無効にしている場合はコンテナを作成できないイメージが存在する。<br>
この時、runc / crunおよびPodmanのビルド時において、<code>BUILDTAGS</code>オプションに<code>seccomp</code>を指定する必要がある。<br>
<br><br>
== gvproxy ==
==== gvproxyとは ====
gvproxyは、libslirpおよびVPNKitを置き換えるものであり、Golangで記述されている。<br>
gVisorのネットワークスタックをベースにしている。<br>
<br>
libslirpと比較して、gvisor-tap-vsockは設定可能なDNSサーバと動的なポート転送を提供する。<br>
<br>
また、QEMU、Hyperkit、Hyper-V、User Mode Linuxで使用することができる。<br>
<br>
<u>※注意 1</u><br>
<u>SUSEにおいて、パッケージ管理システムにgvproxyパッケージが存在しないため、手動でgvproxyをインストールする必要がある。</u><br>
<br>
<u>※注意 2</u><br>
<u><code>podman machine start</code>コマンドを実行して仮想マシンを起動する時、gvproxyが無いためホストネットワークを起動できない場合がある。</u><br>
<u>この時、以下に示すセクションを参照して、gvproxyをインストールする必要がある。</u><br>
<br>
==== Staticビルド済みのバイナリをインストール ====
まず、[https://github.com/containers/gvisor-tap-vsock/ gvproxyのGithub]にアクセスして、gvproxyをダウンロードする。<br>
ダウンロードしたgvproxyのファイル名を変更して、/usr/libexec/podmanディレクトリまたは/usr/local/libexec/podmanディレクトリにコピーする。<br>
# ファイル名を変更
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
<br>
==== ソースコードからインストール ====
gvproxyのビルドに必要なライブラリをインストールする。<br>
# SUSE
sudo zypper install rust cargo protobuf-devel go-md2man
<br>
[https://github.com/containers/gvisor-tap-vsock.git gvproxyのGithub]にアクセスして、ソースコードをダウンロードする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf gvisor-tap-vsock-<バージョン>.tar.gz
cd gvisor-tap-vsock-<バージョン>
<br>
gvproxyをビルドする。<br>
make -j $(nproc)
<br>
binディレクトリに実行バイナリ群が生成される。<br>
そのため、それらの実行バイナリ群をPodmanのインストールディレクトリに配置する。<br>
cd bin
mv ./*  /<Podmanのインストールディレクトリ>/bin
<br><br>
== Podmanに関連するディレクトリ ==
Podmanに関連するディレクトリを以下に示す。<br>
これらのディレクトリは、Podmanとその関連ツール (Podman Desktop) によって使用されており、rootlessモードで実行する時にユーザのホームディレクトリ配下に作成される。<br>
<br>
* ~/.local/share/containers/storage
*: Podmanが使用するメインのストレージディレクトリである。
*: コンテナイメージ、コンテナ、ボリューム等のデータが格納される。
* ~/.local/share/containers/podman-desktop
*: Podman Desktopアプリケーションが使用するディレクトリである。
*: GUIベースのPodman管理ツールの設定やデータが保存される。
* ~/.local/share/containers/cache
*: Podmanのキャッシュディレクトリである。
*: イメージレイヤーのキャッシュやその他の一時的なデータが保存される。
*: キャッシュを使用することにより、同じイメージの再ダウンロードを避け、操作を高速化する。
<br><br>
<br><br>


271行目: 503行目:
  export DOCKER_HOST="unix://<Podmanソケットファイルのパス>"
  export DOCKER_HOST="unix://<Podmanソケットファイルのパス>"
  </syntaxhighlight>
  </syntaxhighlight>
<br>
==== cgroup v1に関する警告 ====
<code>podman</code>コマンドを実行した時、以下に示すような警告が出力される時がある。<br>
Using cgroups-v1 which is deprecated in favor of cgroups-v2 with Podman v5 and will be removed in a future version.
Set environment variable `PODMAN_IGNORE_CGROUPSV1_WARNING` to hide this warning.
<br>
この警告は、Podman 5.0以降はcgroups v1の使用が非推奨となり、将来のバージョンでは削除される予定であることを示している。<br>
これは、以下に示すような原因がある。<br>
* システムがcgroups-v1を使用している場合。
*: 現在のシステムがcgroups-v1を使用しており、Podmanもそれを検出して使用している。
*: しかし、Podman v5以降ではcgroups-v2の使用が推奨されている。
* Podmanのバージョン
*: 使用しているPodmanのバージョンが5.0以降であるため、この警告メッセージが表示されている。
<br>
この警告は、将来的にcgroups v1のサポートが終了することを事前に知らせるためのものである。<br>
現時点ではcgroups v1を使用していても問題ないが、将来のバージョンではcgroups v2に移行する必要がある。<br>
<br>
警告を非表示にするには、~/.profileファイル等に環境変数<code>PODMAN_IGNORE_CGROUPSV1_WARNING</code>を<code>1</code>、または、<code>true</code>、または、<code>yes</code>に設定する。<br>
ただし、これは警告を非表示にするだけで、根本的な問題は解決しない。<br>
<br>
vi ~/.profile
<br>
<syntaxhighlight lang="sh">
# ~/.profileファイル
# 上記の警告を非表示にする
export PODMAN_IGNORE_CGROUPSV1_WARNING=1
# Podmanの設定ファイルのパスを指定
export CONTAINERS_CONF="$HOME/.config/containers/containers.conf"
</syntaxhighlight>
<br>
長期的には、システムをcgroups v2に移行することを検討する。<br>
cgroups v2は、より効率的でシンプルなリソース管理機能を提供している。<br>
移行には、カーネルのアップグレード、または、関連するツールやライブラリの対応が必要となる場合がある。<br>
<br>
SUSEのcgroupのデフォルトモードはハイブリッドモードである。<br>
ハイブリッドモードは、それを必要とするアプリケーションに後方互換性を提供する。<br>
<br>
以下に示す機能はunified v2階層でのみ使用可能である。<br>
* メモリコントローラ
*: 再生保護(別名 memory.low)、memory.high、PSI(圧力ストール情報)
* I/Oコントローラ
*: ライトバック制御、新しい制御ポリシー
* 非特権ユーザへのコントローラ委譲 (ルートレスコンテナ)
* systemd のフリーザサポート
* 単一階層の取り扱いがよりシンプルになる。
<br>
cgroupは、1つのモードしか設定できない。<br>
<br>
現在のPCにおいて、cgroups v2が有効になっているかどうかを確認する。<br>
sudo mount | grep cgroup2
# cgroups v2が有効になっている場合
# 出力にcgroup v2のエントリが含まれている場合は、cgroups v2が有効になっている
# 出力例: cgroups v2が有効になっている場合
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
<br>
vi ~/.config/containers/containers.conf
# または
sudo vi /etc/containers/containers.conf
<br>
<syntaxhighlight lang="ini">
[engine]
cgroup_manager = "systemd"
cgroups = "v2"
</syntaxhighlight>
<br>
もし、上記の手順で解決しない場合は、GRUB2のブートオプションに設定を追加する。<br>
統一制御グループ階層を有効にする場合は、GRUB2ブートローダのカーネルコマンドラインパラメータとして追加する。<br>
sudo vi /etc/default/grub
<br>
# /etc/default/grubファイル
GRUB_CMDLINE_LINUX_DEFAULT="〜 systemd.unified_cgroup_hierarchy=1 〜"
<br>
GRUB2を更新する。<br>
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
<br>
Linuxを再起動する。<br>
sudo shutdown -r now
<br>
<br>


==== Linux仮想マシンの作成と開始 ====
==== Linux仮想マシンの作成と開始 ====
===== Linux仮想マシン (Podman Machine) とは =====
Podman Machineを理解するには、まず、Podmanのアーキテクチャについて知る必要がある。<br>
<br>
Linuxでは、Podmanはデフォルトでrootless (非特権) モードで動作できるため、直接コンテナが実行できる。<br>
<u>Linuxでは、以下に示すようなLinuxカーネルの機能 (コンテナ実行に必要な機能が最初から利用可能) を直接利用できるできるため、</u><br>
<u>Podman Machineは不要であり、podman run等のコマンドが直接実行できる。</u><br>
* namespaces
* cgroups
* SELinux / AppArmor等
<br>
Windows / MacOSでは、Linuxコンテナをネイティブに実行できないため、仮想マシンを介してLinux環境を用意する必要があるため、仮想マシン (VM) が必要になる。<br>
この仮想マシンを<u>Podman Machine</u>と呼ぶ。<br>
<br>
podman machineコマンドの役割を以下に示す。<br>
* Windows / MacOS環境で必要な仮想マシンを起動すること。
* 仮想マシン内でPodmanデーモンを開始すること。
* ホストOSからコンテナを操作できるような環境を準備すること。
<br>
podman machineコマンドを実行せずにpodman runコマンド等が使用できる環境は、以下の通りである。<br>
* ホストOSがLinux
* Podman Machineが自動的に設定・起動されている状態
<br>
===== Linux仮想マシンの初期化 =====
===== Linux仮想マシンの初期化 =====
コンテナが実行される新しいLinux仮想マシンを初期化する。<br>
コンテナが実行される新しいLinux仮想マシンを初期化する。<br>
282行目: 617行目:
一般的なFedora CoreOSのアップグレードは14日ごとに行われるが、自動アップデートのZincataはPodmanマシンでは無効になっている。<br>
一般的なFedora CoreOSのアップグレードは14日ごとに行われるが、自動アップデートのZincataはPodmanマシンでは無効になっている。<br>
<br>
<br>
もし、LinuxホストでPodman Machineを作成した場合は、~/.local/share/containers/podman/machineディレクトリに初期ファイルが生成される。<br>
これは、2[GB]程度の容量が必要なため、Linux上ではPodman Machineは不要であることから削除することを推奨する。<br>
<br>
===== Linux仮想マシンの編集 =====
===== Linux仮想マシンの編集 =====
<u>Podmanをソースコードから任意のディレクトリにインストールした場合、</u><br>
<u>Podmanをソースコードから任意のディレクトリにインストールした場合、</u><br>
338行目: 677行目:
Podmanの動作を確認するため、テストイメージをダウンロードして実行する。<br>
Podmanの動作を確認するため、テストイメージをダウンロードして実行する。<br>
   podman run hello-world
   podman run hello-world
<br><br>
== 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/
<br>
認証情報は、/run/user/$UID/containers/auth.jsonファイルに保存される。<br>
<br>
Docker Hubにログインすることにより、Podmanコマンドで[https://hub.docker.com Docker Hub]からイメージを検索およびダウンロードすることができる。<br>
<br>
==== Podmanイメージの検索 ====
[https://quay.io/search Quay] (デフォルト) および他のWebサイト (登録している場合) からイメージを検索およびダウンロードする。<br>
podman search <イメージ名>
<br>
==== Podmanイメージのダウンロード ====
podman pull <イメージ名>
# 例: Ubuntuの公式イメージをダウンロード
podman pull ubuntu
# 例: Docker HubからApache2のイメージをダウンロード
podman pull docker.io/httpd:latest
<br>
==== ダウンロードしたPodmanイメージの一覧の表示 ====
podman images
<br>
==== Podmanイメージの削除 ====
podman image rm <イメージID>
<br>
Podmanイメージを全て削除する。<br>
podman image rm -f $(podman images -q)
<br>
==== Podmanコンテナの削除 ====
podman container rm <コンテナID>
<br>
Podmanコンテナを全て削除する。<br>
podman container rm -f $(podman container ps -a -q)
<br>
==== コンテナの起動 ====
podman run --name <コンテナ名> -d <イメージ名>
# 例: イメージ名はubuntu、コンテナ名はubuntu01として起動
podman run --name ubuntu01 -itd ubuntu /bin/bash
# 例: イメージ名はhttpd、コンテナ名はwwwとして起動
#    また、コンテナ内の80番ポートをホスト側の8080番にポートフォワーディングしている
podman run --name www -p 8080:80 -d httpd
<br>
==== コンテナのプロセス確認 ====
# 動作中のコンテナのみ表示
podman ps
# 全てのコンテナを表示
podman ps -a  または podman ps --all
<br>
==== コンテナの停止 ====
コンテナが停止している時は、STATUSでExitedとなる。<br>
podman stop <コンテナ名>  または  podman stop <コンテナID>
<br>
==== コンテナのログ確認 ====
例えば、コンテナが起動せずに失敗する (exited) する場合、ログを確認する。<br>
podman logs <コンテナID>
<br>
==== コンテナに名前を付ける ====
podman commit <コンテナID> <任意のコンテナ名>
<br>
==== コマンドの実行 ====
起動中のコンテナにコマンドを実行する。<br>
podman exec -it <コンテナ名> /bin/bash
<br>
==== コンテナとホスト間のファイルコピー ====
ホストからコンテナにファイルをコピーする。<br>
podman cp <ホストのファイルパス> <コンテナ名:コンテナ内の保存先>
# または
podman cp <ホストのファイルパス> <コンテナID:コンテナ内の保存先>
# 例:
podman cp sample.txt my_suse:/tmp  # コンテナを実行
podman exec -it my_suse /bin/bash  # cd /tmp && lsコマンドを実行してファイルを確認
<br>
コンテナからホストにファイルをコピーする。<br>
podman cp <コンテナ名:コンテナ内のファイルパス> <ホストの保存先>
# または
podman cp <コンテナID:コンテナ内のファイルパス> <ホストの保存先>
# 例:
podman cp my_suse:/tmp/sample.txt ~/Downloads
<br>
==== ボリュームのマウント ====
コンテナにボリュームをマウントする。<br>
<br>
<code>-v</code>オプションの代わりに<code>--mount</code>オプションを付加することが推奨されている。<br>
<code>--mount</code>オプションは、キーバリュー形式で各要素が指定できる。<br>
podman container run -it --mount type=<volume, bind, tmpfsのいずれかを指定>,src=<ボリューム名>,dst=<コンテナ内のパス> <コンテナ名/イメージ名:タグ名>
<br>
<code>--rm</code>オプションを付加することにより、匿名ボリュームの場合はコンテナ停止と同時にボリュームも破棄される。<br>
名前付きボリュームの場合は、<code>--rm</code>オプションを付加しても、ボリュームは破棄されない。<br>
<br>
<center>
{| class="wikitable" | style="background-color:#fefefe;"
|+ mountオプションについて
|-
! style="background-color:#66CCFF;" | mountオプションで指定できる種類
! style="background-color:#66CCFF;" | 説明
|-
| style="text-align: center;" | type || <code>volume</code>、<code>bind</code>、<code>tmpfs</code>を指定する。
|-
| style="text-align: center;" | src || <code>source</code>と記述することもできる。<br><br>匿名ボリュームの場合は、省略する。<br>名前付きボリュームの場合は、その名前を記述する。<br>バインドマウントの場合は、ホスト側のディレクトリを指定する。
|-
| style="text-align: center;" | dst || <code>destination</code>、<code>target</code>と記述することもできる。<br><br>コンテナ側のディレクトリを指定する。
|}
</center>
<br>
* 匿名ボリューム
*: ホスト側に/var/lib/podman/volumesディレクトリ内に領域が確保されて、指定したコンテナ内のディレクトリと共有される。
*: 識別のためにハッシュ値が振られており、同一のネットワークからそのハッシュ値でアクセスすることができる。
*: <code>podman container run --mount type=volume,dst=<コンテナ内のディレクトリパス  例: /tmp/sample> <コンテナ名/イメージ名:タグ名></code>
*: <br>
* 名前付きボリューム
*: 匿名ボリュームと同様、ホスト側には/var/lib/podman/volumesディレクトリ内に領域が確保されて、指定したコンテナ内のディレクトリと共有される。
*: ホスト名を指定するため、同一のネットワークからそのホスト名でアクセスすることができる。
*: <code>podman container run --mount type=volume,src=<ボリューム名>,dst=<ホスト名>:<コンテナ内のディレクトリパス  例: /tmp/sample> <コンテナ名/イメージ名:タグ名></code>
*: <br>
* バインドマウント
*: <u>ホスト側のカレントディレクトリ内</u>にある指定したディレクトリとコンテナ側の指定したディレクトリが共有される。
*: <code>podman container run --mount type=bind,src=<ホスト側のディレクトリパス  例: $PWD/host-sample>,dst=<コンテナ内のディレクトリパス  例: /tmp/container-sample> <コンテナ名/イメージ名:タグ名></code>
<br>
==== ボリュームのアンマウント ====
podman volume umount <ボリューム名>
<br>
特定のコンテナにマウントされているボリュームをアンマウントする。<br>
podman volume umount <コンテナID>
<br>
==== ボリュームの削除 ====
podman volume rm <ボリューム名>
<br>
使用されていないボリュームを削除する。<br>
podman volume prune
<br>
ボリュームを全て削除する。<br>
podman volume rm $(podman volume ls -q)
<br>
==== コンテナのバックアップ ====
コンテナをイメージ化してバックアップする。<br>
<br>
# コンテナを新しいメージとして作成する。
#: <code>podman commit <コンテナID> <任意のイメージ名></code>
# 作成したイメージをファイルとして保存する。
#: <code>podman save <上記で入力した任意のイメージ名> > <バックアップするファイル名>.tar</code>
<br>
==== バックアップしたコンテナの復元 ====
podman load -i <バックアップしたファイル名>.tar
<br>
正常に復元されているかどうかを確認する。<br>
podman images
<br>
==== Podmanに関するプロセスを全て終了する ====
<code>pkill</code>コマンドは、Linuxの基本コマンドであり、プロセスの名前や他の属性に基づいてプロセスを終了するために使用する。<br>
これにより、<u>podman</u>という名前のプロセス (Podmanが起動しているプロセス) を全て終了することができる。<br>
<br>
pkill podman
<br>
例えば、問題が発生した場合や特定の操作が必要な場合、全てのPodmanプロセスを終了させる手段として使用されることがある。<br>
ただし、注意が必要であり、実行中のコンテナが強制的に停止される可能性がある点に留意する必要がある。<br>
<br><br>
== Podmanのストレージ ==
コンテナ内で発生したデータは同じコンテナ内のどこかに書き込まれるが、コンテナを破棄すると同時に削除される。<br>
コンテナを破棄してもデータは保存する場合、または、他のコンテナで再利用する場合は、コンテナ外にデータ保存領域を作成する機能を提供している。<br>
<br>
* ボリューム
*: Podmanの管理下でストレージ領域を確保する。
*: ルートレスモードのデフォルトでは、~/.local/share/containersディレクトリである。
*: <br>
*: 名前付きボリュームと匿名ボリュームがあり、名前付きの場合はホスト内で名前解決できるため簡単にアクセスすることができる。
*: 匿名ボリュームは任意のハッシュ値が振られる。
*: <br>
*: 他のプロセスからはアクセスできないため安全に使用できる。
*: <br>
* バインドマウント
*: ホスト側のディレクトリをコンテナ内のディレクトリと共有する。
*: <br>
* tmpfs
*: メモリ上に一時的なストレージ領域を確保する。
*: 使用用途としては、機密性の高い情報を一時的にマウントする場合等がある。
<br>
<code>-v</code>オプション、<code>VOLUME</code>、<code>volumes</code>で指定する場合に関しても、基本的には上記のいずれかを扱っている。<br>
<br><br>
== Containerfile ==
==== Containerfileとは ====
Containerfileは、コンテナイメージの作成手順を自動化する設定ファイルである。<br>
コンテナエンジン (Podman、Buildah、Docker) は、Containerfileから指示を読み取り、イメージの作成に必要なステップを自動化する。<br>
イメージを構築を自動化するには、Containerfileというファイルを作成する必要がある。<br>
<br>
Containerfileには、コンテナを構築するためのベースになる環境、実行するコマンド、配置するファイル等が記述されている。<br>
Containerfileには、Containerfileを含むコンテキストディレクトリのパスを引数として、<code>buildah bud</code>、<code>podman build</code>コマンドを呼び出す。<br>
PodmanおよびBuildahのデフォルトはContainerfileであり、Dockerfileにフォールバックする。<br>
<br>
Containerfileは、Dockerfileと同じシンタックスをサポートしている。<br>
<br>
Containerfileで作成したPodmanイメージを[https://quay.io Quay.io]にアップロードすることも可能である。<br>
<br>
==== イメージの構築 ====
podman build -t <任意のリポジトリ名>/<任意のタグ名> .
# Containerfileのパスを指定する場合
podman build -t <任意のリポジトリ名>/<任意のタグ名> -f <Containerfileのパス>
<br>
==== シンタックス ====
===== FROM =====
FROM <pullするイメージ名>:<タグ名>
# 別名を指定する場合
FROM <pullするイメージ名>:<タグ名> AS <別名>
#
FROM <pullするイメージ名>@<ダイジェスト名>
# 別名を指定する場合
FROM <pullするイメージ名>@<ダイジェスト名> AS <別名>
<br>
===== MAINTAINER =====
MAINTAINERは生成されたイメージの作者フィールドを設定する。<br>
ユーザにサポートのためのEメールもしくはURLを提供する場合に使用する。<br>
MAINTAINER <作者名> <メールアドレス>
<br>
===== USER =====
コンテナ内のユーザを指定する。<br>
# ユーザをrootにする
USER root
<br>
===== WORKDIR =====
作業ディレクトリを追加する。<br>
WORKDIR <作業ディレクトリパス>
<br>
===== ARG =====
Containerfile内で使用する変数を定義する。
# 変数を定義する場合
ARG <変数名>
# 変数を定義して値を代入する場合
ARG <変数名>=<値>
<br>
===== ENV =====
環境変数を定義する。<br>
ENV <環境変数名> <値>
# または
ENV <環境変数名>=<値>
<br>
===== ADD =====
イメージにファイルやディレクトリを追加する。<br>
# ファイルまたはディレクトリを1つ追加する場合
ADD <ホスト側のファイルまたはディレクトリのパス> <コンテナ側のファイルまたはディレクトリのパス>
# ファイルまたはディレクトリを複数追加する場合
ADD <ホスト側のファイルまたはディレクトリのパス 1> <ホスト側のファイルまたはディレクトリのパス 2> ... <コンテナ側のファイルまたはディレクトリのパス>
# []で囲むこともできる
ADD ["<ホスト側のファイルまたはディレクトリのパス 1>", "<ホスト側のファイルまたはディレクトリのパス 2>" ... "<コンテナ側のファイルまたはディレクトリのパス>"]
<br>
===== COPY =====
ホスト側のファイルおよびディレクトリをイメージに複製する。<br>
# ファイルまたはディレクトリを1つ追加する場合
COPY <ホスト側のファイルまたはディレクトリのパス> <コンテナ側のファイルまたはディレクトリのパス>
# ファイルまたはディレクトリを複数追加する場合
COPY <ホスト側のファイルまたはディレクトリのパス 1> <ホスト側のファイルまたはディレクトリのパス 2> ... <コンテナ側のファイルまたはディレクトリのパス>
# []で囲むこともできる
COPY ["<ホスト側のファイルまたはディレクトリのパス 1>", "<ホスト側のファイルまたはディレクトリのパス 2>" ... "<コンテナ側のファイルまたはディレクトリのパス>"]
<br>
===== EXPOSE =====
コンテナ実行時にリッスンするポート番号を指定する。<br>
# ポートを1つ開放する場合
EXPOSE <ポート番号>
# ポートを複数開放する場合
EXPOSE <ポート番号 1> <ポート番号 2> ...
<br>
===== ENTRYPOINT =====
コンテナの起動時に実行する処理を指定する。<br>
# 実行可能コマンドを指定する
# 実行可能コマンドは、フルパスを指定しなければならない。
ENTRYPOINT ["<実行可能コマンド>", "<引数 1>", "<引数 2>", "<引数...>"]
# シェルで実行するコマンドを指定する : /bin/sh -c "<コマンド> <引数 1> <引数 2> <引数...>"
ENTRYPOINT <コマンド> <引数 1> <引数 2> <引数...>
<br>
===== RUN =====
RUNには2つのシンタックスがある。<br>
# 実行可能コマンドを指定する
# 実行可能コマンドは、フルパスを指定しなければならない。
RUN ["<実行可能コマンド>", "<引数 1>", "<引数 2>", "<引数...>"]
# シェルで実行するコマンドを指定する : /bin/sh -c "<コマンド> <引数 1> <引数 2> <引数...>"
RUN <コマンド> <引数 1> <引数 2> <引数...>
<br>
===== RUN mounts =====
コンテナにファイルシステムをマウントする。<br>
現在サポートされているマウントの種類は、bind、cache、secret、tmpfsである。<br>
<br>
* RUN mountsの全体のオプション
** src / source
**: ボリュームおよびbindのマウント元のパスを指定する。 (<u>bindでは必須である</u>)
**: <code>from</code>を指定する場合、<code>src</code>は<code>from</code>フィールドのサブパスになる。
** dst / destination / target
**: マウント先の指定する。
** ro / read-only
**: <code>true</code> (デフォルト) または <code>false</code>を指定する。
*: <br>
* マウントの種類がbindのみの設定
** bind-propagation
**: <code>shared</code>、<code>slave</code>、<code>private</code>、<code>rshared</code>、<code>rslave</code>、<code>rprivate</code> (デフォルト)
** bind-nonrecursive
**: 再帰的なバインドマウントを設定しない。
**: デフォルトでは再帰的である。
** from
**: src / sourceのルートのステージ名またはイメージ名を指定する。
**: デフォルトはビルドコンテキスト。
** rw / read-write
**: マウントへの書き込みを許可する。
*: <br>
* マウントの種類がtmpfsのみの設定
** tmpfs-size
**: tmpfsマウントのサイズ (バイト)。
**: Linuxのデフォルトでは無制限である。
** tmpfs-mode
**: tmpfsのファイルモードを8進数で指定する。
**: Linuxのデフォルトは<u>1777</u>である。
** tmpcopyup
**: tmpfsマウントによりシャドウされるパスは、tmpfs自体に再帰的にコピーされる。
*: <br>
* マウントの種類がcacheのみの設定
** id
**: 特定のidに対して、個別のキャッシュディレクトリを作成する。
** mode
**: 新しいキャッシュディレクトリのファイルモード (8進数) を指定する。
**: デフォルトは<u>0755</u>である。
** ro / readonly
**: キャッシュの読み取り専用となる。
** uid
**: キャッシュディレクトリのuid。
** gid
**: キャッシュディレクトリのgid。
** from
**: src / sourceのルートのステージ名を指定する。
**: デフォルトはホストキャッシュディレクトリである。
** rw / read-write
**: マウントへの書き込みを許可する。
<br>
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
<br>
===== CMD =====
ContainerfileのCMDは1つのみ指定できる。<br>
複数のCMDが記述されている場合は、最後のCMDのみが有効になる。<br>
<br>
CMDには3つのシンタックスがある。<br>
# 実行可能コマンドを指定する
# 実行可能コマンドは、フルパスを指定しなければならない。
# 例: 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> <引数...>
<br><br>
<br><br>


837行目: 782行目:
<br><br>
<br><br>


== エラー関連 ==
==== 実行権限エラー ====
containerfileファイルまたはcontainer-compose.ymlファイルを使用する時、以下に示すようなエラーが出力される場合がある。<br>
error checking context: 'no permission 〜'
<br>
この時、Containerfileファイルまたはcontainer-compose.ymlファイルに実行権限を付加する。<br>
chmod 755 containerfile
# または
container-compose.yml
<br>
==== Systemdエラー ====
openSUSEコンテナをPodmanコンテナとして動作する時、以下のようなエラーが出力されてSystemdサービスが起動できない。<br>
Failed to connect to bus: No such file or directory.
<br>
これは、Podmanコンテナを実行する時、initシステムを実行していないからである。<br>
<br>
<code>systemctl</code>コマンドは、dbusを介してsystemdと通信するプロセスである。<br>
openSUSEコンテナでは、dbusとsysvinitがインストールされていないため(dbusやsystemdが動作していない)、<code>systemctl</code>コマンドは失敗する。<br>
<br>
Podmanコンテナで<code>systemctl</code>を実行するには、その依存関係をインストールして、特殊なコマンドを実行する必要がある。<br>
<br>
containerfileを作成および使用して解決する手順を、以下に記載する。<br>
まず、以下のようなdockerfileを作成する。<br>
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
<br>
次に、作成したcontainerfileからPodmanイメージを作成する。<br>
podman build -t <イメージ名>:<タグ名> -f <containerfile名> .  # イメージ名:タグ名およびDockerfile名(Dockerfile名がdockerfileの場合のみ)は省略できる
例. podman build -t suse153i .
<br>
Podmanコンテナを実行する。<br>
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
<br>
openSUSEコンテナにおいて、<code>systemctl</code>コマンドが実行できるかどうかを確認する。<br>
# Podmanコンテナ内に入る
podman exec -it <コンテナIDまたはコンテナ名> /bin/bash
# systemctlコマンドが実行できるかどうかを確認
systemctl list-units
<br>
==== Systemdサービスのサポート ====
[https://registry.opensuse.org/cgi-bin/cooverview openSUSEコンテナリポジトリ]で公開されているコンテナイメージは、containers-systemdパッケージがインストールされている。<br>
例えば、Systemdサービスを使用してNginXコンテナを設定して、自動的に起動するためのSystemdサービスファイルとSysconfigファイルが含まれている。<br>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:RHEL]][[カテゴリ:SUSE]][[カテゴリ:Raspberry_Pi]][[カテゴリ:PinePhone]][[カテゴリ:Web]]
[[カテゴリ:RHEL]][[カテゴリ:SUSE]][[カテゴリ:Raspberry_Pi]][[カテゴリ:PinePhone]][[カテゴリ:Web]][[カテゴリ:コンテナ]]

2024年11月28日 (木) 14:19時点における最新版

概要

コンテナとは、Linuxシステム上で実行される、互いに隔離されたプロセス群のことである。
また、ソフトウェアプロセスやマイクロサービスをパッケージ化して、あらゆるコンピューティング環境で実行可能にするソフトウェアソリューションである。

コンテナは、1つのプロセス・グループがシステム上の他のプロセスに干渉しないようにする。

コンテナに含まれるファイルには、アプリケーションコード、環境変数、設定コード、バイナリプログラム、ソフトウェアの依存関係、ライブラリ等がある。
これらのコンポーネントをバンドルするプロセスはコンテナ化と呼ばれ、最終的な製品はコンテナイメージとして知られている。

このイメージは、クラウド、オンプレミスのデータシステム、ローカルシステム等、あらゆるプラットフォームにデプロイされる。

また、不正なプロセスがシステム・リソースを独占することはできず、他のプロセスがタスクを実行するのを妨げることもできる。
悪意のあるコンテナであったとしても、他のコンテナを攻撃したり、データを盗んだり、サービス拒否攻撃を引き起こしたりすることもできない。

コンテナの最終的な目標は、同じライブラリの異なるバージョンを必要とするアプリケーションと競合しないように、
共有ライブラリの独自のバージョンでアプリケーションをインストールできるようにすることある。
その代わり、コンテナによってアプリケーションは仮想化された環境に住むことができ、あたかもシステム全体を所有しているかのような印象を与えることができる。

Podman (Pod Manager) は、Open Container Initiatives (OCI) のコンテナイメージを開発、管理、本番環境で実行する時に使用するコンテナエンジンである。
Podmanプロジェクトは、PodmanをLinuxシステム上でOCIコンテナを開発、管理、実行するためのデーモンレス・コンテナ・エンジンと説明している。

OCIは、コンテナフォーマットとランタイムに関するOSレベルの仮想化ソフトウェアコンテナのオープンなガバナンス構造を実装するために設計された。

Podmanコンテナは、スーパユーザ / 非スーパーユーザのいずれでも実行可能である。

PodmanはDockerと同じコマンドラインでDockerができることのほとんど全てを行うことができるため、Docker = Podmanという単純な行のエイリアスで要約されることが多い。
しかし、Podmanはそれ以上のことができる。

Dockerを理解することはPodmanを理解する上で重要ではないが役立つこともある。


コンテナ・オーケストレータ / コンテナ・エンジン / コンテナ・ランタイム

コンテナの世界では、コンテナ・オーケストレータ、コンテナ・エンジン、コンテナ・ランタイムといった用語が同じ意味で用いられることがよくある。

コンテナ・オーケストレータ

コンテナを複数の異なるマシンやノードにオーケストレートするソフトウェアプロジェクトや製品のことである。
これらのオーケストレータは、コンテナを実行するためにコンテナエンジンと通信する。

主要なコンテナ・オーケストレータはKubernetesで、元々はDockerデーモンのコンテナ・エンジンと通信するように設計されていたが、
Kubernetesはコンテナ・エンジンとして主にCRI-Oまたはcontainerdを使用しているため、Dockerを使用することは時代遅れになりつつある。

CRI-Oとcontainerdは、オーケストレーションされたKubernetesコンテナを実行するために構築されている。

Docker SwarmおよびApache Mesosも、コンテナ・オーケストレータである。

コンテナ・エンジン

主に、コンテナ化されたアプリケーションを単一のローカル・ノードで実行するように構成するために使用される。
ユーザ、管理者、開発者が直接起動できる。

また、ブート時にSystemdユニットファイルから起動したり、Kubernetesのようなコンテナ・オーケストレータから起動することもできる。

前述したように、CRI-Oとcontainerdは、Kubernetesがコンテナをローカルで管理するために使用するコンテナエンジンである。
一般的に、ユーザが直接使用することは想定されていない。

DockerとPodmanは、コンテナ化されたアプリケーションを1台のマシンで開発、管理、実行するためにユーザが使用する主要なコンテナエンジンである。

PodmanがKubernetesのコンテナ起動に使われることはほとんどない。

Buildahもコンテナエンジンの1つであるが、コンテナイメージの構築にしか使用されない。

Open Container Initiative (OCI) コンテナ・ランタイム

Linuxカーネルの様々な部分を設定して、最後にコンテナ化されたアプリケーションを起動する。
最も一般的に使用される2つのコンテナ・ランタイムは、runcとcrunである。

KataとgVisorも、コンテナ・ランタイムである。

※注意
Open Container Initiative (OCI) は、コンテナフォーマットとランタイムに関するオープンな業界標準を作成することを主な目的とした標準化団体である。
詳細を知りたい場合は、https://opencontainers.org を参照すること。

下図は、オープンソース・コンテナ・プロジェクトがどのカテゴリーに当てはまるかを示している。

Container 1.png



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のビルドに必要なライブラリをインストールする。

# RHEL
sudo dnf install meson ninja glib2-devel glibc-devel libseccomp-devel

# SUSE
sudo zypper install meson ninja glib2-devel glibc-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のビルドに必要なライブラリをインストールする。

# SUSE
sudo zypper install libseccomp-devel libapparmor-devel libselinux-devel


crun /runcのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf runc-<バージョン>.tar.gz
cd runc-<バージョン>


または、git cloneコマンドを実行して、ソースコードをダウンロードする。

git clone https://github.com/opencontainers/runc.git
cd runc


crun /runcをビルドおよびインストールする。

# AppArmor, SECcompを有効にする場合
make BUILDTAGS="apparmor seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) 

# SELinux, SECcompを有効にする場合
make BUILDTAGS="selinux seccomp" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) 

# SELinux, SECcompを無効にする場合
make BUILDTAGS="" PREFIX=<Podmanのインストールディレクトリ> -j $(nproc) 

make PREFIX=<Podmanのインストールディレクトリ> install


slirp4netnsのインストール

slirp4netnsは、コンテナのネットワーク機能を提供するために使用されるライブラリである。

Podmanがルートレス環境でコンテナのネットワーク機能を提供するために重要な役割を果たしている。
これにより、ユーザはroot権限を必要とせずにコンテナを実行して、ネットワークを利用できるようになる。
また、各コンテナが独立したネットワーク環境を持つことにより、セキュリティと分離性が向上する。

主な役割を以下に示す。

  • ユーザ空間ネットワーキング
    slirp4netnsは、カーネル空間ではなくユーザ空間でネットワーキングを実現する。
    これにより、ルートレス環境でもコンテナがネットワーク機能を利用できるようになる。

  • ネットワーク名前空間の分離
    各コンテナに独立したネットワーク名前空間を提供して、ホストから分離されたネットワーク環境を実現する。

  • ネットワークアドレス変換 (NAT)
    コンテナ内部のIPアドレスをホストのIPアドレスに変換することで、外部ネットワークとの通信を可能にする。

  • ポートフォワーディング
    コンテナ内部のポートをホストのポートに転送して、外部からコンテナが公開するサービスにアクセスできるようにする。

  • DNS解決
    コンテナ内部からDNSを利用してホスト名の解決ができるようにする。


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


catatonitのインストール

catatonitは、PodmanやDocker等のコンテナランタイムが、コンテナ内のプロセスを正しく管理するために使う補助的なツールである。
ポッドは、Kubernetes等のオーケストレーションツールで使用される複数のコンテナを1つにまとめた単位であるが、ポッド自体の作成や管理はKubernetesの制御プレーンやAPIサーバが行う。

catatonitは、コンテナのinitプロセスとして使用される小さなプログラムである。
Podmanや他のコンテナランタイムでは、コンテナ内でプロセスが正しく動作および終了するためにinitプロセスを使用することが一般的である。
catatonitはそのための軽量な選択肢の1つであり、特にリソースの少ない環境やシンプルなコンテナイメージでの使用に適している。

コンテナのinitプロセスは、コンテナ内で最初に実行されるプロセスであり、次のような役割を果たす。

  • 孤児プロセスの回収
    コンテナ内で起動されたプロセスが終了した時、その親プロセスが終了している場合、プロセスが孤児化される。
    initプロセスはこれらの孤児プロセスを回収して、適切に終了させる。

  • シグナルの管理
    catatonitは、コンテナに送信されるシグナルをキャッチして、適切にハンドリングする。
    これにより、コンテナ内で実行中のプロセスがシグナルを受信できるようにする。

  • リソースのクリーンアップ
    コンテナが終了する時、catatonitはシステムリソースを適切にクリーンアップする。


catatonitのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf catatonit.tar.xz
cd catatonit


または、git cloneコマンドを実行してソースコードをダウンロードすることもできる。

git clone https://github.com/openSUSE/catatonit.git
cd catatonit


catatonitをビルドおよびインストールする。

./autogen.sh

mkdir build && cd build

../configure --prefix=<Podmanのインストールディレクトリ>
make -J $(nproc)
make install


最新の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に関連するディレクトリ

Podmanに関連するディレクトリを以下に示す。
これらのディレクトリは、Podmanとその関連ツール (Podman Desktop) によって使用されており、rootlessモードで実行する時にユーザのホームディレクトリ配下に作成される。

  • ~/.local/share/containers/storage
    Podmanが使用するメインのストレージディレクトリである。
    コンテナイメージ、コンテナ、ボリューム等のデータが格納される。
  • ~/.local/share/containers/podman-desktop
    Podman Desktopアプリケーションが使用するディレクトリである。
    GUIベースのPodman管理ツールの設定やデータが保存される。
  • ~/.local/share/containers/cache
    Podmanのキャッシュディレクトリである。
    イメージレイヤーのキャッシュやその他の一時的なデータが保存される。
    キャッシュを使用することにより、同じイメージの再ダウンロードを避け、操作を高速化する。



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ソケットファイルのパス>"


cgroup v1に関する警告

podmanコマンドを実行した時、以下に示すような警告が出力される時がある。

Using cgroups-v1 which is deprecated in favor of cgroups-v2 with Podman v5 and will be removed in a future version.
Set environment variable `PODMAN_IGNORE_CGROUPSV1_WARNING` to hide this warning.


この警告は、Podman 5.0以降はcgroups v1の使用が非推奨となり、将来のバージョンでは削除される予定であることを示している。
これは、以下に示すような原因がある。

  • システムがcgroups-v1を使用している場合。
    現在のシステムがcgroups-v1を使用しており、Podmanもそれを検出して使用している。
    しかし、Podman v5以降ではcgroups-v2の使用が推奨されている。
  • Podmanのバージョン
    使用しているPodmanのバージョンが5.0以降であるため、この警告メッセージが表示されている。


この警告は、将来的にcgroups v1のサポートが終了することを事前に知らせるためのものである。
現時点ではcgroups v1を使用していても問題ないが、将来のバージョンではcgroups v2に移行する必要がある。

警告を非表示にするには、~/.profileファイル等に環境変数PODMAN_IGNORE_CGROUPSV1_WARNING1、または、true、または、yesに設定する。
ただし、これは警告を非表示にするだけで、根本的な問題は解決しない。

vi ~/.profile


 # ~/.profileファイル
 
 # 上記の警告を非表示にする
 export PODMAN_IGNORE_CGROUPSV1_WARNING=1
 
 # Podmanの設定ファイルのパスを指定
 export CONTAINERS_CONF="$HOME/.config/containers/containers.conf"


長期的には、システムをcgroups v2に移行することを検討する。
cgroups v2は、より効率的でシンプルなリソース管理機能を提供している。
移行には、カーネルのアップグレード、または、関連するツールやライブラリの対応が必要となる場合がある。

SUSEのcgroupのデフォルトモードはハイブリッドモードである。
ハイブリッドモードは、それを必要とするアプリケーションに後方互換性を提供する。

以下に示す機能はunified v2階層でのみ使用可能である。

  • メモリコントローラ
    再生保護(別名 memory.low)、memory.high、PSI(圧力ストール情報)
  • I/Oコントローラ
    ライトバック制御、新しい制御ポリシー
  • 非特権ユーザへのコントローラ委譲 (ルートレスコンテナ)
  • systemd のフリーザサポート
  • 単一階層の取り扱いがよりシンプルになる。


cgroupは、1つのモードしか設定できない。

現在のPCにおいて、cgroups v2が有効になっているかどうかを確認する。

sudo mount | grep cgroup2

# cgroups v2が有効になっている場合
# 出力にcgroup v2のエントリが含まれている場合は、cgroups v2が有効になっている
# 出力例: cgroups v2が有効になっている場合
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)


vi ~/.config/containers/containers.conf
# または
sudo vi /etc/containers/containers.conf


 [engine]
 cgroup_manager = "systemd"
 cgroups = "v2"


もし、上記の手順で解決しない場合は、GRUB2のブートオプションに設定を追加する。
統一制御グループ階層を有効にする場合は、GRUB2ブートローダのカーネルコマンドラインパラメータとして追加する。

sudo vi /etc/default/grub


# /etc/default/grubファイル

GRUB_CMDLINE_LINUX_DEFAULT="〜 systemd.unified_cgroup_hierarchy=1 〜"


GRUB2を更新する。

sudo grub2-mkconfig -o /boot/grub2/grub.cfg


Linuxを再起動する。

sudo shutdown -r now


Linux仮想マシンの作成と開始

Linux仮想マシン (Podman Machine) とは

Podman Machineを理解するには、まず、Podmanのアーキテクチャについて知る必要がある。

Linuxでは、Podmanはデフォルトでrootless (非特権) モードで動作できるため、直接コンテナが実行できる。
Linuxでは、以下に示すようなLinuxカーネルの機能 (コンテナ実行に必要な機能が最初から利用可能) を直接利用できるできるため、
Podman Machineは不要であり、podman run等のコマンドが直接実行できる。

  • namespaces
  • cgroups
  • SELinux / AppArmor等


Windows / MacOSでは、Linuxコンテナをネイティブに実行できないため、仮想マシンを介してLinux環境を用意する必要があるため、仮想マシン (VM) が必要になる。
この仮想マシンをPodman Machineと呼ぶ。

podman machineコマンドの役割を以下に示す。

  • Windows / MacOS環境で必要な仮想マシンを起動すること。
  • 仮想マシン内でPodmanデーモンを開始すること。
  • ホストOSからコンテナを操作できるような環境を準備すること。


podman machineコマンドを実行せずにpodman runコマンド等が使用できる環境は、以下の通りである。

  • ホストOSがLinux
  • Podman Machineが自動的に設定・起動されている状態


Linux仮想マシンの初期化

コンテナが実行される新しいLinux仮想マシンを初期化する。
VMにアクセスするためのSSHキーが自動的に生成されて、VM内のスーパーユーザアカウントとユーザアカウントへのシステム接続が追加される。

podman machine init


デフォルトでは、VMのディストリビューションはカスタムFedoraイメージに基づくWSLを除き、Fedora CoreOSである。
一般的なFedora CoreOSのアップグレードは14日ごとに行われるが、自動アップデートのZincataはPodmanマシンでは無効になっている。

もし、LinuxホストでPodman Machineを作成した場合は、~/.local/share/containers/podman/machineディレクトリに初期ファイルが生成される。
これは、2[GB]程度の容量が必要なため、Linux上ではPodman Machineは不要であることから削除することを推奨する。

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 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ファイルが含まれている。