1 はじめに
イメージの作成は、以下の方法があります。
- Containerfileを使う方法
- Podmanのcommitコマンドを使う方法
ここでは、Containerfileを使用したイメージの作り方について説明します。Containerfileでイメージを作成する際には、buildコマンドを使用します。書式は以下の通りです。
$ podman build -t Podmanイメージ名 Containerfile格納ディレクトリ
参考情報:Dockerfile リファレンス — Docker-docs-ja 24.0 ドキュメント
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
3 podmanのインストール方法
podmanパッケージをインストールします。
[root@server ~]# dnf -y install podman
podmanコマンドの版数を確認します。
[root@server ~]# podman -v
podman version 4.9.4-rhel
4 ディレクティブ
ディレクティブとは、Containerfile内に記述するコマンドのことです。ディレクティブを使用すると、コンテナにソフトウェアをインストールしたり、ホストのファイルをコンテナ内にコピーしたりすることができます。
| ディレクティブ |
概要 |
| FROM |
ベースとなるコンテナイメージを指定します |
| COPY |
ホストのファイル、ディレクトリ、URLをコンテナにコピーします。ADD と異なる点は、リモートURL の指定不可、アーカイブファイルを自動で展開しません |
| ADD |
ホストのファイル、ディレクトリ、URLをコンテナにコピーします。ADDはCOPYに比べ多機能ですが、シンプルなコピーにはCOPYを使うことが推奨されているようです |
| RUN |
イメージのビルド中に実行するコマンドを指定します。具体的には、イメージの構築に必要なソフトウェアのインストール、設定変更、ファイルのダウンロードなどを行うことができます |
| ENTRYPOINT |
コンテナが起動したときに実行されるメインプロセスを指定するために使用します |
| CMD |
コンテナが起動するときに実行するコマンドのデフォルトのパラメータを指定します |
| EXPOSE |
コンテナがパケットを待ち受けるポート番号を指定するために使用します。パケットはlistenシステムコールを実行して待ち受けます |
| ENV |
コンテナ内で環境変数を設定するために使用します。これにより、コンテナ内のプロセスが利用する環境変数を定義できます。ENV ディレクティブで設定した環境変数は、結果として作成されたイメージから実行したコンテナでも維持されます |
| LABEL |
イメージに任意のラベル(キー・バリュー形式で指定)を付けるために使用します。ラベルは、プロジェクトでイメージを管理するために使用しま。例えば、誰が作成したイメージなのかといった情報をイメージに付けることができます |
| WORKDIR |
コンテナ内の作業ディレクトリを変更するために使用します |
| USER |
USERディレクティブで指定したユーザー権限でコンテナ内のプロセスやコマンドを実行します |
5 FROMディレクティブの使い方
イメージの初期状態を確認します。
[user1@server ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
[user1@server ~]$ vi Containerfile
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
イメージをビルドします。-t(タグ)オプションは、ビルドするイメージの名前(test_image)を指定します。最後に指定するパラメータは、Containerfile を格納したディレクトリを示します。ここではピリオド(.)を指定しているため、podman コマンドを実行する場所と同じディレクトリに Containerfile があることを意味しています。
[user1@server ~]$ podman build -t test_image .
STEP 1/1: FROM docker.io/library/almalinux
Trying to pull docker.io/library/almalinux:latest...
Getting image source signatures
Copying blob 587e68e1d836 done |
Copying config 8109fa501e done |
Writing manifest to image destination
COMMIT test_image
--> 8109fa501eaf
Successfully tagged localhost/test_image:latest
Successfully tagged docker.io/library/almalinux:latest
8109fa501eaf5af622946e7c5c033cb7aef816c3267b1c17c7b62b34fea099a5
イメージを確認すると、イメージ(test_image)が作成されたことがわかります。
[user1@server ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test_image latest 8109fa501eaf 5 weeks ago 191 MB
docker.io/library/almalinux latest 8109fa501eaf 5 weeks ago 191 MB
次の検証のため、イメージを削除します。
[user1@server ~]$ podman rmi -f $(podman images -q)
6 COPY/ADDディレクティブの使い方
6.1 COPY ディレクティブの使い方
ホストからコンテナにコピーするファイルを作成します。
[user1@server ~]$ vi test.sh
[user1@server ~]$ cat test.txt
12345
作成したファイルの所有者と所有グループを確認します。ホスト環境では、user1 でファイルを作成しているため、所有者および所有グループが user1 になっていることが確認できます。
[user1@server ~]$ ls -l test.txt
-rw-r--r--. 1 user1 user1 6 7月 8 20:20 test.txt
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・ホストで作成したファイル(test.txt)をコンテナの /tmpにコピーする(COPY )
[user1@server ~]$ vi Containerfile
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
COPY test.txt /tmp
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージを確認します。
[user1@server ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test_image latest 4d4957e1ef46 2 seconds ago 191 MB
docker.io/library/almalinux latest 8109fa501eaf 6 weeks ago 191 MB
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image
ce501fb90adaa9828d45f3ad02fb2e24b242048228f42dbc095cfb4fa1265fcc
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
[root@ce501fb90ada /]#
ホストからコンテナにコピーしたファイルを確認します。ファイルの所有者、所有グループはrootになっています。ファイルの所有者、所有グループの変更方法は後述します。
[root@ce501fb90ada /]# ls -l /tmp/test.txt
-rw-r--r--. 1 root root 6 Jul 8 11:20 /tmp/test.txt
コンテナからぬけます。
[root@ce501fb90ada /]# exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
次は、コンテナ内にコピーしたファイルの所有者、所有グループをuser1に変更してみます。
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
RUN adduser user1
COPY test.txt /tmp
RUN chown user1:user1 /tmp/test.txt
コンテナを起動してファイル(/tmp/test.txt)の所有者および所有グループを確認すると user1 に変更されていることが確認できます。
[root@45abd84d6676 /]# ls -l /tmp/test.txt
-rw-r--r--. 1 user1 user1 6 Jul 8 11:20 /tmp/test.txt
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
6.2 ADDディレクティブの使い方
6.2.1 圧縮ファイルのコピー
(1) 事前準備(圧縮ファイルの作成)
テスト用のファイルを作成します。
[user1@server ~]$ vi test.txt
[user1@server ~]$ cat test.txt
12345
テスト用の圧縮ファイルを作成します。
[user1@server ~]$ tar -zcvf test.tar.gz test.txt
test.txt
(2) ADDディレクティブの動作確認
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・ホストで作成した圧縮ファイル(test.tar.gz )を解凍してコンテナの/tmpにコピーする(ADD)
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
ADD test.tar.gz /tmp/
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image
23fb9dc21856fd4dec4d02f1310a74d02468213c456dc66dd270bd39ed3b43ca
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
[root@23fb9dc21856 /]#
ADD ディレクティブは圧縮ファイルを解凍してコンテナにコピーするため、ホストで作成した圧縮ファイルがコンテナ内で解凍されることが確認できます。
[root@23fb9dc21856 /]# cat /tmp/test.txt
12345
コンテナからぬけます。
[root@23fb9dc21856 /]# exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
6.2.2 ディレクトリのコピー
ホストでテスト用のディレクトリ、ファイルを作成します。
[user1@server ~]$ mkdir host_dir
[user1@server ~]$ echo "12345" > host_dir/test1.txt
[user1@server ~]$ echo "67890" > host_dir/test2.txt
Containerfileを使って、次の内容のイメージを作成します。
・(FROM )
・ホストで作成したディレクトリ(host_dir )をコンテナの/tmpにコピーする(ADD)
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
ADD host_dir /tmp
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image
ba931b22c906117c514d604b1a556cbc933665b4e39e3500d8e081a0b0c37183
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
[root@ba931b22c906 /]#
コンテナで/tmp配下のファイルを確認します。ホストのhost_dir 配下に作成したファイルがコンテナの/tmp配下にコピーされていることが確認できます。
[root@ba931b22c906 /]# ls -l /tmp/*
-rw-r--r--. 1 root root 6 Jul 14 00:24 /tmp/test1.txt
-rw-r--r--. 1 root root 6 Jul 14 00:24 /tmp/test2.txt
コンテナからぬけます。
[root@ba931b22c906 /]# exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
7 RUNディレクティブの使い方
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・iprouteパッケージをイメージにインストールする(RUN )
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
RUN dnf -y install iproute
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージを確認します。
[user1@server ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test_image latest f28aa2f7799c 54 seconds ago 238 MB
docker.io/library/almalinux latest 8109fa501eaf 5 weeks ago 191 MB
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image
db3023492a4caf5ce9b0b653bc5b2ecb6cba5065ccf68de12e6ed268bc44631c
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
[root@db3023492a4c /]#
コンテナでパッケージを確認すると、iprouteパッケージがインストールされていることが確認できます。
[root@db3023492a4c /]# rpm -qa|grep iproute
iproute-6.2.0-6.el9_4.x86_64
コンテナからぬけます。
[root@db3023492a4c /]# exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
8 ENTRYPOINT/CMDディレクティブの使い方
Dockerfile リファレンス — Docker-docs-ja 24.0 ドキュメントによると、ENTRYPOINTディレクティブは以下の書式があります。 exec 形式が推奨されているようです。ここでも、ディレクティブはexec 形式を使用します。
ENTRYPOINT ["実行ファイル", "パラメータ1", "パラメータ2"]
ENTRYPOINT コマンド パラメータ1 パラメータ2
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・コンテナ起動時に実行するプログラムを指定する(ENTRYPOINT )
・ENTRYPOINT で指定するコマンドのパラメータを指定する(CMD )
[user1@server ~]$ vi Containerfile
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
ENTRYPOINT ["ping","-c","1"]
CMD ["example.com"]
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
もう1つターミナルを開いてtcpdumpを実行します。-iはインタフェース名を指定します。お使いの環境に合わせて適宜変更してください。なお。、tcpdumpの詳細な使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# tcpdump -i enp1s0 icmp -n
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run --name test1 test_image
tcpdumpの実行結果を確認すると、example.com(93.184.215.14)宛てのping実行結果が確認できます。
[root@server ~]# tcpdump -i enp1s0 icmp -n
22:21:10.429828 IP 192.168.122.87 > 93.184.215.14: ICMP echo request, id 20, seq 1, length 64
22:21:10.524670 IP 93.184.215.14 > 192.168.122.87: ICMP echo reply, id 20, seq 1, length 64
digコマンドで確認すると、example.comのIPアドレスは93.184.215.14であることが確認できます。なお、digコマンドの使い方は、digコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# dig example.com +short
93.184.215.14
次の検証のため、コンテナを削除します。
[user1@server ~]$ podman rm test1 --force
次に、コンテナ起動時にパラメータを明示的に指定します。指定するパラメータは、デフォルトゲートウェイのIPアドレス(192.168.122.1)です。
[user1@server ~]$ podman run --name test1 test_image 192.168.122.1
tcpdumpの実行結果を確認すると、example.comに対するpingの結果ではなく、デフォルトゲートウェイのIPアドレス(192.168.122.1)に対するpingの結果であることが確認できます。つまり、CMDで指定したパラメータがコンテナ起動時に指定したパラメータで上書きされたことがわかります。
[root@server ~]# tcpdump -i enp1s0 icmp -n
22:27:21.353640 IP 192.168.122.87 > 192.168.122.1: ICMP echo request, id 24, seq 1, length 64
22:27:21.353973 IP 192.168.122.1 > 192.168.122.87: ICMP echo reply, id 24, seq 1, length 64
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
9 EXPOSEディレクティブの使い方
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・コンテナのhttpdが80番ポートでリッスンする(EXPOSE )
[user1@server ~]$ vi Containerfile
[user1@server ~]$ cat Containerfile
FROM httpd:latest
EXPOSE 80
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
作成したイメージを確認します。
[user1@server ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test_image latest 72416f67c6ae 36 seconds ago 152 MB
docker.io/library/httpd latest c0c20df5e7be 5 days ago 152 MB
ビルドしたイメージ(test_image)からコンテナを起動します。このとき、-pオプションを使って、ホストの8080番ポートへのアクセスをコンテナの80番ポートにマッピングします。
[user1@server ~]$ podman run -d -p 8080:80 --name test1 test_image
1f8a374faf80f2bd28b48710de04b74f8d2cdc2ef98489f4e6d027136fc271d4
ポートのマッピングを確認します。ホストの任意(0.0.0.0)のIPアドレスに対する8080番ポートへのアクセスが、コンテナの80番ポートへのアクセスに変換されることが確認できます。
[user1@server ~]$ podman port test1
80/tcp -> 0.0.0.0:8080
curlコマンドを実行してホストの8080番ポートにアクセスしてみます。コンテナのhttpdからの応答を確認することができます。
[user1@server ~]$ curl http://localhost:8080
<html><body><h1>It works!</h1></body></html>
コンテナからぬけます。
[root@db3023492a4c /]# exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
10 ENVディレクティブの使い方
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・環境変数(TEST)に文字列("Hello, World!")を設定する(ENV )
・環境変数に設定した文字列をechoコマンドで出力する(CMD )
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
ENV TEST="Hello, World!"
CMD echo $TEST
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。コンテナを起動する際に、環境変数TESTに設定した文字列が出力されることを確認できます。
[user1@server ~]$ podman run --name test1 test_image
Hello, World!
あと始末をします。
[user1@server ~]$ podman rm test1
test1
コンテナを実行する際に、設定された環境変数を上書きすることもできます。例えば、環境変数TESTに"bye"を設定してコンテナを起動してみます。この場合、コンテナが起動する際に、”Hello, World!”ではなく"bye"が出力されることを確認できます。
[user1@server ~]$ podman run -e TEST=bye --name test1 test_image
bye
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
11 LABELディレクティブの使い方
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・イメージにラベルをつける(LABEL )。ラベルの内容は、作成者(maintainer)、イメージのバージョン(version)、イメージの作成日(2024/7/10)
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
LABEL maintainer="[email protected]"
LABEL version="1.0"
LABEL created="2024-07-10"
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
Podmanのinspectコマンドとjqコマンドを併用して、イメージに付けたラベルを確認してみます。なお、io.buildah.versionはBuildahのバージョン情報を示しており、ビルドツールが自動的に追加するものです。
[user1@server ~]$ podman inspect test_image --format '{{json .Config.Labels}}' | jq
{
"created": "2024-07-10",
"io.buildah.version": "1.33.7",
"maintainer": "[email protected]",
"version": "1.0"
}次の検証のため、イメージを削除します。
[user1@server ~]$ podman rmi -f $(podman images -q)
12 WORKDIRディレクティブの使い方
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・作業ディレクトリを /etc に変更する(WORKDIR )
・ファイル(test.conf)に文字列を書き込む(RUN )
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
WORKDIR /etc
RUN echo "Hello" > test.conf
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image
734466e173c07719688d9deb0304eacc4ece68bdb3cbc58685b47954142c8eae
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
[root@734466e173c0 etc]#
作業ディレクトリを確認すると /etc であることが確認できます。
[root@734466e173c0 etc]# pwd
/etc
ファイル(test.conf)に書き込んだ内容を確認すると、"Hello"であることが確認できます。
[root@734466e173c0 etc]# cat test.conf
Hello
コンテナからぬけます。
[root@734466e173c0 etc]# exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
13 USERディレクティブの使い方
Containerfileを使って、次の内容のイメージを作成します。
・ベースイメージにAlmaLinuxを使用する(FROM )
・ユーザー(user2)を作成する(RUN )
・実行ユーザーをuser2に変更する(USER )
・作業ディレクトリを/home/user2に変更する(USER )
[user1@server ~]$ cat Containerfile
FROM docker.io/library/almalinux
RUN adduser user2
USER user2
WORKDIR /home/user2
イメージをビルドします。
[user1@server ~]$ podman build -t test_image .
ビルドしたイメージ(test_image)からコンテナを起動します。
[user1@server ~]$ podman run -dit --name test1 test_image
ae3345f70a53062894ff5b050ff48fe7225553d0799d97f2e38baddee92a1692
コンテナでbashを実行します。
[user1@server ~]$ podman exec -it test1 bash
[user2@ae3345f70a53 ~]$
idコマンドを使用してユーザー名を確認してみます。ユーザ名がuser2であることが確認できます。
[user2@ae3345f70a53 ~]$ id
uid=1000(user2) gid=1000(user2) groups=1000(user2)
次に、pwdコマンドを使用して現在の作業ディレクトリを確認すると、作業ディレクトリが/home/user2であることが確認できます。
[user2@ae3345f70a53 ~]$ pwd
/home/user2
コンテナからぬけます。
[user2@ae3345f70a53 ~]$ exit
exit
次の検証のため、コンテナ、イメージを削除します。
[user1@server ~]$ podman rm test1 --force
[user1@server ~]$ podman rmi -f $(podman images -q)
Y 参考図書
今回の記事執筆にあたり参考にした図書は以下のものです。