6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

DENSOAdvent Calendar 2021

Day 1

docker desktop の代わりに windows10 wsl2 で podman をつかう

Last updated at Posted at 2021-11-30

docker desktop の有料化に対する猶予期間が終了する、1月31日が近づいてきました。皆様いかがお過ごしでしょうか。

さて、今日は windows10 の wsl2 環境で docker desktop の代替として podman が使えそうか検証していきたいと思います!

用意するもの :briefcase:

wsl2

> wsl -l -v
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop         Stopped         2
  docker-desktop-data    Stopped         2

ubuntu

❯ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
Codename:       focal

まだ 18.04 使ってるよーという方がこのあたりを参考に、20.04 にされることをお勧めします。

なお、sudo do-release-upgrade コマンドが Reading state information... Done の後でfailしてしまう場合は、こちらに書かれているように、 sudo apt-get purge snapd してあげると進みます(ました)。

Install :comet:

install と書きましたが、まずは docker desktop を uninstall します。
いつでも戻せるという甘えを断ち切ります。

うおー
image.png

>wsl -l -v
  NAME      STATE           VERSION
* Ubuntu    Running         2

docker いなくなりました :cry:

では、install していきます。
公式Docを見ると下記blogポストがリンクされています。

これによると、install コマンドはこう。

. /etc/os-release
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/x${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/x${NAME}_${VERSION_ID}/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update -qq
sudo apt-get -qq -y install podman
sudo mkdir -p /etc/containers
echo -e "[registries.search]\nregistries = ['docker.io', 'quay.io']" | sudo tee /etc/containers/registries.conf

ubuntu 20.10 以降だと

# Ubuntu 20.10 and newer
sudo apt-get -y update
sudo apt-get -y install podman
sudo mkdir -p /etc/containers
echo -e "[registries.search]\nregistries = ['docker.io', 'quay.io']" | sudo tee /etc/containers/registries.conf

でいけんのかな?未確認。

上記の blog によると、構成オプションの変更が必要そうなのですが、

--cgroup-manager cgroupfs --event-logger file

podman info してみると、すでに該当の構成で設定されており、必要なさそうです。

❯ podman info
...
  cgroupManager: cgroupfs
...
  eventLogger: file
...

version

❯ podman version
Version:      3.4.2
API Version:  3.4.2
Go Version:   go1.16.6
Built:        Thu Jan  1 09:00:00 1970
OS/Arch:      linux/amd64

podman run :basketball_player_tone1:

とりあえず run してみます。

 ❯ podman run -dt -p 8080:80/tcp httpd
✔ docker.io/library/httpd:latest
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 0d58b11d2867 done
Copying blob e88da7cb925c done
Copying blob ba1caf8ba86c done
Copying blob eff15d958d66 done
Copying blob ab86dc02235d done
Copying config ad17c88403 done
Writing manifest to image destination
Storing signatures
7ae5b62981563f779be7af3c2210841d70ac513a0941f76ead7fffe7e7f2a350
❯ podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED         STATUS             PORTS                 NAMES
7ae5b6298156  docker.io/library/httpd:latest  httpd-foreground  17 seconds ago  Up 18 seconds ago  0.0.0.0:8080->80/tcp  jolly_mayer

localhost:8080 にアクセスしてみます。
image.png

イケてる!

止めます。

❯ podman stop jolly_mayer
jolly_mayer
❯ podman ps -a
CONTAINER ID  IMAGE                           COMMAND           CREATED        STATUS
    PORTS                 NAMES
7ae5b6298156  docker.io/library/httpd:latest  httpd-foreground  6 minutes ago  Exited (0) 5 seconds ago  0.0.0.0:8080->80/tcp  jolly_mayer

restart してみたり、 rm してみたり。このあたりの使用感は docker と全然変わらないですね。

volume mount :package:

マウントしてみます。

echo "test page" > index.html
podman run -d --rm -p 8080:80 -v $PWD:/usr/share/nginx/html --name web nginx

image.png

うむ、普通にできました。

external network :spider_web:

default 状態の確認。

❯ podman network ls
NETWORK ID    NAME        VERSION     PLUGINS
2f259bab93aa  podman      0.4.0       bridge,portmap,firewall,tuning

ここにネットワークを作ります。

❯ podman network create ex-network
/etc/cni/net.d/ex-network.conflist

できた。

❯ podman network ls
NETWORK ID    NAME        VERSION     PLUGINS
2f259bab93aa  podman      0.4.0       bridge,portmap,firewall,tuning
34f160cc6cae  ex-network  0.4.0       bridge,portmap,firewall,tuning,dnsname

nginx をたててみます。

❯ podman run -d --rm -p 8080:80 -v $PWD:/usr/share/nginx/html --name web --net ex-network nginx
7759d6c9199f29891b1fed4fc7543e9bf01054698710c41392bedb927e619411

busybox の debug コンテナから web コンテナにアクセスしてみます。

podman run -it --rm --net ex-network busybox sh
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob e685c5c858e3 done
Copying config 7138284460 done
Writing manifest to image destination
Storing signatures
/ # wget -q -O - web:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

問題なくイケてますね!

docker と podman の network 実装の違いの話

ちなみに、こちらの記事で述べられている、

docker network create コマンドと同様に podman network create コマンドでカスタムネットワークを作成できますが、Podman (3.0.0-rc1) では複数のネットワーク間での通信が禁止されていません。

について検証してみました。
こちらの issue ですね。

もう1つ network を作成して、

❯ podman network create ex-network-alt
/etc/cni/net.d/ex-network-alt.conflist

コンテナ名でのアクセスはできませんが、

❯ podman run -it --rm --net ex-network-alt busybox sh
/ # wget -q -O - web:80
wget: bad address 'web:80'
/ # exit

IP だとアクセスできてしまいました。

 podman run -it --rm --net ex-network-alt busybox sh
/ # wget -q -O - 10.89.0.2:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

なるほど。

k8s yaml :ship:

podman は(公式には)docker-compose をサポートしていません。
その代わり、k8s yaml をサポートしています。
そんな podman の醍醐味(?)である k8s yaml での動作を見てみます。

container から pod yaml をつくる

まず手始めに、起動している container から k8s pod yaml を生成してみます。
単一の container から pod yaml をつくる方法です。

❯ podman generate kube web > web-kube.yaml

おぉ。見慣れたやつ。

web-kube.yaml
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-3.4.2
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2021-11-24T13:49:13Z"
  labels:
    app: web
  name: web
spec:
  containers:
  - args:
    - nginx
    - -g
    - daemon off;
    image: docker.io/library/nginx:latest
    name: web
    ports:
    - containerPort: 80
      hostPort: 8080
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: root-workspace-host-0
  volumes:
  - hostPath:
      path: /root/workspace
      type: Directory
    name: root-workspace-host-0

では次に複数の container から pod yaml を作ってみたいと思います。
が、そのためにまず pod そのものをコマンドで作ります。

空のpodを作るコマンド

podman pod create --name my-pod

お、pod ができている!

❯ podman pod list
POD ID        NAME        STATUS      CREATED        INFRA ID      # OF CONTAINERS
70976cb582e2  my-pod      Created     4 minutes ago  8bdec75f2026  1
❯ podman ps -a
CONTAINER ID  IMAGE                 COMMAND     CREATED        STATUS      PORTS       NAMES
8bdec75f2026  k8s.gcr.io/pause:3.5              8 minutes ago  Created                 70976cb582e2-infra

この pod に対して、次のように、podman run コマンドを --pod で実行すると container が pod に割り当てられると言うわけです。
(この時、--pod new:my-pod2 のように new を付けるとpodの作成もやってくれるらしいです。)

podman run -d --rm -p 8080:80 -v $PWD:/usr/share/nginx/html --name web --net ex-network --pod my-pod nginx

おー container 増えた。

❯ podman pod ls
POD ID        NAME        STATUS      CREATED         INFRA ID      # OF CONTAINERS
70976cb582e2  my-pod      Running     10 minutes ago  8bdec75f2026  2
❯ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS             PORTS                 NAMES
8bdec75f2026  k8s.gcr.io/pause:3.5                                  10 minutes ago  Up 33 seconds ago                        70976cb582e2-infra
aef5792650c1  docker.io/library/nginx:latest  nginx -g daemon o...  32 seconds ago  Up 32 seconds ago  0.0.0.0:8080->80/tcp  web

例があまりよくないけど、さっきの busybox コンテナも pod に入れて、30s 毎に web container にアクセスするようにしてみます。

❯ podman run -d --rm --name debug --net ex-network --pod my-pod busybox sh -c "while true; do wget -q -O - web:80; sleep 30; done;"
87cd836c39135dc59bb4bbd3414bd03dc0ec5aa5cf6ef8b475ae2011dcf56562
❯ podman logs debug
test page
test page

うむうむ。

さてさて、これらをいよいよ k8s pod yaml に変換します。
コマンドは単一 container の時と同じですが、今度は pod 名で。

❯ podman generate kube my-pod > my-pod-kube.yaml

できてるできてる。

my-pod-kube.yaml
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-3.4.2
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2021-11-24T16:12:52Z"
  labels:
    app: my-pod
  name: my-pod
spec:
  containers:
  - args:
    - nginx
    - -g
    - daemon off;
    image: docker.io/library/nginx:latest
    name: web
    resources: {}
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: root-workspace-host-0
  - command:
    - sh
    - -c
    - while true; do wget -q -O - web:80; sleep 30; done;
    image: docker.io/library/busybox:latest
    name: debug
    resources: {}
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
  restartPolicy: Never
  volumes:
  - hostPath:
      path: /root/workspace
      type: Directory
    name: root-workspace-host-0
status: {}

ex-networkを指定している要素は yaml には表れてこないですね :thinking:
必要ないからかな。

というわけで、podman だと、ローカル環境などで(試行錯誤しながら)複数 container によるオーケストレーション環境を作り、それを k8s yaml に吐きだして管理できることが分かりました。

docker-compose には compose yaml を ganerate する仕組みはなかった(気がする)から新鮮 :sparkles:

pod yaml を作ってしまえば、一度 pod も container も消して、

❯ podman pod stop my-pod
70976cb582e2758ecf8f3f9900cfc96919fc31b5f40c66edbfb0905a74f4c998
❯ podman pod rm my-pod
70976cb582e2758ecf8f3f9900cfc96919fc31b5f40c66edbfb0905a74f4c998
❯ podman ps -a --pod
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES       POD ID      PODNAME

何もない状態から、podman play コマンドで、docker-compose up のように先ほどの環境が作れます。

❯ podman play kube my-pod-kube.yaml
Pod:
b9ccabbc6312534340feef2ee4f37b86f306bc0a0e509801ab1f52aec68eefd1
Containers:
89579f9b1b615a6ddab8b86eb7d0c8950fb5e8a4341e0e8976d1956140b34feb
fc1ec0acc05c246c7eff078dd9fe0e90bba100d553c25e129962bbb31aad3a08
❯ podman pod ls
POD ID        NAME        STATUS      CREATED         INFRA ID      # OF CONTAINERS
b9ccabbc6312  my-pod      Degraded    18 seconds ago  732642163dc8  3
❯ podman ps -a --pod
CONTAINER ID  IMAGE                             COMMAND               CREATED         STATUS                     PORTS       NAMES               POD ID        PODNAME
732642163dc8  k8s.gcr.io/pause:3.5                                    22 seconds ago  Up 15 seconds ago                      b9ccabbc6312-infra  b9ccabbc6312  my-pod
89579f9b1b61  docker.io/library/nginx:latest    nginx -g daemon o...  19 seconds ago  Up 15 seconds ago                      my-pod-web          b9ccabbc6312  my-pod
fc1ec0acc05c  docker.io/library/busybox:latest                        15 seconds ago  Exited (0) 12 seconds ago              my-pod-debug        b9ccabbc6312  my-pod

と思ったらあれ?

❯ podman logs my-pod-debug
wget: bad address 'web:80'

yamlを少し修正する必要がありそうです。

...
spec:
  containers:
  - args:
    - nginx
    - -g
    - daemon off;
    image: docker.io/library/nginx:latest
    ports:                 # ここ追記
      - containerPort: 80  # ここ追記
    name: web
...
  - command:
    - sh
    - -c
    - while true; do wget -q -O - localhost:80; sleep 30; done; # ここ web -> localhost
    image: docker.io/library/busybox:latest
    name: debug
...
❯ podman logs my-pod-debug
test page
test page
test page

でたでた。

ちなみに、podman generate command の

 ❯ podman generate systemd --files --name my-pod
/root/workspace/pod-my-pod.service
/root/workspace/container-my-pod-web.service
/root/workspace/container-my-pod-debug.service

を実行すると、systemd 用の unit file が作られて、これを /usr/lib/systemd/system などに配置すると daemon のいない podman でもサービスを永続化できるっぽい。
けど今回は docker desktop の代替を目指すので、ここでは触れません。

resource limit :ghost:

k8s yaml で行けるとなると、contaier 毎の resource request/limit も yaml 通りに設定されるんでしょうか :thinking:
少し見てみたいと思います。

何も制限を設けず、負荷をかけてみます。
debug コンテナのコマンドを少し修正して、

sleep 5; while true; do wget -q -O - localhost:80 > /dev/null; done;
❯ podman top my-pod-debug
USER        PID         PPID        %CPU        ELAPSED      TTY         TIME        COMMAND
root        1           0           22.060      36.2640195s  ?           8s          sh -c while true; do wget -q -O - localhost:80 > /dev/null; done;

では、cpu に limit を追加します。

...
  - command:
    - sh
    - -c
    - sleep 5; while true; do wget -q -O - localhost:80 > /dev/null; done;
    image: docker.io/library/busybox:latest
    name: debug
    resources:
      limits:       # ここだよー
        cpu: "200m" # ここだよー
    securityContext:
      capabilities:
        drop:
        - CAP_MKNOD
        - CAP_NET_RAW
        - CAP_AUDIT_WRITE
...

おーだいぶ控えめになりました。

❯ podman top my-pod-debug
USER        PID         PPID        %CPU        ELAPSED        TTY         TIME        COMMAND
root        1           0           4.034       1m39.1670656s  ?           4s          sh -c sleep 5; while true; do wget -q -O - localhost:80 > /dev/null; done;
root        21940       1           0.000       1.1671397s     ?           0s          wget -q -O - localhost:80

registry login

docker login command と同じでした。

❯ podman login registry.gitlab.com -u yo_C_ta
Password:
Login Succeeded!

小ネタ :coffee:

調べてて見つけた小ネタです。

所感 :xmas-tree:

なんとなく個人の感想ですが、k8s 化を見据えて何らかのサービスを作っている場合には、初期の段階から k8s yaml の構成を考えていけるので、docker で始めるよりも開発者体験はいいのかなーと思いました。

あと、docker desktop の代替検討として考えると、podman は daemonless らしいので何もしていない時に手元の PC リソースを圧迫しないのもいいのかも(程度は未確認)。

podman 自体のリリースサイクルも早いらしいので、今後さらに期待できそうです :heart_eyes:
乗り換え候補としては十分ありだと思いますが、もう少し他も見てみよう :eyes:

6
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?