コンテナの基礎から学んでECS、EKSを学んでいこうと思い、Docker/Kubernetes実践コンテナ開発入門 (改訂新版)を読んでいたのですが、今回はDockerfileの記述内容の意味を整理するために執筆しました。
本記事ではコンテナとは?という点については焦点を当てておりませんので、その点については割愛させていただきます。
そもそもDockerfileとは
DockerfileとはDockerイメージを作成するためのいわば設計書のようなものです。
コンテナを作成するためには、そのコンテナのイメージが必要になりますが、イメージを作成するためにはコードを記述し、Dockerfileを作成する必要があります。
Dockerfileにはどんなことを記述するの?
Dockerfileに記述する内容は以下のようなものです。
※以下コードはDocker/Kubernetes実践コンテナ開発入門 (改訂新版)から引用させていただきました。
- FROM
- WORKDIR
- RUN
- ENV
- COPY
- CMD
上記について順番に説明していきましょう。
FROM
まずFROMですが、こちらはコンテナのベースとなるイメージを指定します。
ベースとなるイメージとは、OSであればLinuxのディストリビューションを例にお話しさせていただきますと、
Ubuntu、CentOS、AWSであればAmazon Linuxなどが存在しますが、これらのベースをどれにしますか?を決める箇所です。
OS以外でも例えばプログラミング言語のベースイメージはどれにする?といった場合、PHPなのか、GoなのかをFROMで指定してやることで、そのベースのイメージを作成することができます。
本記事の例ではubuntu:23.10と指定していますが、イメージにubuntuを指定し、「:」よりも後ろの数字はタグを指定します。
「タグ」とは言いますが、指定したイメージのバージョンを表しています。ubuntuにもバージョンがありますが、23.10のバージョンを使いますよ、ということを明示的に指定しています。
このタグを指定しない場合は「latest」となります。
もっと一般的な例に置き換えるならば、「Finalfantasy:7 REBIRTH」というイメージにした場合、ベースとなるイメージは「Finalfantasy」,タグ(バージョン)は「7 REBIRTH」のイメージを作る感じです。
WORKDIR
コード内には出てきていませんが、WORKDIRに指定する内容は後述するRUN, COPY, CMDなどの命令する実行するコンテナのディレクトリの場所を指定することになります。
例えばWORKDIR /app
であれば、コンテナ内の/app
ディレクトリでコマンドを実行する、/app
ディレクトリにコピーする、ために指定します。
またコンテナ内に/app
ディレクトリが存在しない場合はどうか?という話ですが、その場合には/app
ディレクトリを新規で作成してくれます。
RUN
次にRUNです。今回示した例ではRUNを以下のように指定しています。
RUN apt update
RUN apt install -y cron
このRUNはDockerのイメージをビルドする際に、コンテナ内で実行するコマンドを定義します。
Dockerイメージをビルドとは、ビルドする際にDockerfileのコードの内容を上から順に読み取ってDockerイメージを作り上げていくわけですが、その際にRUNにコマンドの内容が記述されている場合にはそのコマンドが実行されたイメージが出来上がります。
そのためコンテナを起動する際には、すでにRUNに記述された状態のイメージを起動するわけなので、docker run
などでコンテナを起動したときには既にRUNは実行されています。
順番としては以下でしょう。
$ dockder image build
コマンドでDockerイメージがビルドされる- そのビルドの過程で
RUN
に記述された内容が実行される - コンテナをイメージから起動する際には、すでに
RUN
に記述されたコマンドが実行された状態のものが起動される
ENV
ENVは環境変数を指定します。
MySQLを例に話をします。MySQLのイメージを作成する際には環境変数を渡すことでMySQLの値を設定することができます。
MySQLにおける環境変数とは例えば以下のようなものです。
- MYSQL_ROOT_PASSWORD
- MYSQL_DATADASE
MYSQL_ROOT_PASSWORD
MySQLのrootアカウントに設定するパスワードを指定します。
MYSQL_DATABASE
データベースの名前を指定します。
これらをDockerfileに記述する場合は以下のようになります。
ENV MYSQL_ROOT_PASSWORD
ENV MYSQL_DATABASE
はい、ここで気づいた方もいるかと思いますが、厳密にはENVに環境変数の値を直接は書きません。
外部ファイルに環境変数を定義してファイルを渡す、などの手法が用いられます。
※ここら辺の詳細はdocker-compose.ymlの関する内容を今後ブログでアウトプットできればと思っております。
COPY
ビルドコンテキストのファイルやディレクトリをコンテナ内にコピーします。
COPY task.sh /usr/local/bin/
指定の仕方はCOPY [コピー元] [コピー先] となります。
上記の例だと、task.shをコンテナ内の/usr/local/bin/へコピーする、という意味になります。
ビルドコンテキストとは
docker buildコマンドを実行する際に付与する情報のことを指します。
「ファイルlocationのセット」とも表現することができますが、Dockerfile以外にも同じディレクトリ内にファイルが存在する場合にはファイルlocationのセットの一部であり、それらが「ビルドコンテキスト」になります。
実際にディレクトリ構成を見ながら説明します。
現状のディレクトリ構成は以下のようになっています。
work
└─ ch03
└─cronjob
├─ Dockerfile
└─ task.sh
cronjob配下にDockerfileとtask.shが存在します。task.shがビルドコンテキストとなります。
上記の例ではtask.shのファイルのみしか存在しませんが、ディレクトリを指定すれば、そのディレクトリに存在するファイルすべてがビルドコンテキストということになります。
CMD
RUNはイメージビルド時に実行されるコマンドと説明しましたが、CMDはイメージビルド後にコンテナ起動時に実行します。
CMDの書き方は配列形式で指定をします。
CMD ["cron", "-f"]
上記コマンドがどのように実行されているかというと、以下のコマンドがコンテナ内で実行されます。
$ cron -f
最後に
Dockerfileの内容はなんとなくはわかっていましたが、深堀りすると人に説明できるほどの理解度がなかったため、今回ブログにまとめました。
まだまだ序の口なので今後もDockerに関しての知見を広げていくためにアウトプットしていこうと思っています。