コンテナ｜macOS で Docker の代わりに Podman を使用する

## 概要
Windows や macOS、Linux 等の異なる環境でも同じソフトウェアを動かせる「コンテナ」技術によって、今や開発者の中でも大人気の **Docker** ですが、利用するために必要な **Docker Desktop** が突然、ある時期から一定規模の企業に対しては有料化されることになりました。
それ以降、Docker の代替となるコンテナツールに関する相談を複数の企業様から受けることもいくつかあり、代わりに **Podman** を使用する機会が増えてきました。

元々は Linux 上で利用する技術ですが、今後のコンテナツールの選択肢としても主流の１つになりそうなので、今回は、個人レベルで macOS に利用する方法をライトにまとめてみました。

### 前提
macOS で導入・利用する内容を記載します。Windows の場合は、適宜読み替えてください。

## Podman とは
**「Podman」**（ポッドマン）は、Red Hat 社がオープンソースコミュニティとともに開発した、Docker の代替となり得るコンテナ技術です。つまり、**Docker にとっては超強力なライバル** です。

https://podman.io/

Docker との違いは、Podman の **特徴** を知れば理解しやすいです。

### 特徴
- **デーモンレスである（Daemonless）**
  - デーモン（Daemon）を起動する必要がない
  - それにより、セキュリティリスクを軽減できる（理由は下記）
- **ルートレス・コンテナを使用できる（Rootless mode）**
  - 多くのデーモンプロセスは root 権限で実行されるため、セキュリティの脆弱性を生む可能性があり、攻撃者の標的となり易い
  - デーモンレスによって root 権限を使用せずにコンテナを使用できるため、セキュリティリスクを軽減する
  - これにより、root 権限がない一般ユーザでも、コンテナをより気軽に使用できる
  - 更に、SELinux（セキュリティ強化されたLinux）ラベルを使用すれば、管理者はコンテナ起動時の提供リソースや機能のより詳細な制御が可能になる
- **Docker と互換性がある（OCI Compatible）**
  - Docker 互換性があり、コマンドも docker とほぼ似ているため、移行もし易い
  - つまり『Docker で出来ることは、大体できる』ということ

Podman は、付属機能である **Skopeo** や **Buildah** などと共に利用することで、Docker を利用して実現するほぼ全てのことが、Podman でも対応可能になります。

尚、Skepeo と Buildah についても下記に軽く記載しますが、小難しいので今すぐココで深く理解する必要はありません。

### Skopeo
**「Skopeo」**（スケーポー）は、Podman 利用時に補完的に機能するコマンドラインツールです。
コンテナイメージに関する管理については、この技術が担うことが多いです。
具体的には、Linux、Windows、macOS など異なるプラットフォーム上で、コンテナイメージやイメージリポジトリに関する操作・検査・署名・転送などが効率的に実行できるツールです。

### Buildah
**「Buildah」**（ビルダー）も、Podman 利用時に補完的に機能するコマンドラインツールです。
OCI イメージとコンテナの操作、ビルドに使用します。

Podman は Buildah のソースコードを流用して後から作られたツールですが、Buildah のコマンドは Podman より詳細な操作が可能なため、ビルドに関する処理は Buildah が担うことが多いです。
Docker や Kubernetes とも互換性があります。

## Docker ではなく Podman を採用するメリット

### 技術面
どちらが「扱いやすい」かはユースケース次第だが、Podman を推奨できる点は以下。

- Docker は事実上のデファクト標準コンテナだが、Podman はほぼ同様のことができる（ただし、エコシステムや関連ツールの観点ではまだ弱い）
- **完全 daemon-less ＆ rootless** がデフォルト。プロセスごとに fork して動く
  - 最近は Docker も rootless モード追加されたが設計思想が異なる
- システム連携の観点で、`podman generate systemd` で systemd ユニット自動生成。Kubernetes YAML も出力可
  - Docker は単一コンテナが前提。systemd 連携はサードパーティ
- Docker 経験があれば 1 日で移行可能。rootless の仕組みを理解すると運用が楽

### ビジネス面（ライセンスと費用）
採用する根拠としては、こちらの理由が大きかったりもする。

| 観点|**Docker**|**Podman**|
|---|---|---|
| **ソフト本体のライセンス**  | Engine は Apache 2.0 だが **Docker Desktop は商用利用に条件**<br>- 250 名超 or 年商 1000 万 USD 超は有料プラン必須 (Team/Business) ([Docker][1], [Docker Community Forums][2]) | **CLI/Engine・Podman Desktop とも Apache 2.0**。商用利用も無償 ([podman.io][3], [GitHub][4]) |
| **有償サブスクリプション**  | - Docker Desktop：5 – 24 USD/ユーザー/月<br>- 2025-03 から Docker Hub の大規模 pull に従量課金が導入 ([Docker Community Forums][5]) |なし。Red Hat の有償サポートを付ける場合のみ別途契約|
| **社内コンプライアンス対応** | 契約管理・台帳管理が必要。監査で「Desktop ライセンス保有者＝実利用ユーザ数」を証明する手間|完全 OSS なので契約管理は不要（ただしサポート契約を結ぶ場合は別）|
| **ベンダーロックイン** | Docker Only 機能 (Dev Environments, Extensions) を使い込むと乗り換えコスト増 | OCI 準拠のみ依存。別ランタイムへの乗り換え容易 |

[1]: https://www.docker.com/pricing/?utm_source=chatgpt.com "Pricing - Docker"
[2]: https://forums.docker.com/t/yet-another-question-about-licensing-big-company-and-pro-license/142728?utm_source=chatgpt.com "Yet another question about licensing. Big company and PRO license"
[3]: https://podman.io/?utm_source=chatgpt.com "Podman"
[4]: https://github.com/containers/podman.io/blob/main/License?utm_source=chatgpt.com "podman.io/License at main · containers/podman.io · GitHub"
[5]: https://forums.docker.com/t/is-a-paid-subscription-required-for-companies-to-use-images-on-dockerhub-after-the-implementation-of-docker-hub-consumption-pricing/145895?utm_source=chatgpt.com "Is a paid subscription required for companies to use images on ..."


## 導入手順（インストール）
以下に導入手順の概略を記載しますが、詳細な導入手順は、[Podman の公式ページ](https://podman.io/docs/installation) や [Red Hat の公式ページ](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html-single/building_running_and_managing_containers/index) を参考にしてください。

### Podman を導入する
macOS なら Homebrew でインストールするだけで簡単に導入が完了します。

```bash
brew install podman
```

Windows の場合は [こちら](https://podman.io/docs/installation#windows) を参考にインストールしてみてください。
基本的にインストーラーをダウンロードして、exeファイルをダブルクリックで起動するだけのはずです。

※ 念のため、インストール後はターミナルを再起動すると無難

### インストール確認
インストール成功確認のため、`podman` コマンドが使えるようになったかを試す。

```bash
# バージョン確認コマンド
$ podman -v

# 実行結果
podman version 5.5.0
```

## 初期環境構築
Podman をマシンにインストールしたら、最初だけ **podman machine** を用意する環境構築作業が必要です。

以下の初期化コマンドを実行します。
（※ 1GB 程度の容量をダウンロードします）
```bash
podman machine init
```

コマンド実行後、以下の様になれば初期化完了です。

```bash
# 実行結果
Looking up Podman Machine image at quay.io/podman/machine-os:5.5 to create VM
Getting image source signatures
Copying blob 2c27f1c0c040 done   | 
Copying config 44136fa355 done   | 
Writing manifest to image destination
2c27f1c0c0405ae651c1e0261cefbb3ca6c0d263bee9ce8af377376d2df8ba03
Extracting compressed file: podman-machine-default-amd64.raw: done

Machine init complete # 初期化完了

# 次にやってほしいコマンド
To start your machine run:

	podman machine start
```

### podman machine とは
Podman はもともと **Linux 環境** で動くツールで、Windows / macOS 版は **リモートクライアント** のみが提供されています。
つまり、Windows / macOS で Podman を使うには、**「接続先となる Linux 環境」** が必要ということです。

Windows の場合は、WSL（Windows Subsystem for Linux）があるので、そこにインストールして、OS の PowerShell 等から呼び出すことができます。
macOS には、WSL の様に OS 標準提供の Linux 環境がないので、別途用意する必要があります（実は Docker も同様）。

そこで、macOS 上で Linux 仮想マシンを提供する機能が **"podman machine"** であり、マシンを作成する処理が `podman machine init` です。

### VM（仮想マシン）作成確認
以下のコマンドで、VM が作成されたかを確認できます。

```bash
# 仮想マシン (VM) 一覧
$ podman machine list

# 実行結果（初期化前は、ヘッダのみの空表示になる）
NAME                     VM TYPE     CREATED        LAST UP            CPUS        MEMORY      DISK SIZE
podman-machine-default*  applehv     3 minutes ago  Currently running  12          2GiB        100GiB
```


もしくはコネクションリストの有無でも一応確認できる。
```bash
# コネクションリスト確認
$ podman system connection list

# 実行結果 コネクションリスト表示
Name                         URI                                                         Identity                                                     Default     ReadWrite
podman-machine-default       ssh://core@127.0.0.1:55669/run/user/501/podman/podman.sock  /Users/{ユーザ名}/.local/share/containers/podman/machine/machine  true        true
podman-machine-default-root  ssh://root@127.0.0.1:55669/run/podman/podman.sock           /Users/{ユーザ名}/.local/share/containers/podman/machine/machine  false       true
```

## VM 起動・停止

### VM 起動
導入した VM の起動
```bash
podman machine start
```

※ 最初は `Starting machine "podman-machine-default"` と表示されて数十秒止まっている様に見えるが、しばらくすると以下の様に表示されて起動に成功する

```bash
Starting machine "podman-machine-default"

: #（中略）

Machine "podman-machine-default" started successfully
```

### VM 情報確認
以下で、仮想マシン等の情報を確認できる

```bash
podman info
```

### よく使うコマンド

コンテナ確認

```bash
podman ps
```

※ image の pull などが出来ていなければ、ヘッダ行のみの空データとなる

## 試しに何か入れてみる
nginx を入れて起動してみる

### nginx イメージを取得

nginx の image をpull
```bash
podman pull nginx
```

### コンテナ起動

pullしたイメージを使ってコンテナを起動します。
```bash
podman run -d -p 8080:80 --name test_nginx nginx
```
※ `test_nginx` という名前をつけていますが、任意の値に変えられます

### 起動確認

起動できているかを確認します。
```bash
podman ps
```

起動成功していれば、以下の様になります
```bash
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS         PORTS                 NAMES
259f66911c78  docker.io/library/nginx:latest  nginx -g daemon o...  24 seconds ago  Up 24 seconds  0.0.0.0:8080->80/tcp  test_nginx
```

Web ブラウザを開いて `localhost:8080` にアクセスしてみましょう。

![podman_web_200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/75073724-c7b5-4bb7-a3a4-fb31ba15d4cc.png)

無事、Nginx が導入・起動できていることが確認できました。

尚、以下の様に **"400 Bad Request, Request Header Or Cookie Too Large"** というエラー画面になる場合は、既存のブラウザ Cookie が大きすぎるために発生します。
ブラウザの Cookie を削除するか、**「シークレットモード」** でブラウザ起動してアクセスすると、これを回避できます。

![podman_web_400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/9027f4ca-d435-43e5-8118-3a30ce162f41.png)

## 不要になったイメージ・コンテナを削除する
どんなイメージ・コンテナを導入しても、停止や削除の基本的な手順は以下の通りです。

### コンテナ停止
```bash
podman stop test_nginx
````

※ 事前に `test_nginx` という名前をつけたため、上記の名前を指定している

### コンテナ削除
```bash
podman rm test_nginx
````

### コンテナ削除確認
```bash
podman ps
````

### イメージ一覧確認
```bash
podman images
```

イメージ一覧が出てきますので、イメージ ID をコピーします（下記は筆者のサンプル）
```bash
REPOSITORY               TAG         IMAGE ID      CREATED      SIZE
docker.io/library/nginx  latest      be69f2940aaf  5 weeks ago  197 MB
```

### イメージ削除
先ほどコピーした ID を指定して、イメージ削除コマンド実行

```bash
podman rmi be69f2940aaf
````

### イメージ一覧確認
削除されて空になっていることを確認

```bash
podman images
```
これで再び VM はクリーンになりました。

## VM 環境を破棄する場合
今の手順では VM（仮想マシン）が１つしか存在しませんが、VM は複数建てることができます。つまり、VM 単位で作ったり削除したりもできます。

### VM 停止
基本的に起動しっぱなしで構わないが、環境破棄のために止めたい場合は、まず VM を停止する

```bash
podman machine stop
```

VM の NAME を確認しておく

```bash
podman machine list
```

VM の NAME を指定して削除
```bash
podman machine rm {VM の NAME}
```

デフォルトの VM が１つしかないなら、以下でも大丈夫
```bash
podman machine rm -f
```

## イメージはどこで探すの？
Podman 自体には専用のイメージレジストリはありませんが、Podman は **Docker Hub を含む複数のレジストリと互換性があり、自由に利用できます。**

Podman は以下のような 既存の **OCI 準拠レジストリ** を使ってイメージの pull/push が可能です。

| レジストリ | 説明 |
| --- | --- |
| **Red Hat Enterprise Linux（RHEL）** | RHEL 向けの商用レジストリ。`rhel`, `ubi（Universal Base Image）` などの公式イメージがここにある。ログイン不要で使えるUBI系イメージは、Red Hat 以外でも利用可能 |
| **Docker Hub** (`docker.io`) | デフォルトで使用されるレジストリ。多くの公式イメージがここにある |
| **Quay.io** | Red Hat 系のイメージによく使われる。Podman 開発元とも親和性が高い |
| **Fedora** |Fedora 用に最適化されたコンテナイメージ（nginx、postgres、toolchain など）が置かれている。ベースイメージやテスト用として使われることが多い|
| **GitHub Container Registry (ghcr.io)** | GitHub Actions などと連携できる OCI レジストリ |
| **Harbor** | オープンソースの自前ホスト型レジストリ。企業用途にも |
| **Amazon ECR / Google GCR / Azure ACR** | クラウドベンダーが提供するレジストリ。Podman からもアクセス可能 |

### Podman のレジストリ設定ファイル
Podman は `/etc/containers/registries.conf` を使って、**検索順** や **優先レジストリ** をカスタマイズできます。

macOS の場合は、Linux 仮想マシン内のその場所に設定されています。
```bash
# Podman VM に入る（SSH接続）
podman machine ssh

# 設定ファイルを確認
cat /etc/containers/registries.conf

# ログアウト
exit
```

私の実際の設定ファイルの中身は以下でした（参考）

```toml
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io"]
```

pull を実行すると、この記載順に探していって、最初に見つかったイメージを取得してきます。

### 補足：Podman とレジストリの関係

- Podman はあくまで「OCI 準拠のコンテナランタイム」であり、**レジストリは外部のものを使う前提** です
- Docker も実際には Docker Hub を「別サービス」として利用していますが、Podman はさらにレジストリを明示的に指定して使う文化があります

**使用例**
```bash
# docker.io から nginx を pull
podman pull docker.io/library/nginx

# quay.io から pull
podman pull quay.io/bitnami/nginx

# ghcr.io から pull
podman pull ghcr.io/OWNER/REPO:TAG
```

### 自前レジストリを使いたい場合は？

Podman + Harbor を使って自前でレジストリを構築可能。

あるいは `registry:2` イメージで簡単なローカルレジストリを立てることもできます。

## GUI ツールを使う
Pocman は Docker for Desktop のような GUI ツールもあります。GUI になれている場合はこちらを利用すると良い

https://podman-desktop.io/

macOS なら以下のインストールですぐに入る
```bash
brew install --cask podman-desktop
```

勝手にデータを利用されたくない場合は、初回起動時のチェックを外すと良い。

GUI ツールでは、コンテナやイメージを導入していると、リスト表示されるため、前述の Nginx のテスト導入をしている場合は、既に GUI 上に追加したイメージやコンテナが表示されているはずです。

イメージの削除、コンテナの停止・削除がマウスのワンクリックで出来るためお手軽です。