Server Build Exercises on AWS (Amazon Web Services) 2022 edition

Dockerfile

04_docker/04-03_web.py/docker/Dockerfileを解説します。 行番号をふりますが、実際のファイルには左端の5バイト分(数字4桁+スペース)がありません。

行番号をふった Dockerfile 全体はこちら

コンテナのカスタマイズをしたいなら、一番重要な情報は次の2点でしょう。 よくわからないなら、 他のところはいじらないほうがよいです(いじらなくても多分なんとかなります)

  • 新たに(OSの)パッケージを追加したいのなら0031行目PKG_MODEL_SPECIFICに追加
  • Python ライブラリを追加したいなら0050行目に追加

Dockerfile の基礎

FROM debian

CMD echo "Helo, World!"

という短い Dockerfile を build すれば hello world コンテナになります。 hello world はともかく、 このように Dockerfile の先頭には、元にする OS イメージの指定が来ます。 それがFROM行で、使いたい OS イメージ名を書きます。 必要なら debian:10.10 のようにバージョン番号指定も可能です

変数による上書き

この構築ガイドで使う汎用Dockerfileでは多くの変数を外部から設定可能にしています。

build.shで解説したとおり build.sh のオプション(–build-arg)で多くの変数の値を上書きしています。 指定している変数はIMAGE SANDBOX_UID SANDBOX_USER SANDBOX_PASSWORD SANDBOX_HOME LANG LANGUAGE TIMEZONEです

変数は Dockerfile 全体に散らばっていますが、まずは0001-0016行が最初の設定部分になります。

0001-0002 行では利用する OS イメージを指定します。

0001 ARG    IMAGE
0002 FROM ${IMAGE}

コマンドラインで –build-arg IMAGE=debian:10.11 オプションをつけているので、 これらの行は

FROM debian:10.11

の意味に解釈されます。 ちなみに –build-arg で使う変数は、 Dockerfile の中でARG 変数名という形で宣言されている必要があります。 そのため、0002行目の FROM 以前に 0001 行目の ARG IMAGE 宣言が必要です

0004-0013 では同じくコマンドラインオプションで指定する変数 LANG LANGUAGE TIMEZONE の値を上書きしています。 これらは –build-arg オプションの使用例として入れてありますが、 この構築においては、そんなに重要ではありません。 でも、変な警告とか出たりするのもイヤなので、 言語やタイムゾーンは適切に設定しておきましょう

0004 # fundamental: language, timezone
0005 ARG        LANG
0006 ARG    LANGUAGE
0007 ARG    TIMEZONE
0008 ENV        LANG=${LANG}
0009 ENV    LC_CTYPE=${LANG}
0010 ENV LC_MESSAGES=${LANG}
0011 ENV      LC_ALL=
0012 ENV    LANGUAGE=${LANGUAGE}
0013 ENV          TZ=${TIMEZONE}

0015-0016 行目はオマケです、このガイドでは利用していない設定です(が、消し忘れていた:-) 無視してください

0019-0039 行目で必要なソフトウエアをインストールしています。以下、コメントは適当に省略していきます。

0019 ENV DEBIAN_FRONTEND noninteractive

0019 行は、パッケージ管理ソフトが[y/n]と聞いてこなくてよいとパッケージ管理システムに伝える設定です

0029 ARG           PKG_BASE="locales tzdata sudo procps"
0030 ARG       PKG_UTILTIES
0031 ARG PKG_MODEL_SPECIFIC="systemd coreutils python3 python3-pip telnet curl"

ここ(0029-0031行)で PKG_BASE PKG_UTILITIES PKG_MODEL_SPECIFIC という変数を定義し、 インストールしたいパッケージ群をカテゴリごとに定義しています。 変数は${変数}と書けば展開されます(下を参照)。

コンテナにパッケージを追加したいのなら、 PKG_MODEL_SPECIFIC を編集して curl の右側に入れたいパッケージ名を追加していけばよいでしょう

0033-0039 は長い一行のコマンドを\で複数行に書いています。 なお、パッケージを追加するだけなら 0033-0039 行目を改変する必要はありません (上に書いたようにPKG_MODEL_SPECIFIC変数に追加するだけでよい)。

0033 RUN apt-get update &&				   \
0034     apt-get install -y	${PKG_BASE}		   \
0035 			${PKG_MODEL_SPECIFIC}		   \
0036 			${PKG_UTILTIES}			&& \
0037 			apt-get -y autoremove		&& \
0038 			apt-get clean			&& \
0039 			rm -rf /var/lib/apt/lists/*

意味は… とりあえず最低限の解説はしておきましょう

  • RUN 「文字列」は「文字列」部分を実行せよと docker build に伝える命令文です
    • 「文字列」の部分はシェルの構文です
    • コマンドA && コマンドBは「コマンドAが成功すればコマンドBを実行する」という意味です
    • 折り返しをといて、 一行にすればRUN コマンドA && コマンドB && コマンドC && コマンドD && コマンドEなので、 5つすべてが成功するなら、コマンドA〜コマンドEまでが順番に実行されていきます
  • aptなんとかはdebianのパッケージ管理システムのコマンド
  • 変数は${変数}と書くと展開されるので、0034-0036行は apt-get install -y locales tzdata sudo ... curl のように解釈されます

ようするに、 シェルプログラミングの基礎つまり Unix のコマンドライン操作がわからないと理解できません。 Unix操作法がわからないと、クラウドもどうにもならないことが噛みしめられましたね? :-)

後半戦ではコンテナのカスタマイズ

おそらく 0041-0047に手を入れる必要はありません。変更する必要があるとすれば 0050 行以降です

0041 RUN sed -i "/${LANG}/s/^# //" /etc/locale.gen && locale-gen && update-locale LANG=${LANG}

0041行は念のためコマンドでロケール(言語設定)を再設定しています。 なんかaptにまかせておくとうまくいかないことがあるためです

0043-0046は変数SANDBOX_ほげほげの宣言と初期値の設定をしています。 docker build のコマンドラインオプションで上書きされない場合、この初期値が使われます

0043 ARG        SANDBOX_UID=1000
0044 ARG       SANDBOX_USER=docker
0045 ARG   SANDBOX_PASSWORD=docker
0046 ARG       SANDBOX_HOME=/home/$SANDBOX_USER}

0047 行もシェル構文の実行です。ここではコンテナのデフォルトユーザ${SANDBOX_USER}を作成しています

0047 RUN [ $SANDBOX_UID -ne 0 ] && { useradd -m --uid ${SANDBOX_UID} --groups sudo,video --shell /bin/bash ${SANDBOX_USER} && echo ${SANDBOX_USER}:${SANDBOX_PASSWORD} | chpasswd; } || true

0050 行もシェル構文の実行です。 pip3 (Python 3自身のパッケージ管理システムのコマンド)で、 www.py が必要としている mysql ライブラリ(mysql-connector-python)をインストールします。

0050 RUN /usr/bin/pip3 install mysql-connector-python

必要な Python ライブラリがあれば、ここに追加してください

0056-0058 は、

  • 0056: コンテナ内に /sandbox ディレクトリを作成し、
  • 0057: docker build を実行しているディレクトリにある ./files ディレクトリをコンテナ内の /sandbox へコピーします
0056 RUN     mkdir /sandbox
0057 COPY    files /sandbox
0058 RUN     find  /sandbox -type d -name CVS | xargs rm -fr || true

0058 はゴミを消して(クリーニングして)いるだけです

最後です。 コンテナ実行環境をデフォルトユーザへ切り替えます。

  • 0060: ディレクトリを${SANDBOX_HOME}へ変更
  • 0061: ねんのため${SANDBOX_HOME}のpermission(権限)を${SANDBOX_USER}へ設定
  • 0062: コンテナで処理を実行するデフォルトユーザを${SANDBOX_USER}へ設定
0060 WORKDIR          ${SANDBOX_HOME}
0061 RUN     chown -R ${SANDBOX_USER}    ./
0062 USER             ${SANDBOX_USER}

最後の最後に実行するものをENTRYPOINTと呼んでいます。

0064 ENTRYPOINT ["/sandbox/entrypoint.sh"]

コンテナの起動時、 コンテナ内の/sandbox/entrypoint.shというスクリプトを実行するとコンテナをしつけています。 なお、entrypoint.shは終わらない処理である必要があります

Last updated on 12 Dec 2021
Published on 12 Dec 2021
Copyright (C) 2021-2022 Ken'ichi Fukamachi, All rights reserved. CC BY-NC-SA 4.0
We appreciate AWS Academy Japan for the offer of the learning environment.

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.