Podmanを始めたい

## はじめに

この記事はDocker経験者がPodmanを使ってみる記事です。主な内容としては実践したときのメモを中心に書きます。（忘れやすいことなど）誤りなどがあれば書き直していく予定です。

## Podmanってなんですか？

PodmanとはLinuxのディストリビューションで有名なRed HatさんところのエンジニアがOSSとして開発したコンテナオーケストレーションツールです。
公式では以下のように説明されています。

> Podman (POD マネージャー) は、Linux® システム上でコンテナを開発、管理、実行するための オープンソースツールです。Red Hat® のエンジニアがオープンソース・コミュニティと共に開発した Podman は、libpod ライブラリを使用してコンテナエコシステム全体を管理します。 

> アーキテクチャがデーモンレスで包括的であることから、Podman はコンテナ管理の選択肢として、より安全で利用しやすいものとなっています。また、開発者は Buildah や Skopeo などの付属のツールと機能を使用して、コンテナ環境をニーズに合わせてカスタマイズすることができます。 

https://www.redhat.com/ja/topics/containers/what-is-podman

厳密にはPOD マネージャーと言われています。理由としては管理の単位がPodであるところでしょう。

なお、OSSという記載のあるとおりGitHubに具体的な実装が記されています。興味のある方は調べてみると良いでしょう。
[containers podman - GitHub](https://github.com/containers/podman)

## Podmanの始め方

結論を言うと[Get Started with Podman](https://podman.io/get-started)を閲覧しましょうということになるんですが、不親切だと思うので主な利用方法をここに書いておきます。

具体的には以下のとおりです。

- Podman Installerを使ってインストールする（推奨）
- brew install（MacOSの場合）
- winget
  - Podman for Windows（Windowsの場合）
- Linuxのパッケージマネージャを使ってインストール
  - ディストリビューションによってインストール方法が異なります

## インストールする

今回はちょっと試したいだけなので`brew install`でセットアップを開始したいと思います。

```bash
brew install podman
```

## サブコマンドを調べる

インストールが完了したらまずはサブコマンドを調べてみましょう。

```bash
podman --help
```

実行結果

```text
Manage pods, containers and images

Usage:
  podman [options] [command]

Available Commands:
  attach      Attach to a running container
  build       Build an image using instructions from Containerfiles
  commit      Create new image based on the changed container
  compose     Run compose workloads via an external provider such as docker-compose or podman-compose
  container   Manage containers
  cp          Copy files/folders between a container and the local filesystem
  create      Create but do not start a container
  diff        Display the changes to the object's file system
  events      Show podman system events
  exec        Run a process in a running container
  export      Export container's filesystem contents as a tar archive
  farm        Farm out builds to remote machines
  generate    Generate structured data based on containers, pods or volumes
  healthcheck Manage health checks on containers
  help        Help about any command
  history     Show history of a specified image
  image       Manage images
  images      List images in local storage
  import      Import a tarball to create a filesystem image
  info        Display podman system information
  init        Initialize one or more containers
  inspect     Display the configuration of object denoted by ID
  kill        Kill one or more running containers with a specific signal
  kube        Play containers, pods or volumes from a structured file
  load        Load image(s) from a tar archive
  login       Log in to a container registry
  logout      Log out of a container registry
  logs        Fetch the logs of one or more containers
  machine     Manage a virtual machine
  manifest    Manipulate manifest lists and image indexes
  network     Manage networks
  pause       Pause all the processes in one or more containers
  pod         Manage pods
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image from a registry
  push        Push an image to a specified destination
  rename      Rename an existing container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images from local storage
  run         Run a command in a new container
  save        Save image(s) to an archive
  search      Search registry for image
  secret      Manage secrets
  start       Start one or more containers
  stats       Display a live stream of container resource usage statistics
  stop        Stop one or more containers
  system      Manage podman
  tag         Add an additional name to a local image
  top         Display the running processes of a container
  unpause     Unpause the processes in one or more containers
  untag       Remove a name from a local image
  update      Update an existing container
  version     Display the Podman version information
  volume      Manage volumes
  wait        Block on one or more containers

Options:
      --config string             Location of authentication config file
  -c, --connection string         Connection to use for remote Podman service
      --help                      Help for podman
      --identity string           path to SSH identity file, (CONTAINER_SSHKEY)
      --log-level string          Log messages above specified level (trace, debug, info, warn, warning, error, fatal, panic) (default "warn")
      --out string                Send output (stdout) from podman to a file
      --ssh string                define the ssh mode (default "golang")
      --storage-opt stringArray   Used to pass an option to the storage driver
      --url string                URL to access Podman service (CONTAINER_HOST) (default "unix:///var/folders/nk/26yk2_3d1dd382hvzshrs_3h0000gn/T/storage-run-501/podman/podman.sock")
  -v, --version                   version for podman

```

インストールが完了したのでバージョン情報を調べます。

```bash
podman --version
```

実行結果

```text
podman version 5.1.1
```

## コマンドを試してみる

では、さっそくPodmanのコマンドを試してみます。Podmanは最初に`init`という動作が必要です。
※初回起動時は1GBくらいのダウンロードが実行されるので注意

```bash
podman machine init
```

上記の動作が完了することでVM起動します。初期化したVMを確認する場合は以下のコマンドを実行します。

```bash
podman system connection list
```

実行結果

```text
Name                         URI                                                         Identity                                                        Default     ReadWrite
podman-machine-default       ssh://core@127.0.0.1:51497/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:51497/run/podman/podman.sock           /Users/{ユーザ名}/.local/share/containers/podman/machine/machine  false       true
```

初期化したVMを開始するには`start`を実行します。

```bash
podman machine start
```

実行結果

```text
Starting machine "podman-machine-default"

This machine is currently configured in rootless mode. If your containers
require root permissions (e.g. ports < 1024), or if you run into compatibility
issues with non-podman clients, you can switch using the following command:

	podman machine set --rootful

API forwarding listening on: /var/folders/nk/26yk2_3d1dd382hvzshrs_3h0000gn/T/podman/podman-machine-default-api.sock

The system helper service is not installed; the default Docker API socket
address can't be used by podman. If you would like to install it, run the following commands:

        sudo /opt/homebrew/Cellar/podman/5.1.1/bin/podman-mac-helper install
        podman machine stop; podman machine start

You can still connect Docker API clients by setting DOCKER_HOST using the
following command in your terminal session:

        export DOCKER_HOST='unix:///var/folders/nk/26yk2_3d1dd382hvzshrs_3h0000gn/T/podman/podman-machine-default-api.sock'

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

起動が完了したのでpodmanの情報を表示してみましょう。※実行結果は長いので省略

```bash
podman info
```

なお、`start`していない状態でinfoを実行すると一部のみ表示され、あとはエラーが返されます。

## podmanでコンテナにハンズオン

nginxを起動する例を元にPodmanを使っていきましょう。まずはプロセスを確認します。

```bash
podman ps -a
```

nginxイメージをpullします。

```bash
podman pull nginx
```

pullしたイメージを使ってコンテナを起動します。

```bash
podman run -d -p 8080:80 --name test_nginx nginx
```

起動できているかを確認します。

```bash
podman ps
```

```text
CONTAINER ID  IMAGE                           COMMAND               CREATED             STATUS             PORTS                         NAMES
d96c999f9dcc  docker.io/library/nginx:latest  nginx -g daemon o...  About a minute ago  Up About a minute  0.0.0.0:8080->80/tcp, 80/tcp  test_nginx
```

nginxのページがローカルホストに公開されているかを確認するため、以下のコマンドを実行します。

```bash
 curl localhost:8080
```

以下のようなHTMLがレスポンスとして返ってくれば、nginxのページがローカルホストに公開されています。

```html
<!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>
```

[localhost:8080](http://localhost:8080/)を開くと以下のように画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527543/70481d6e-d401-b45a-07c5-ccfc1ae68988.png)

## 片付け

片付けの手順としては以下のとおりです。

- コンテナを止める
- コンテナを削除
- イメージを削除

順番に対応していきましょう。まずはコンテナを止めます。

```bash
podman stop test_nginx
```

次にコンテナを削除します。

```bash
podman rm test_nginx
```

コンテナが起動していないことを確認します。

```bash
podman ps
```

以下のように最初の状態に戻っていれば、問題なく削除できています。

```text
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES
```

nginxイメージを削除します。まずはimage idを調べるために`images`を実行します。

```bash
podman images
```

実行結果

```text
REPOSITORY               TAG         IMAGE ID      CREATED      SIZE
docker.io/library/nginx  latest      11ceee7cdc57  2 weeks ago  197 MB
```

イメージIDを指定して削除します。

```bash
podman rmi 11ceee7cdc57
```

なお、他の削除方法として`podman images -q`を使って削除する方法もあります。

```bash
podman rmi `podman images -q`
```

※他にも様々な消し方がありますが、今回は基礎レベルの話になりますので割愛

最後にイメージの一覧を表示して削除されているかを確認します。

```bash
podman images
```

## 環境を削除する

コンテナが削除できましたのでコンテナを動かしていた環境を削除します。まずはVMを止めます。

```bash
podman machine stop
```

止めたVMを削除します。今回は1つのVMしか作成していないため、マシン名の指定はしていません。
複数のマシンがある場合はマシン名をrmの次に指定する必要があります。

```bash
podman machine rm
```

最後にVMのリストを表示して削除できているかを確認します。

```bash
podman system connection list
```

実行結果

```text
Name        URI         Identity    Default     ReadWrite
```

## まとめ

今回はPodmanを使ってコンテナを動かしてみました。使ってみる感じではdockerのコマンドと遜色がないのでPodmanであるかどうかを意識することがなく、コンテナを操作できました。

記事に登場するコマンドは以下の記事を参考に作成しているので使うだけ（コマンドを入力するだけ）ならますますdockerと遜色がないと感じました。

[【docker】dockerのキワミ](https://qiita.com/ymd65536/items/68b68465635841a62556)

次はクラウド上で使ってみたいです。

追記
思うにVM丸ごと消せば、コンテナイメージも消えるので環境をまるごと消すでいいんじゃないかなと思ったところです。

dockerだとVMを起動するという工程がない（サブコマンドinitを実行する必要がない）のでそこらへんの意識がありませんでした。

## おわり