Podmanでコンテナ/ホスト間でファイルをコピーする方法
- 1 はじめに
- 2 検証環境
- 3 インストール方法
- 4 事前準備
- 5 コンテナ/ホスト間でファイルをコピーする方法
- 6 マウントする方法
- 7 イメージを作成する方法(commit)
- Y 参考図書
- Z 参考情報
1 はじめに
- コンテナ/ホスト間でファイルをコピーする方法
- ボリュームをマウントする方法
- コンテナをイメージ化する方法
2 検証環境
サーバのAlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 5.14.0-284.11.1.el9_2.x86_64
SELinuxは有効にしておきます。
[root@server ~]# getenforce Enforcing
3 インストール方法
podmanパッケージをインストールします。
[root@server ~]# dnf -y install podman
podmanコマンドの版数を確認します。
[root@server ~]# podman -v podman version 4.9.4-rhel
4 事前準備
テスト用のユーザを作成します。
[root@server ~]# useradd user1
user1のパスワードを設定します。
[root@server ~]# passwd user1
以降の作業は、一般ユーザで実行します。
[user1@server ~]$ id uid=1000(user1) gid=1000(user1) groups=1000(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
almalinuxイメージをダウンロードします。
[user1@server ~]$ podman pull almalinux
ダウンロードしたイメージを確認します。
[user1@server ~]$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/almalinux latest 8109fa501eaf 4 weeks ago 191 MB
5 コンテナ/ホスト間でファイルをコピーする方法
コンテナとホストの間でファイルをコピーする方法について説明します。
書式は以下のとおりです。
- ホストからコンテナにファイルをコピーする時
$ podman cp ホスト側パス コンテナ名:コンテナ側パス
- コンテナからホストにファイルをコピーする時
$ podman cp コンテナ名:コンテナ側パス ホスト側パス
5.1 ホストからコンテナにファイルをコピーする方法
test1という名前のコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 almalinux 06ed782d14df2a869b2a3b10eaee8a59c1e55a28f834ad7c4836eebed4bd222c
起動したコンテナを確認します。
[user1@server ~]$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 06ed782d14df docker.io/library/almalinux:latest /bin/bash 11 seconds ago Up 11 seconds test1
コンテナにコピーするファイルを作成します。
[user1@server ~]$ echo "test" > test.txt [user1@server ~]$ cat /home/user1/test.txt test
ファイルをコンテナの/tmpにコピーします。
[user1@server ~]$ podman cp /home/user1/test.txt test1:/tmp
コンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test1 bash [root@06ed782d14df /]#
コピーしたファイルを確認します。ホストで作成したファイルがコンテナにコピーできていることが確認できます。
[root@06ed782d14df /]# cat /tmp/test.txt test
5.2 コンテナからホストにファイルをコピーする方法
ホストにコピーするファイルを作成します。
[root@06ed782d14df /]# echo "12345" > /tmp/test.txt
作成したファイルの中身を確認します。
[root@06ed782d14df /]# cat /tmp/test.txt 12345
コンテナから抜けます。
[root@06ed782d14df /]# exit exit
コンテナの /tmp/test.txt をホストの /home/user1/test2.txt にコピーします。
[user1@server ~]$ podman cp test1:/tmp/test.txt /home/user1/test2.txt
コピーしたファイルを確認します。コンテナで作成したファイルがホストにコピーできていることが確認できます。
[user1@server ~]$ cat /home/user1/test2.txt 12345
6 マウントする方法
6.1 概要
ボリュームやファイル/ディレクトリのマウントについて説明します。
| マウント方法 | 概要 |
|---|---|
| ボリュームマウント | ボリュームとは、ハードディスクの1つの領域です。作成したボリュームをコンテナ内にマウントする方法です。これにより、データを永続的に保存することができます。例えば、コンテナが削除されたり再起動されたりしても、ボリュームに保存されたデータは失われません。ボリュームは、コンテナ間でデータを共有するためにも使用されます。 |
| バインドマウント | ホストの特定のファイルやディレクトリをコンテナ内にマウントする方法です。これにより、ホスト上のデータをコンテナ内から直接アクセスすることができます |
6.2 ボリュームマウント
ボリューム(vol1)を作成します。
[user1@server ~]$ podman volume create vol1 vol1
作成したボリュームを確認します。vol1という名前のボリュームが作成されたことがわかります。
[user1@server ~]$ podman volume ls DRIVER VOLUME NAME local vol1
コンテナ(test1)を起動します。このとき、作成したボリューム(vol1)をコンテナの/mntにマウントします。
[user1@server ~]$ podman run -dit --name test1 -v vol1:/mnt docker.io/library/almalinux efe1bcf540fc2e947b1f22028b7a297798eccd3934951a0c76de55c2995ba5d1
起動したコンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test1 bash [root@efe1bcf540fc /]#
マウントしたボリュームにファイルを作成します。
[root@efe1bcf540fc /]# echo "12345" > /mnt/file1.txt [root@efe1bcf540fc /]# cat /mnt/file1.txt 12345
コンテナからぬけます。
[root@efe1bcf540fc /]# exit exit
コンテナ(test2)を起動します。このとき、作成したボリューム(vol1)をコンテナの/mntにマウントします。
[user1@server ~]$ podman run -dit --name test2 -v vol1:/mnt docker.io/library/almalinux 2f54ed031bcae970db373f2a5e479db34e6f588c4a5b1ae179f60bfdfbffef5f
起動したコンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test2 bash [root@2f54ed031bca /]#
マウントしたボリューム内のファイルの内容を確認します。このファイルはtest1コンテナで作成されたものですが、test2コンテナでもその内容を参照できることが確認できます。
[root@2f54ed031bca /]# cat /mnt/file1.txt 12345
コンテナからぬけます。
[root@2f54ed031bca /]# exit exit
コンテナを削除します。
[user1@server ~]$ podman rm test1 test2 --force
作成したボリュームを削除します。
[user1@server ~]$ podman volume rm vol1 vol1
6.3 バインドマウント
SELinuxが有効な場合、マウントしたボリュームやファイルにアクセスできません。マウントする際、状況に応じて z(小文字)または Z(大文字)を指定する必要があります。これらのオプションを指定すると、PodmanがボリュームやファイルのSELinuxコンテキストを再ラベルします。これにより、コンテナがマウントしたボリュームやファイルにアクセスできるようになります。
| オプション | 概要 |
|---|---|
| z(小文字) | 複数のコンテナでボリュームやファイルを共有する場合 |
| Z(大文字) | 他のコンテナとボリュームやファイルを共有しない場合 |
podman-run — Podman documentationよりオプションの説明を以下に引用します。
To change a label in the container context, add either of two suffixes :z or :Z to the volume mount. These suffixes tell Podman to relabel file objects on the shared volumes. The z option tells Podman that two or more containers share the volume content. As a result, Podman labels the content with a shared content label. Shared volume labels allow all containers to read/write content. The Z option tells Podman to label the content with a private unshared label Only the current container can use a private volume. Relabeling walks the file system under the volume and changes the label on each file, if the volume has thousands of inodes, this process takes a long time, delaying the start of the container. If the volume was previously relabeled with the z option, Podman is optimized to not relabel a second time. If files are moved into the volume, then the labels can be manually change with the chcon -Rt container_file_t PATH command.
コンテナがマウントするディレクトリを作成します。
[root@server ~]# mkdir /host_dir
作成したディレクトリの所有者(ユーザ、グループ)をrootからuser1に変更します。
[root@server ~]# chown user1:user1 /host_dir/
ディレクトリの所有者(ユーザ、グループ)を確認します。所有者がuser1に変更されたことがわかります。また、/host_dirのコンテキストは以下のようになっています。
- ユーザ:unconfined_u
- ロール:object_r
- タイプ:default_t
[root@server ~]# ls -ldZ /host_dir drwxr-xr-x. 2 user1 user1 unconfined_u:object_r:default_t:s0 6 7月 7 22:50 /host_dir
マウントするディレクトリにファイルを作成します。
[user1@server ~]$ echo "12345" > /host_dir/test.txt [user1@server ~]$ cat /host_dir/test.txt 12345
コンテナを起動します。このとき、大文字のZを指定して、マウントするディレクトリを他のコンテナと共有しないようにしてみます。
[user1@server ~]$ podman run --name test1 -dit -v /host_dir:/var:Z docker.io/library/almalinux:latest 265a303d3dcf22b80d21f90b34d5f283fcf40db273fb71a209588c7c37278c2e
起動したコンテナでbashコマンドを実行します。
[user1@server ~]$ podman exec -it test1 bash [root@265a303d3dcf /]#
マウントしたディレクトリのファイルの中身を確認します。
[root@265a303d3dcf /]# cat /var/test.txt 12345
コンテナからぬけます。
[root@265a303d3dcf /]# exit exit
あと始末をします。
[user1@server ~]$ podman rm test1 --force
マウントしたディレクトリのSELinuxコンテキストを確認します。コンテキストのタイプがdefault_tからcontainer_file_tに変更されていることがわかります。これは、Zオプションを付けることで、コンテナが/host_dirにアクセスできるように、ディレクトリのコンテキストタイプがdefault_tからcontainer_file_tに変更されたためです。
[user1@server ~]$ ls -ldZ /host_dir drwxr-xr-x. 2 user1 user1 system_u:object_r:container_file_t:s0:c168,c334 22 7月 7 22:53 /host_dir
タイプを元のdefault_t に戻す場合は、以下のようにchconコマンドを実行します。
[user1@server ~]$ chcon -t default_t /host_dir
ディレクトリのSELinuxコンテキストを確認します。コンテキストのタイプがdefault_tに戻ったことがわかります。
[user1@server ~]$ ls -ldZ /host_dir/ drwxr-xr-x. 2 user1 user1 system_u:object_r:default_t:s0:c168,c334 22 7月 7 22:53 /host_dir/
7 イメージを作成する方法(commit)
イメージを作成する方法は2つあります。
1. podman commitコマンドでコンテナをイメージに書き出す方法
2. Containerfileからイメージを作成する方法
ここでは、1について説明します。2については別の記事で説明します。
イメージを確認します。
[user1@server ~]$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/almalinux latest 8109fa501eaf 4 weeks ago 191 MB
イメージ(almalinux)からコンテナ(test1)を起動します。
[user1@server ~]$ podman run -dit --name test1 almalinux 9bfd0427bbdd1482f17ea78a9b717b9b3e6f86298c924ae4d99508ad0b2d118c
コンテナ(test1)に入り、bashシェルを起動します。
[user1@server ~]$ podman exec -it test1 bash [root@9bfd0427bbdd /]#
ipコマンドの版数を確認してみます。しかし、イメージ(almalinux)にはipコマンドが入っていないので、エラーになります。
[root@9bfd0427bbdd /]# ip -V bash: ip: command not found
dnfコマンドを実行して、iprouteパッケージをインストールします。
[root@9bfd0427bbdd /]# dnf -y install iproute
ipコマンドの版数を確認します。
[root@9bfd0427bbdd /]# ip -V ip utility, iproute2-6.2.0, libbpf 1.3.0
コンテナから抜けます。
[root@9bfd0427bbdd /]# exit exit
もう1つターミナルを開いて、コンテナをイメージ(test-ip)に書き出します。
[user1@server ~]$ podman commit test1 test1-ip Getting image source signatures Copying blob 926bdaa81747 skipped: already exists Copying blob 878b4f5d7422 done | Copying config f88cafa116 done | Writing manifest to image destination f88cafa116a62a69141aed482e81a49280712084662cb5a4176202c5940231b1
イメージを確認すると、test1-ipという名前のイメージが作成できたことがわかります。
[user1@server ~]$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/test1-ip latest f88cafa116a6 About a minute ago 238 MB docker.io/library/almalinux latest 8109fa501eaf 4 weeks ago 191 MB
イメージ(test1-ip)からコンテナ(test2)を起動します。
[user1@server ~]$ podman run -dit --name test2 test1-ip fe5e178feca69b92b753d7f7b3963080fdfb55792f5003e5de3a48c0fb3c1cd9
コンテナ(test2)に入り、bashシェルを起動します。
[user1@server ~]$ podman exec -it test2 bash [root@fe5e178feca6 /]#
ipコマンドのバージョンを確認します。イメージ(test1-ip)には最初からipコマンドが含まれているため、ipコマンドのバージョン確認をしてもエラーにならないことが確認できます。
[root@fe5e178feca6 /]# ip -V ip utility, iproute2-6.2.0, libbpf 1.3.0
Y 参考図書
今回の記事執筆にあたり参考にした図書は以下のものです。
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ




