2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

コンテナを使って開発をする機会が多いですが、業務ではすでに環境が用意されていることが多くDockerfileを触る機会は少ないと思います。
テンプレートや既存のDockerfileをどこかからコピーしてきて、そのまま使うことなども多く、理解できていないがちなので、復習も兼ねてまとめたいと思います。

Dockerfileの基本文法

FROM

カスタムimageのベースになるimageを指定します。
Docker Hubのような公開されているリポジトリからimageを引っ張ってくることができます。

imageは1:1ではなく、tagを使って複数の種類が公開されています。
例えば、bookworm(Debian12)をベースにNode v22.12をインストールしているimageを使う場合は、以下のように指定します。

FROM node:22.12-bookworm

WORKDIR

RUN, CMD, ENTRYPOINT, ADD, COPYを実行する際の作業ディレクトリを指定します。
ここで指定したディレクトリが存在しない場合は自動で作成されます。

以下のように指定すると/appが作成され、そこをworking directoryとして他の命令類が実行されます。

WORKDIR /app

COPY

COPY <コピー元> <コピー先>のように指定し、ローカルにあるコピー元のファイルやディレクトリをコピー先のパスにコピーします。
この時のコピー先のパスは、WORKDIRからの相対パスになります。

WORKDIR /app
COPY . .

上記のような条件を想定すると、ホスト側のカレントディレクトリ(Dockerfileが存在するディレクトリ)を、コンテナ内の/appディレクトリにコピーします。

これに似た機能としてADD命令がありますが、基本的にはCOPY命令を使う方が良いようです。

RUN

Dockerfileで作成するカスタムimageのビルド時に実行されます。
コンテナの実行時ではなくビルド時です。

以後必要になるソフトウェアパッケージのインストールなどを行うことが多いです。

debian系のベースimageを使った場合、apt-getでパッケージをインストールすると思いますが、現在利用可能なパッケージのリストを更新(apt-get update)と、パッケージのインストールは同一RUN命令内で実行するのがベストプラクティスのようです。

RUN apt-get update && apt install -y \
    git \
    gcc \
    # ...

CMD

コンテナを起動するときに実行するデフォルトのコマンドを指定します。
デフォルトなので、引数として実行するコマンドを指定した場合はそちらが優先されます。
なので、CMD [ "bash" ]があるDockerfileをbuildして実行するのと、CMDが指定されていないDockerfileをbuildして、$ docker run -it --name CONTAINER_NAME IMAGE_NAME bashをすることによって得られる結果は同じになります。

公開されているimageを確認すると、defaultの挙動としてのCMDが指定されていることを確認できるはずです。
例えば、mysql:8.0ではCMD ["mysqld"]が指定されていますが、character-setの設定を変えて起動したい時などは、引数で実行したいコマンドを指定します。

docker run -it --name mysql mysql:8.0 mysqld --character-set-server=utf8

ENTRYPOINT

dockerではデフォルトのentrypointとして、/bin/sh -cが指定されています。

例えば、以下のようなDockerfileをビルドして、コンテナを立ち上げるとCMDに指定したコマンドが/bin/bash -cの引数に渡されていることがわかります。(後から解説しますがshell形式で指定しているのがポイントです)

FROM ubuntu:latest

CMD /bin/bash
$ docker run -it --name fuga fuga
root@7a8318a62284:/# ps la
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0     1     0  20   0   2380  1432 do_wai Ss   pts/0      0:00 /bin/sh -c /bin/bash
4     0     7     1  20   0   4296  3468 do_wai S    pts/0      0:00 /bin/bash

ENTRYPOINTは、このデフォルトだと/bin/sh -cになっている箇所をカスタマイズすることが可能です。
例えば、以下のようなスクリプトをENTRYPOINTに指定することによって、CMDの実行前に"hello world"を出力することができます。

entrypoint.sh
#!/bin/bash
echo "hello world"
"$@"
FROM ubuntu:latest
COPY /entrypoint.sh /bin/
RUN chmod +x /bin/entrypoint.sh

ENTRYPOINT ["/bin/entrypoint.sh"]
CMD [ "bash" ]
$ docker run -it --name fuga fuga
hello world
root@c8a263464b89:/# ls

CMDを実行する前に必要な処理をENTRYPOINTに指定することがほとんどだと思います。
Railsで自動生成されるdocker-entrypointを見ると、前処理として必要なdbのsetupなどが記載されていることがわかります。

shell形式とexec形式

CMDENTRYPOINTでは、shell形式とexec形式のどちらも指定することができます。

# shell形式
CMD echo "hello world!"
#exec形式
CMD [ "echo", "hello world!" ]

shell形式の場合は、その名の通りshellがCMDを解釈しそのコマンドを実行します。
なのでCMDに指定したコマンドはshellからforkされて実行されています。

FROM ubuntu:latest
CMD /bin/bash
root@4e6c0bdbb347:/# ps la
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0     1     0  20   0   2380  1432 do_wai Ss   pts/0      0:00 /bin/sh -c /bin/bash
4     0     7     1  20   0   4296  3548 do_wai S    pts/0      0:00 /bin/bash

exec形式の場合は、直接コマンドが実行されます。そのまま実行されるのでPIDは1になります。

FROM ubuntu:latest
CMD ["/bin/bash"]
root@eb20652c9389:/# ps la
F   UID   PID  PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0     1     0  20   0   4296  3544 do_wai Ss   pts/0      0:00 /bin/bash
4     0     9     1  20   0   7660  3468 -      R+   pts/0      0:00 ps la

Dockerfile以外のカスタムイメージの作り方

docker commit

カスタムイメージを作る際にはDockerfileを使うことが多いですが、docker commitを使うことによって、コンテナに対して変更を加え、そこからカスタムイメージを作成することも可能です。

例えばubuntu:latestをベースイメージとしてタグを切り、コンテナを立ち上げて変更分をイメージに反映させようとすると以下のようになります。

$ docker tag ubuntu:latest hoge
$ docker run -it --name hoge hoge

# コンテナに対して変更を加える
root@77ca2ef25a30:/# apt update -y && apt install -y vim
root@77ca2ef25a30:/# exit

# コンテナの変更分をイメージに反映させる
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                      PORTS     NAMES
77ca2ef25a30   hoge      "/bin/bash"   About a minute ago   Exited (0) 23 seconds ago             hoge
$ docker commit 77ca2ef25a30 hoge

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?