docker
dockerfile

Dockerfileの書き方を深掘りしつつまとめてみた

はじめに

この記事は、現在Dockerについて学習している自分が、Dockerfileの書き方について、
ファイル内に記述されているコマンドの意味などをアウトプットを兼ねて解説した内容になります。

過去に投稿したDocker関連の記事はこちら

第1回Dockerハンズオン初心者・中級者編で学んだことをまとめてみた

https://qiita.com/yuta-ushijima/items/fdcaea4220e773a5ad2d

docker-compose.ymlの書き方について解説してみた

https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04

Dockerfileってなに?

Dockerを使ってアプリケーションを動かす際に、DockerImage(以下Image)の元となるファイルのこと。食べ物でいえば、原材料のようなものと思うとわかりやすいかもしれません。

Dockerfile内には、Imageを生成する際に実行させたいコマンドを、命令を実行するための環境変数の引数にして記述します。

Dockerfileサンプルコード

# 使用するrubyのバージョン
# rubyの2.4.1というImageをベースにDockerfileを作成する
FROM ruby:2.4.1

# このDockerfileのメタデータを記述
# MAINTAINERはdeprecateになった
LABEL maintainer="Yuta_Ushijima <contact@yuta-u.com>"|

# 文字コードの設定
# 日本語を受け付けるように設定(rails consoleで日本語を使うなど) => LANG=C.UTF-8
# 設定したロケールの値をC.UTF-8で上書きする => LC_ALL=C.UTF-8
# 文字コードのカテゴリをutf-8に設定 => LC_CTYPE="utf-8"
ENV LANG=C.UTF-8 \
    LC_ALL=C.UTF-8 \
    LC_CTYPE="utf-8"

# 使用するエディタ
ENV EDITOR vim 

# インストールするライブラリなどをshell形式で記述。\(バックスラッシュ)を使って、一つのRUNで複数のコマンドを実行できる。
RUN apt-get update --fix-missing \
  && apt-get -y upgrade \
  && apt-get install -qq -y \
    apt-utils \
    build-essential \
    ca-certificates \
    curl \
    git \
    glances \
    graphviz \
    htop \
    libcurl3 \
    libpq-dev \
    man \
    mysql-client \
    nano \
    nodejs \
    patch \
    software-properties-common \
    sudo \
    unzip \
    vim \
    wget \
    xvfb \
    zlib1g \
    zlib1g-dev \
  && apt-get autoremove -y \ => 不要なパッケージの自動削除。-yで確認ダイアログの非表示。
  && apt-get clean \ => パッケージキャッシュの削除
  && fc-cache -f -v => 利用可能なフォントのキャッシュを更新。

# bundle installをスムーズに実行させるため、予め重めのgemをここでinstallしていおく
RUN gem update --system
RUN gem install -q --no-rdoc --no-ri pkg-config --version 1.3.1
RUN gem install -q --no-rdoc --no-ri rails --version 5.2.1
RUN gem install -q --no-rdoc --no-ri nokogiri --version 1.8.4
RUN gem install -q --no-rdoc --no-ri mysql2 --version 0.5.2

# GemfiletとGemfile.lockをルートディレクトリにコピー
COPY Gemfile Gemfile.lock ./
# Gemfile.lockが通常のファイルであれば、bundle installを実行
RUN if test -f Gemfile.lock; then \
    bundle install --binstubs --jobs=4 --retry=3; \
  fi
# コピー元のGemfileとGemfile.lockを削除
RUN rm Gemfile Gemfile.lock

# ディレクトリの作成
RUN mkdir -p /memo-app/backend

# 実行するディレクトリの指定
WORKDIR /memo-app/backend

# 現在のディレクトリ(ここでは/memo-app/backend)の新規ファイルやディレクトリをルートディレクトリに追加
ADD . .

    # RAILS_SERVE_STATIC_FILES=trueにすることで、rails serverを起動時にpublic/assetsを読み込む
ENV RAILS_SERVE_STATIC_FILES=true \
    PORT=3000 \
    # コンテナにxtermというターミナルエミュレータを割り当てる
    TERM=xterm

ENV PORT=3000 \
    # RACK_ENV=development \
    # RAILS_ENV=development \
    RAILS_SERVE_STATIC_FILES=true \
    TERM=xterm

EXPOSE 3000
EXPOSE 3310

Dockerfileで記述する環境変数について

環境変数の種類自体は、そこまで数が多くないので、それぞれを表にしてまとめてみます。

項目 意味 リファレンスリンク
FROM ビルドする際にどのImageをベースにするか http://docs.docker.jp/v1.10/engine/reference/builder.html
LABEL Dockerfileのメタデータを記述 https://docs.docker.com/engine/reference/builder/#label
ENV 環境変数のkeyとvalueを設定 https://docs.docker.com/engine/reference/builder/#env
RUN 引数に設定したコマンドをビルド時に実行。引数の書き方がshell形式とexec形式がある。 https://docs.docker.com/engine/reference/builder/#run
COPY プロジェクトソースにあるファイルやディレクトリを指定先にコピーする http://docs.docker.jp/v1.10/engine/reference/builder.html#copy
WORKDIR RUNやCMDなどの命令を実行するディレクトリを指定 http://docs.docker.jp/v1.10/engine/reference/builder.html#workdir
ADD 新しく追加されたファイルやディレクトリを指定先に追加 http://docs.docker.jp/v1.10/engine/reference/builder.html#add
EXPOSE コンテナ実行時に指定したポートで接続用意ができていることをDockerに伝える https://docs.docker.com/engine/reference/builder/#expose

RUNにおけるapt-getコマンドについて

Dockerfileのベストプラクティスの要点をまとめると、

  • apt-getupdateinstallは同一のRUNで実行すること
# -yで確認ダイアログを出さずにinstallを実行する
apt-get update && apt-get install -y \
  • RUNの最終行でapt-get cleanしてキャッシュを削除すること (apt-get clean allじゃなくてもapt-get cleanだけでOK。apt-get cleanのあとにどんな引数を書いても無視されるため)
RUN apt-get update && apt-get install -y \
    aufs-tools \
    automake \
    build-essential \
    curl \
    dpkg-sig \
    libcap-dev \
    libsqlite3-dev \
    lxc=1.0* \
    mercurial \
    reprepro \
    ruby1.9.1 \
    ruby1.9.1-dev \
    s3cmd=1.1.* \
 && apt-get clean \
  • 更新しやすくするために、installするライブラリはABCの降順で記述すること

参考サイト

Cロケールについて

https://docs.oracle.com/cd/E26924_01/html/E27144/glmbx.html

https://wiki.archlinux.jp/index.php/%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB

Dockerfileのベストプラクティス

http://docs.docker.jp/engine/articles/dockerfile_best-practice.html

apt-getコマンドについて

https://qiita.com/white_aspara25/items/723ae4ebf0bfefe2115c

apt-get clean allについて

https://askubuntu.com/questions/144222/how-do-apt-get-clean-and-apt-get-clean-all-differ

fc-cache -fvについて

https://qiita.com/nju33/items/b80d92a4257edeb4b9a1

シェルスクリプトのif文について

https://shellscript.sunone.me/if_and_test.html

xtermについて

http://docs.docker.jp/v1.12/engine/reference/run.html#id67