Dockerfile内でよく使う命令をまとめてみました。
この記事では2つの命令を解説しますが、どちらも、多用することの多い命令になります。
CMD命令は、イメージをコンテナとして実行したときのデフォルトの実行命令を指定する命令です。
RUN命令との違いはRUN命令はイメージ生成時に動作するのに対し、CMD命令はイメージ生成時には動作しません。
この影響でCMD命令はイメージのレイヤーを増加させません。
CMD命令は、1つしか有効にできません。
複数記述してある場合は、最後に記述されているCMD命令が有効になります。
また、CMD命令は少し記述方法が特殊になります。
CMD ["命令","引数1","引数2",...]
このように、[]
で囲みつつ、命令と引数をすべてダブルクォーテーション
で囲んで指定します。
配列のような指定方法と思っていただければいいかと思います
引数には、ls
命令であれば-l
オプションや-a
オプションなどになります。
もちろん、gcc
命令のようにmain.c
のようなファイルの指定もできます。
例 : ubuntuイメージのデフォルト実行命令をイメージ生成時にコンパイルしたバイナリを実行する
当然バイナリは、実行するOSごとにコンパイルする必要があるので、ホストOSでコンパイルしてイメージ内にCOPY
するという方法は使えません。
ホストOSでソースコードを用意して、それをイメージ内にコピー(COPY)してgcc(RUN)して、デフォルト実行するコマンドをa.out
にしてバイナリを実行させてみようと思います
まずは全体のフォルダ構成です。カレントディレクトリの矢印が付いているフォルダ
にいる状態でdockerコマンドを実行していきます
DockerTest/ <- カレントディレクトリ
- main.c
- Dockerfile
main.cファイルを以下のような記述で作成しました。
#include <stdio.h>
int main(){
printf("Hello CMD");
return 0;
}
dockerfileのFORM
命令で持ってくるベースイメージはgccを指定します。
FROM gcc
# コピー
COPY main.c main.c
# コンパイル実行
RUN gcc main.c
# コンパイルの結果生成されたa.outをデフォルト実行に設定
CMD ["./a.out"]
まずは、イメージをビルドします。
生成するイメージは`gcc-testとしました。
docker image build -t gcc-test .
実行すると以下のようなログが流れて正常にイメージを生成できるかと思います。
[+] Building 33.9s (8/8) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 225B 0.0s
=> [internal] load metadata for docker.io/library/gcc:latest 2.2s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/3] FROM docker.io/library/gcc:latest@sha256:de5eab50ec2a4f64aa63b13cf14406a9266fce4016a9401c40 29.7s
=> => resolve docker.io/library/gcc:latest@sha256:de5eab50ec2a4f64aa63b13cf14406a9266fce4016a9401c403 0.0s
=> => sha256:a8b1354530263850950f06cdaf2fba4d2ee014b2c2ac6bc5a2a8097d89dd77f5 1.80kB / 1.80kB 0.2s
=> => sha256:c02a85f4822d38153c9749e5481a33ec72b748938c199687c674b0772cb7f12d 9.63kB / 9.63kB 0.4s
=> => sha256:5a943f17ed11816067c3d8776686b9c3744c060e4e28641d98f2e063ec313a0d 157.73MB / 157.73MB 19.6s
=> => sha256:a74f2e01d9631f365fbeb32a320522f9ad65c8e3457c5cb73e5fb93857b39561 2.81MB / 2.81MB 1.0s
=> => sha256:1c8ff076d818ad6b8557e03e10c83657cc716ab287c8380054ff91571c8cae81 211.27MB / 211.27MB 22.1s
=> => sha256:2e66a70da0bec13fb3d492fcdef60fd8a5ef0a1a65c4e8a4909e26742852f0f2 64.15MB / 64.15MB 10.6s
=> => sha256:2e6afa3f266c11e8960349e7866203a9df478a50362bb5488c45fe39d99b2707 24.05MB / 24.05MB 4.3s
=> => sha256:8cd46d290033f265db57fd808ac81c444ec5a5b3f189c3d6d85043b647336913 49.56MB / 49.56MB 7.6s
=> => extracting sha256:8cd46d290033f265db57fd808ac81c444ec5a5b3f189c3d6d85043b647336913 3.0s
=> => extracting sha256:2e6afa3f266c11e8960349e7866203a9df478a50362bb5488c45fe39d99b2707 1.0s
=> => extracting sha256:2e66a70da0bec13fb3d492fcdef60fd8a5ef0a1a65c4e8a4909e26742852f0f2 3.5s
=> => extracting sha256:1c8ff076d818ad6b8557e03e10c83657cc716ab287c8380054ff91571c8cae81 4.4s
=> => extracting sha256:a74f2e01d9631f365fbeb32a320522f9ad65c8e3457c5cb73e5fb93857b39561 0.1s
=> => extracting sha256:5a943f17ed11816067c3d8776686b9c3744c060e4e28641d98f2e063ec313a0d 2.8s
=> => extracting sha256:c02a85f4822d38153c9749e5481a33ec72b748938c199687c674b0772cb7f12d 0.0s
=> => extracting sha256:a8b1354530263850950f06cdaf2fba4d2ee014b2c2ac6bc5a2a8097d89dd77f5 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 108B 0.0s
=> [2/3] COPY main.c main.c 1.2s
=> [3/3] RUN gcc main.c 0.4s
=> exporting to image 0.2s
=> => exporting layers 0.1s
=> => exporting manifest sha256:f06f3edbbe22191eeb02aa28d791f24530d1943e0bd02d68853fb579b73e88f4 0.0s
=> => exporting config sha256:b4db4e2d264346fb4450021197c5a14d2dfbb4f0581306d5fef003864517033e 0.0s
=> => exporting attestation manifest sha256:7024b7972794fd855cb61631602709469fde1809b6670f1b6019beb2c 0.0s
=> => exporting manifest list sha256:b4e95797eff29aab3767a1b50e17947033571f0c585237547de88c6781c4749f 0.0s
=> => naming to docker.io/library/gcc-test:latest 0.0s
=> => unpacking to docker.io/library/gcc-test:latest
その後、コンテナを実行して「デフォルトでHello CMD
」が実行されるかを確認します
このコンテナでは、特に入力もせずに出力を1行見たいだけなので-it
のようなオプションはつけず、--rm
で実行後自動で削除されるように設定します
docker container run --rm gcc-test
実行して、以下のような表示がされれば無事にCMDの設定ができていたということになります
Hello CMD
WORKDIR命令は、イメージビルド時の処理のカレントディレクトリの変更と、コンテナ生成時のデフォルトディレクトリの設定を行います。
WORKDIR命令を使っていない場合は、デフォルトで/
がカレントディレクトリになっているはずです。(Ubuntuは)
イメージビルド時のカレントディレクトリの変更ができるので、「特定のディレクトリに移動してRUN
でコマンドを実行したい」や「コンテナ起動時のディレクトリをすぐに作業を始められるディレクトリにしたい」などの設定ができるようになっています
例 : 階層の移動が分かりやすいようにtouch命令を実行して痕跡をたどる
今回はシンプルに、Dockerfile
だけの以下のフォルダ構成で動作の確認をしていきます。
DockerTest\
- Dockerfile
Dcokerfile
の内部では、WORKDIRを3回、touchを3回行いディレクトリの移動の形跡を残すことで動作の履歴を見ていきます。
FROM ubuntu:20.04
RUN touch 1.txt
WORKDIR /myApp
RUN touch 2.txt
WORKDIR ../
RUN touch 3.txt
WORKDIR /testDir
想定では以下のようにファイルとディレクトリが生成されると思っています。
\
- 1.txt
- ...
- myApp\
- 2.txt
- 3.txt
- testDir <- コンテナ起動時のカレントディレクトリ
では、まずは、イメージをビルドしていきます。
docker image build -t workdir-test .
特にエラーが出なければ、生成したworkdir-test
イメージからコンテナを生成して内部のBashを使って想定通りの構造になっているか確認します。
docker container run -it --rm workdir-test
以下が確認したときのログになります。
正常に想定通りのファイル構造とデフォルトディレクトリになっているのが確認できると思います。
root@05c0f42fa214:/testDir# pwd
/testDir
root@05c0f42fa214:/testDir# ls ../
1.txt bin dev home lib32 libx32 mnt opt root sbin sys tmp var
3.txt boot etc lib lib64 media myApp proc run srv testDir usr
root@05c0f42fa214:/testDir# ls ../myApp/
2.txt
地味に多用するコマンドの紹介でした。
頭の中で想定しているとどうしてもこんがらがってしまうので、Dockerの強みの小回りが利くことを利用して実際に動かしてみて想定通りの動作になっているかをチェックしながらDockerfileを構築していくのがいいかと思います。