Docker

【Docker】Docker file

環境・事前準備

macOS Big Sur
・Docker Desktopのインストール
Homebrew:brew install --cask docker

Docker imageは、Docker Hub等のレジストリからダウンロードする他、「Dockerfile」から独自に作成(ビルド)することもできます。

Dockerはクライアント・サーバーモデルを採用しており、クライアントであるDocker CLI」からコマンドを入力することで、サーバーである「Docker Host」に指示を出し、Docker imageのビルドやコンテナの管理を行っています。

Docker CLIからビルドの指示を出すことで、作成したDockerfile(ファイル名も「Dockerfile」とします。)及びその他のファイル(以下の図の場合、「other file」)はディレクトリ(「build context」)ごとDocker Hostに送られ、Docker imageが生成されます。

Dockerfileの作成

Dockerfileは、Docker imageの設計図であり、その実態はテキストファイルです。「INSTRUCTION arguments」の形で記述していくことで、Docker imageの仕様を定義することができます。

INSTRUCTION arguments 内容
FROM <image> ベースとなるイメージ(基本的にOS)を指定。
RUN <command> Linuxコマンドを実行。
CMD ["executable", "param1", "param2", ...] デフォルトコマンド(executable。コンテナ起動時に実行するコマンド。)を指定。最後に1回だけ記述。
ENTRYPOINT ["executable"] デフォルトコマンド(executable)を指定。run時にコマンド上書きができない。「CMD」は「ENTRYPOINT」の引数のみ指定する。(CMD ["param1", "param2", ...]※CMDで指定した引数は上書き可能。)
COPY <source_file> <destination_directory> build context内のファイル<source_file>(ディレクトリも可)をimageに組み込み、コンテナ内のディレクトリ<destination_directory>で受け取る。
ADD <source_file> <destination_directory> <source_file>にtar形式の圧縮ファイルを指定する場合、「COPY」の代わりに使用する。コンテナ生成時には自動的に解凍もする。
ENV <key> <value> or ENV <key>=<value> ... 環境変数(OS上のプロセスが共有する変数)を設定する。
WORKDIR <directory> instructionの実行ディレクトリを変更する。<directory>は絶対パスで指定する(存在しなければ自動的に作成もする)。
※「WORKDIR」で変更しない場合、instruction毎にrootディレクトリで実行される。

Image layer

Docker imageは「Image layer」で構成されています。既存のimageのレイヤーを使い回ししつつ、コンテナの生成やDocker imageの変更等、追加の情報は新しいlayerを積み上げることで保存されます。

Docker imageでは、容量の大きな内容を扱うことも多いため、容量の縮減やビルド時間の短縮が課題となってきます。

  • 容量の縮減:Layer数を最小にする工夫をします。Dockerfileにおいて「RUN」、「COPY」、「ADD」は新しいlayerを作ります。「&&」(コマンドを繋げる)を使用することで、(RUN等の使用回数を減らし)容量を削減することができます。
  • ビルド時間の短縮:キャッシュを活用します。一度ビルドした内容はキャッシュとして保存され、変更したlayerのみビルドされる仕組みとなっています。検証時は敢えて「RUN」を分けてキャッシュを使うことで、ビルドの時間を短縮し、検証後に「&&」でコマンドを繋げたり、複数の引数をまとめる(見やすくするため「\」で改行したりします。)等の修正を加えます。

「Dockerfile」のコード例(Jupyer Labの実行環境構築)を以下に示します。

# ベースとなるOSに「ubuntu」を指定。
FROM ubuntu:latest
# apt-get:ubuntuで使用するパッケージ管理コマンド。
# apt-get update:新しいパッケージリストを取得。
# apt-get install <package>:<package>をインストール。「-y」オプションで質問に対して「yes」と回答するように設定できる。
# sudo:root以外のユーザーがroot権限でコマンドを実行できるパッケージ。
# wget:Webサーバーからファイルをダウンロードするパッケージ。
# vim:エディタ。
RUN apt-get update && apt-get install -y \
    sudo \
    wget \
    vim
WORKDIR /opt
# Anacondaのインストーラーをダウンロードしてインストールする。インストール後、インストーラーは削除する。
# インストーラーのオプションは「sh -x <installer>」で確認できる。
# 「-b」オプション:バッチモードでインストール。
# 「-p」オプション:インストール先を指定。
RUN wget https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh && \
    sh Anaconda3-2023.03-1-Linux-x86_64.sh -b -p /opt/anaconda3 && \
    rm -f /opt/Anaconda3-2023.03-1-Linux-x86_64.sh
# パスを通す。
ENV PATH /opt/anaconda3/bin:$PATH
RUN pip install --upgrade pip
WORKDIR /
# 「jupyter lab」コマンドでJupyter Labを実行。
# --ip=0.0.0.0:localhostで実行。
# --allow-root:rootでの実行を許可。Jupyter Labはデフォルトでrootでのアクセスを禁止している。
# --LabApp.token='':Jupyter Lab起動時に入力が必要となるトークンを何も指定しない(空文字とする)。
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--allow-root", "--LabApp.token=''"]

 

Dockerfileが保存されているフォルダ(build context)をカレントディレクトリに指定し、以下のコマンドでビルドします。

% docker build .

 

コンテナを起動する際は、Docker HostとJupyter Labのポートを繋ぐ(publish)必要があります。Jupyter Labのポートは「8888」がデフォルトで設定されています。以下は、Docker Hostのポートも「8888」としてJupyter Labのポートにpublishした上で起動するコマンドです。

% docker run -p 8888:8888 <image>

 

ブラウザで「localhost:8888」にアクセスすればJupyter Labが起動します。