SEワンタンの独学備忘録

IT関連の独学した内容や資格試験に対する取り組みの備忘録

【Docker】入門⑦ Dockerfileでのコマンド/デーモン実行方法

前回の続きでDockerfileについて。

Dockerfileでのコマンド実行(RUN命令)

ベースイメージから実際に活用できるDockerイメージを生成するためには、イメージをプルするだけでは使い物にならないので各種インストールや設定を行う必要があります。

そのためにはコンテナに対してコマンドを実行していきます。

Shell形式での実行

前回の記事でも扱いましたが、コマンドの実行は「RUN」命令で実行します。
RUN」の後ろはShell形式で記述ができます。

# centOSに対するnginxのインストール
RUN yum install -y nginx

自動で実行するので、y OR n の選択でyを選択するために「-y」オプションを付ける必要があります。

Exec形式での実行

Shell形式での実行は「/bin/sh」で実行されますが、Exec形式で実行するとシェルを経由せずに直接実行します。
Exec形式というのは私はあまり馴染みがないですが以下のような形式で記述を行います。

# centOSに対するnginxのインストール
RUN ["/bin/bash","-c","yum install -y nginx"]

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

デーモンなので、Linuxの常駐プログラムの実行になります。
末尾に「d」のつくhttpdなどがデーモンの一種ですね。

イメージの生成はRUN命令を用いますが、コンテナ内でコマンドを実行するにはCMD命令を用います。
CMD命令にもいくつかの記述形式が存在します。

CMD命令はDockerfile内で一度しか実行できないようで、複数記述した場合は最後に記述した内容が実行されるようです。

Shell形式での実行

CentOSイメージをビルドし、コンテナ内でnginxをデーモン実行する際に以下のように実行します。

# nginxデーモン実行
CMD nginx -g 'daemon off;'
Exec形式での実行

RUN命令と同様の形式で記述します。

# nginxデーモン実行
CMD ["nginx", "-g", "daemon off;"]

ENTRYPOINT命令

ENTRYPOINT命令で実行したコマンドはコンテナが起動した際に実行されます。

CMD命令で実行した場合との違いは、CMD命令はコンテナの起動時(run)に引数で新たなコマンドを指定した場合、コマンドの上書きが行われます。

対してENTRYPOINT命令ではコンテナで確実に実行されるため、起動時のコマンドを時々によって使い分ける必要がある場合にはCMD命令で実行する必要があります。

また、ENTRYPOINT命令で指定したコマンドに対してCMD命令でオプションを指定することも可能なので、コマンドのオプションを可変にする場合は使い分ける必要があります。

Shell形式での実行
# nginxのShell実行
ENTRYPOINT nginx -g 'daemon off;'
Exec形式での実行
# nginxのExec実行
ENTRYPOINT ["nginx", "-g", "daemon off;"]

ONBUILD命令

ONBUILD命令はビルド時に実行するコマンドをイメージ内に設定する命令です。

経験がないといまいち言ってることが分からないかもしれません。

f:id:wantanBlog:20200301021324p:plain

ベースイメージを生成するためのDockerfile1にONBUILD命令を記述すると
Dockerfile2でオリジナルイメージをビルドする際にコマンドを指定できます。

・例

ONBUILD ADD index.html /var/www/html

webサーバの構築検証

f:id:wantanBlog:20200302215637p:plain

命令の検証

上記の内容だけでは命令イメージがしにくいのでwebサーバの構築を通して検証を行います。

・Dockerfileの内容

# ベースイメージの取得
FROM centos

# nginxのインストール
RUN yum -y install nginx

# ビルド後のINDEXファイルの配置
ONBUILD ADD index.html /usr/share/nginx/html

# デーモン実行
ENTRYPOINT ["nginx", "-g", "daemon off;"]

・Dockerfileの実行

docker build -t testos:1.0 /home/ec2-user/docker_work

・Dockerコンテナの生成

docker container run -it --name webserver -p 80:80 testos:1.0

・ブラウザで疎通確認
f:id:wantanBlog:20200301223332p:plain

nginxがコンテナを起動した時点で起動していることが確認できます。
※ENTRYPOINT命令

また、ここではindexファイルは置き換わっていないことが確認できます。
※ONBUILD命令

ベースイメージを元にしてオリジナルイメージを生成します。

・Dockerfile2の内容

# ベースイメージの取得
FROM testos:1.0

・Dockerfile2の実行

docker build -t webserver:1.0 -f deployfile .

・Dockerコンテナ2の生成

docker container run -it --name webserver2 -p 8080:80 webserver:1.0

・ブラウザで疎通確認(ポート:8080)
f:id:wantanBlog:20200301232827p:plain

新たに生成したサーバではindexファイルが置き換わっていることが確認できます。

一人で構築している場合には恩恵がほぼない(最初のDockerfileの時点でindexファイルを配置すればいいから)ですが、インフラ構築とアプリ構築がチームで分かれていて、複数人でアプリ開発を行っている場合などには、各自の環境でここでいうDockerfile2を実行することでそれぞれの環境に同一のインフラ環境を構築して、アプリはそれぞれのものをデプロイするなどの運用が可能になります。