うさぎ好きエンジニアの備忘録

うさぎたちに日々癒されているエンジニアが業務で直面したもの & 個人的な学習メモを残していきます。

コマンドやデーモンを起動する命令を使う

第五弾(最終回にしたい)。

今回は「RUN」・「CMD」・「ENTRYPOINT」命令を使ってみた。

Dockerイメージを作成するためには、必要なミドルウェアのインストールや、ユーザやディレクトリの作成などを行う必要がある。

また、イメージからコンテナを起動したときにプロセスなどをデーモンとして動かす必要もある。

コマンドの実行

コマンドを実行する際は「RUN」命令を使用する。

RUN命令は、ベースイメージに対してアプリケーションやミドルウェアをインストールしたり、設定を追加したりするために、なんらかのコマンドを実行するときに使用する命令。

構文としては↓。

RUN [実行したいコマンド]

RUN命令の記述方法には以下の2通りがある。

Shell形式での記述

シェルでコマンドを実行する際と同じような記述をする方法。

例えばnginxをaptコマンドでインストールする際は以下のようなRUN命令を記述する。

RUN apt-get install -y nginx

上記のような記述を行うと、/bin/sh -c を使ってコマンドを実行した際と同じ動作をする。

Exec形式での記述

Shell形式で記述すると /bin/sh で実行されるが、Exec形式で記述するとシェルを介さず直接実行する。そのため、環境変数を指定することはできない。

Exec形式では、以下のように実行したいコマンドをJSON形式で記述する。

# /bin/bashでaptコマンドを実行し、nginxをインストールする
RUN ["/bin/bash", "-c", "apt-get install -y nginx"]

サンプルを使って実行してみる

以下のようなDockerfileを用意。

FROM ubuntu:latest

RUN echo shell形式での実行
RUN ["echo", "Exec形式での実行"]
RUN ["/bin/bash", "-c", "echo 'Exec形式でbashを使って実行'"]

このイメージをビルド。

$ docker build -t ponteru-sample .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM ubuntu:latest
 ---> d131e0fa2585
Step 2/4 : RUN echo shell形式での実行
 ---> Running in 7570a5963803

shell形式での実行
 ---> 04e881a36661
Removing intermediate container 7570a5963803
Step 3/4 : RUN echo Exec形式での実行
 ---> Running in 1d58a4316340

Exec形式での実行
 ---> 90e24a111228
Removing intermediate container 1d58a4316340
Step 4/4 : RUN /bin/bash -c echo 'Exec形式でbashを使って実行'
 ---> Running in 7f387174e8fa

Exec形式でbashを使って実行
 ---> c20c0003b901
Removing intermediate container 7f387174e8fa
Successfully built c20c0003b901

イメージを生成する際に実行されたコマンドを docker history で確認すると想定通りの挙動をしていることがわかる。

$ docker history ponteru-sample
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
c20c0003b901        7 minutes ago       /bin/bash -c echo 'Exec形式でbashを使って実行'           0 B
90e24a111228        7 minutes ago       echo Exec形式での実行                                 0 B
04e881a36661        7 minutes ago       /bin/sh -c echo shell形式での実行                     0 B

雑感

コマンドを実行する際にシェルを明示的に指定したいときはExec形式、/bin/sh でコマンドを実行したい場合にはShell形式で記述すればよさげ。

デーモンの実行 (CMD命令)

RUN命令は「イメージを作成するために実行する」コマンドを記述する。それに対して、イメージを元に作成したコンテナ内でコマンドを実行する場合には「CMD」命令を使用する。

Dockerfileには1つのみCMD命令を記述できる。もし複数記述した場合、最後のCMD命令のみが実行される。

また、CMD命令を使ってコマンドを実行することでコンテナ内でプロセスを常時動作させることができる。 構文としては↓。

CMD [実行したいコマンド]

RUN命令同様、記述方法には「Shell形式」と「Exec形式」の2通りがある。

Shell形式での記述

Nginxをフォアグラウンドで実行する際のコマンド例。

CMD nginx -g 'daemon off;'

Exec形式での記述

Shell形式の記述の時と同様に、Nginxをフォアグラウンドで実行する際のコマンド例。

CMD ["nginx", "-g", "daemon off;"]

デーモンの実行 (ENTRYPOINT命令)

ENTRYPOINT命令で指定したコマンドは docker container run コマンドを実行した際に実行される。

基本的にはCMD命令と同じ。

Shell形式での記述

Nginxをフォアグラウンドで実行する際のコマンド例。

ENTRYPOINT nginx -g 'daemon off;'

Exec形式での記述

Shell形式の記述の時と同様に、Nginxをフォアグラウンドで実行する際のコマンド例。

ENTRYPOINT ["nginx", "-g", "daemon off;"]

ENTRYPOINT命令とCMD命令の組み合わせ

以下のようにDockerfileを記述すると、ENTRYPOINT命令の引数としてCMD命令に記述した内容を使うことができる。

ENTRYPOINT ["top"]
CMD ["-d", "10"]

この場合、top -d 10 がコンテナ内で実行される。