はじめに
前回の記事 に引き続いて、Docker の代わりに Podman を使うためにどのような差分があるのかを見ていく。
Podman Volume
MySQLなどをサーバー上で利用する場合、ボリュームを永続化しておく必要がよい (そうしないと、コンテナの削除などでデータが消えてしまうなど問題が出る)。 この時、Docker では docker volume
で永続化したボリュームを作成してこれを利用する。
Podman の場合も同様に podman volume
コマンドがあるので、これを利用してボリュームを作成できる。 この時は Podman で用意されたと考えられるデフォルトディレクトリがマウントされる。
# rootless の場合
$ podman volume create sample
sample
$ podman volume inspect sample
[
{
"Name": "sample",
"Driver": "local",
"Mountpoint": "/home/centos/.local/share/containers/storage/volumes/sample/_data",
"CreatedAt": "2020-07-13T17:41:12.27273779+09:00",
"Labels": {
},
"Scope": "local",
"Options": {
},
"UID": 0,
"GID": 0,
"Anonymous": false
}
]
# rootful な場合
$ sudo podman volume create sudo-sample
sudo-sample
$ sudo podman volume inspect sudo-sample
[
{
"Name": "sudo-sample",
"Driver": "local",
"Mountpoint": "/var/lib/containers/storage/volumes/sudo-sample/_data",
"CreatedAt": "2020-07-13T17:41:58.770498487+09:00",
"Labels": {
},
"Scope": "local",
"Options": {
},
"UID": 0,
"GID": 0,
"Anonymous": false
}
]
特定パスをマウントしたボリュームの作成
個人的には特定のパス (例えば、 /opt/mount/mysql
)をマウントポイントにしたい、といったケースがある。
この場合、Docker では 例えばこちらの記事にあるように docker-compose.yml に以下のような記述を書いて volume をマウントしていた。
volumes:
datastore:
driver_opts:
type: none
device: /opt/mount/mysql
o: bind
これは同様の方法の内容を podman
コマンドで実現して、ボリュームを作成できる。
$ podman volume create -o type=none -o device=/opt/mount/mysql -o o=bind datastore
ただ、この方法で作成したボリュームは rootful でなければマウントできないようだ。
そのため、もしこの方法を使うというのであれば rootful なコンテナに対して利用する。
$ podman run --rm -v datastore:/tmp2 nginx touch /tmp2/hoge
Error: error mounting volume datastore for container 549045ccdd392987427598764ffc0b533fdb5d6a6b31bd4172aa28282bc15e2d: cannot mount volumes without root privileges: operation requires root privileges
……のだが、ルートで実行するとどうなるか。 以下の通り Permission denied ではじかれてしまう。 ディレクトリパーミッションが 777
であるにも関わらず、である。
# パーミッションは問題ない
$ ls -l /opt/mount/
total 0
drwxrwxrwx. 2 root root 6 Jul 13 18:00 mysql
$ sudo podman run --rm -v datastore:/tmp2 nginx touch /tmp2/hoge
touch: cannot touch '/tmp2/hoge': Permission denied
マウントボリュームが Permission denied
今回の検証環境が RedHat 系ということで、心当たりがある人がいるかもしれないが、結論から言えば原因は SELinux である。 今回の検証環境では sestatus = enabled
の状態で検証している。 公式のトラブルシュートで2番目に述べられている通り、非常に多くの人が引っかかる問題のようだ。 紹介されている解消法は2つ。
-
-v
の第三引数として:z
あるいは:Z
オプションをつける- Docker にも存在するオプションで、SELinux用のラベルの付け替えを行う
-
--security-opt label=disable
を指定することでコンテナに対するセキュリティラベリングを無効化する- こちらも同様にDockerにも存在するオプション
今回は後者のオプションをつけて、SELinuxのセキュリティラベリングを無効化して動作させる。 これでマウントができていることが確認できた。
$ sudo podman run --security-opt label=disable --rm -v datastore:/tmp2 nginx touch /tmp2/hoge
$ ls -l /opt/mount/mysql/
total 0
-rw-r--r--. 1 root root 0 Jul 13 18:28 hoge
MySQL の永続化
ということで本題。 一度 sudo podman rm -af && sudo podman volume rm -af
を実施して、一通り削除してから開始します。
# ボリューム datastore を作成
$ sudo podman volume create -o type=none -o device=/opt/mount/mysql -o o=bind datastore
datastore
# マウントしてMySQLを起動
$ sudo podman run --security-opt label=disable -d -v datastore:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=sample mysql
a40dc20b6246411acc57bb0c7b19825579f95acfe25296685009f7c89e1a9c18
# MySQL DBに接続してデータベースを作成 (内容を変化させる)
$ sudo podman exec -it a40 mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database hogehoge;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| hogehoge |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql>
mysql> exit;
Bye
# マウントしたホストのディレクトリにデータが書き込まれていることを確認
$ ls -l /opt/mount/mysql/
total 186776
-rw-r-----. 1 systemd-coredump input 56 Jul 13 18:34 auto.cnf
-rw-r-----. 1 systemd-coredump input 3104223 Jul 13 18:34 binlog.000001
-rw-r-----. 1 systemd-coredump input 353 Jul 13 18:34 binlog.000002
-rw-r-----. 1 systemd-coredump input 32 Jul 13 18:34 binlog.index
-rw-------. 1 systemd-coredump input 1680 Jul 13 18:34 ca-key.pem
-rw-r--r--. 1 systemd-coredump input 1112 Jul 13 18:34 ca.pem
-rw-r--r--. 1 systemd-coredump input 1112 Jul 13 18:34 client-cert.pem
-rw-------. 1 systemd-coredump input 1676 Jul 13 18:34 client-key.pem
drwxr-x---. 2 systemd-coredump input 6 Jul 13 18:34 hogehoge
-rw-r-----. 1 systemd-coredump input 196608 Jul 13 18:34 '#ib_16384_0.dblwr'
-rw-r-----. 1 systemd-coredump input 8585216 Jul 13 18:34 '#ib_16384_1.dblwr'
-rw-r-----. 1 systemd-coredump input 5642 Jul 13 18:34 ib_buffer_pool
-rw-r-----. 1 systemd-coredump input 12582912 Jul 13 18:34 ibdata1
-rw-r-----. 1 systemd-coredump input 50331648 Jul 13 18:34 ib_logfile0
-rw-r-----. 1 systemd-coredump input 50331648 Jul 13 18:34 ib_logfile1
-rw-r-----. 1 systemd-coredump input 12582912 Jul 13 18:34 ibtmp1
drwxr-x---. 2 systemd-coredump input 187 Jul 13 18:34 '#innodb_temp'
drwxr-x---. 2 systemd-coredump input 143 Jul 13 18:34 mysql
-rw-r-----. 1 systemd-coredump input 30408704 Jul 13 18:34 mysql.ibd
drwxr-x---. 2 systemd-coredump input 8192 Jul 13 18:34 performance_schema
-rw-------. 1 systemd-coredump input 1680 Jul 13 18:34 private_key.pem
-rw-r--r--. 1 systemd-coredump input 452 Jul 13 18:34 public_key.pem
-rw-r--r--. 1 systemd-coredump input 1112 Jul 13 18:34 server-cert.pem
-rw-------. 1 systemd-coredump input 1680 Jul 13 18:34 server-key.pem
drwxr-x---. 2 systemd-coredump input 28 Jul 13 18:34 sys
-rw-r-----. 1 systemd-coredump input 10485760 Jul 13 18:34 undo_001
-rw-r-----. 1 systemd-coredump input 12582912 Jul 13 18:34 undo_002
上で作ったコンテナ・ボリュームをわざと削除して、データが削除されていないかを確認します。
# Podman上のコンテナとボリュームを全削除
$ sudo podman rm -af
a40dc20b6246411acc57bb0c7b19825579f95acfe25296685009f7c89e1a9c18
$ sudo podman volume rm -af
datastore
# 再度ボリュームをマウントし、MySQLコンテナを生成
$ sudo podman volume create -o type=none -o device=/opt/mount/mysql -o o=bind datastore
datastore
# -- NOTE: ここで既に初期化済の MySQL データをバインドしているのでパスワードは不要
$ sudo podman run --security-opt label=disable -d -v datastore:/var/lib/mysql mysql
a5a2dc5121ce3bacc805d2f3a227af4f43edb48c083a4ca8c381029f38cc1c5e
# 消去したPodmanのボリューム内に変更されたデータがローカル側にバインドされていることを確認
# (Database: hogehoge が存在する)
$ sudo podman exec -it a5a mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| hogehoge |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
ということで永続化ができていることが確認できます。
まとめ
この部分はほとんど Docker と同じでした。