コンテンツにスキップ

Dockerfile@Docker

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. セットアップ

インストール

▼ aptリポジトリから

Dockerエンジン、CLI、インストールする。

$ apt-get install -y \
    docker-ce \
    docker-ce-cli

dockerプロセスをデーモンとして起動する。

$ systemctl start docker


イメージのデバッグ

*例*

ビルドに失敗したコンテナイメージからコンテナを作成し、接続する。

rmオプションを設定し、接続の切断後にコンテナを削除する。

Dockerfileで、コンテナイメージのプロセスの起動コマンドをENTRYPOINTで設定している場合は、後から上書きできなくなる。

そのため、docker runコマンドの引数として新しいコマンドを渡せずに、デバッグできないことがある。

$ docker run --rm -it <ビルドに失敗したコンテナイメージID> /bin/bash

その他、プルしたコンテナイメージ内でちょっとしたコマンドを検証したいといった場合にも役立つ。

$ docker run --rm -it <検証したいコンテナイメージID> ls


02. ADD

ADDとは

ホスト側のファイルを、コンテナの指定ディレクトリ配下にコピーし、このファイルがtarファイルの場合は解凍する。

また、URLを直接的に指定して、ダウンロードから解凍までを実行もできる。


COPYとの違い

似た命令としてCOPY処理がある。

ADD処理はCOPY処理とは異なり、インターネットからファイルをダウンロードして解凍した上で、コピーする。

解凍によって意図しないファイルがDockerfileに組み込まれる可能性があるため、COPY処理が推奨である。

*実装例*

以下ではADD処理を使用している。

URLを直接的に指定し、ダウンロードから解答までを実行している。

ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all

これは、次のように書き換えるべきである。

RUN mkdir -p /usr/src/things \
  && curl -SL http://example.com/big.tar.xz | tar -xJC /usr/src/things \
  && make -C /usr/src/things all


03. ARG

ARGとは

Dockerfikeの命令で扱える変数を定義する。


ENVとの違い

似た命令としてENVがある。

ARGENVとは異なり、OS上のコマンド処理に展開するための変数として定義できない。

# ARGは、OS上のコマンド処理に展開するための変数として定義できない。
ARG PYTHON_VERSION="3.8.0"
# 変数を展開できない
RUN pyenv install ${PYTHON_VERSION}

# ENVは、OS上のコマンド処理に展開するための変数として定義できる。
ARG PYTHON_VERSION="3.8.0"
RUN pyenv install ${PYTHON_VERSION}

一方で、Dockerfikeの命令に展開するための変数として定義できる。

# ARGは、Dockerfikeの命令に展開するための変数として定義できる。
ARG OS_VERSION="8"
FROM centos:${OS_VERSION}

# ENVは、Dockerfikeの命令に展開するため変数として定義できない。
ENV OS_VERSION "8"
# 変数を展開できない
FROM centos:${OS_VERSION}

そのため、以下の様に使い分けることになる。

# 最初に全て、ARGで定義
ARG CENTOS_VERSION="8"
ARG PYTHON_VERSION="3.8.0"

# 変数展開できる
FROM centos:${CENTOS_VERSION}

# ARGを事前に宣言
ARG PYTHON_VERSION
# 必要に応じて、事前にENVに詰め替える。
ENV PYTHON_VERSION ${PYTHON_VERSION}

# 変数展開できる
RUN pyenv install ${PYTHON_VERSION}


スコープ

▼ FROMより前のARG

FROMより前で使用したARGSは、後続含めてFROMでしか使用できない。

ARG PYTHON_VERSION="3.8.0"
FROM python:${PYTHON_VERSION}

# 変数の値を使えない
RUN echo $PYTHON_VERSION

# 変数の値を使える
FROM python:${PYTHON_VERSION}

もしFROM内で使用する場合は、変数の再宣言が必要である。

値の格納は不要である。

ARG PYTHON_VERSION="3.8.0"
FROM python:${PYTHON_VERSION}

# 変数の再宣言
ARG PYTHON_VERSION

# 変数の値を使えない
RUN echo $PYTHON_VERSION

# 変数の値を使える
FROM python:${PYTHON_VERSION}


04. CMD

CMDとは

イメージのプロセスの起動コマンドを実行する。

パラメーターの記述形式には、文字列形式、json形式がある。


注意点

DockerfileでCMDを指定しない場合、コンテナイメージのデフォルトのバイナリファイルが割り当てられる。

一旦、デフォルトのバイナリファイルを確認した後に、これをDockerfileに明示的に実装する。

CONTAINER ID   IMAGE   COMMAND     CREATED          STATUS         PORTS                    NAMES
2b2d3dfafee8   *****   "/bin/sh"   11 seconds ago   Up 8 seconds   0.0.0.0:8000->8000/tcp   foo-image

静的型付け言語ではプロセスの起動時に、代わりにアーティファクトのバイナリファイルを実行しても良い。

その場合、binディレクトリにバイナリファイルとしてのアーティファクトを配置することになる。

しかし、binディレクトリへの認可スコープがないことがあるため、その場合は、1つ下にディレクトリを作成し、そこにバイナリファイルを配置するようにする。

# /go/bin にアクセスできない時は、/go/bin/cmdにアーティファクトを配置する。
ERROR: for xxx-container  Cannot start service go: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "/go/bin": permission denied: unknown


05. COPY

COPYとは

ホスト側 (第一引数) のディレクトリ/ファイルをコンテナ側 (第二引数) にコピーする。

COPY ./src src/

コンテナ側のパスは、WORKDIRをルートとした相対パスで定義できるが、絶対パスで指定した方がわかりやすい。

ディレクトリ内の複数ファイルを丸ごとコンテナ内にコピーする場合は、『/』で終える必要がある。

イメージのビルド時にコピーされるのみで、ビルド後のコードの変更は反映されない。

設定ファイル (例:nginx.confファイル、php.iniファイル) をホストからコンテナにコピーしたい時によく使用する。


--from

他のステージ名、ローカルのコンテナイメージ名、リモート (DockerHubのみ) のコンテナイメージ名、を指定して、そのコンテナイメージが持つファイルをコピーする。

COPY --from=composer:<バージョン> /usr/bin/composer /usr/bin/composer
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf


06. ENTRYPOINT

ENTRYPOINTとは

イメージのプロセスの起動コマンドを実行する。


CMDとの違い

似た命令としてCMDがある。

CMDとは異なり、後から上書き実行できない。

使用者に、コンテナの起動方法を強制させたい場合に適する。

イメージのプロセスの起動コマンドを後から上書きできなくなるため、docker runコマンドの引数として新しいコマンドを渡せずに、デバッグできないことがある。

# 上書きできず、失敗してしまう。
$ docker run --rm -it <コンテナイメージ名>:<バージョンタグ> /bin/bash


07. ENV

ENVとは

OS上のコマンド処理で展開できる変数を定義できる。


08. EXPOSE

EXPOSEとは

他のコンテナに対してコンテナポートを開放する。

また、コンテナイメージの利用者にとってのドキュメンテーション機能もあり、ポートマッピングを実行する時に使用できるコンテナポートとして保証する機能もある。

ホスト側からはアクセスできないことに注意する。


プロセスによるポート受信

コンテナのポートを開放するのみでは不十分である。

プロセス自体がリクエストを受信できるようにポートを設定する必要がある。

ただし、多くの場合デフォルトでこれが設定されている。

例えば、PHP-FPMでは、/usr/local/etc/www.conf.defaultファイルと/usr/local/etc/php-fpm.d/www.confファイルには、listenオプションの値に127.0.0.1:9000が割り当てられている。


09. FROM

FROMとは

ベースのコンテナイメージを、コンテナにインストールする。

FROM python:latest-slim


イメージレジストリの指定

指定できるイメージレジストリの例と記法は以下の通りである。

▼ DockerHub

PHP-FPMをインストールする場合は、php:8.0-fpmである。

▼ クラウドプロバイダー (パブリック)

パブリックなAWS ECR、Google Container Registry、Google Cloud Artifact Registry、RedHat Quay、からイメージをプルする。

ECRパブリックギャラリーからPHP-FPMをインストールする場合は、public.ecr.aws/bitnami/php-fpm:latestである。

▼ クラウドプロバイダー (プライベート)

プライベートなAWS ECR、Google Container Registry、Google Cloud Artifact Registry、RedHat Quay、からイメージをプルする。

ECRプライベートレジストリからPHP-FPMをインストールする場合は、<AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/private-foo-php-repository:latestである。


バージョンの指定

タグ

FROM python:latest


ダイジェスト値

ダイジェスト値 (イメージの識別子) を指定する/

FROM python@sha256:*****


レートリミット

▼ DockerHub

DockerHubのレートリミットは、匿名アカウントであれば100プル/6時間、無料アカウントであれば200プル/6時間、である。

CIパイプライン上でコンテナイメージをビルドしていると、これにひっかかりやすい。

クラウドプロバイダーのレートリミットの方が寛容なため、クラウドプロバイダー (パブリック/プライベート) からプルする方法もよい。

▼ crane

craneコマンドを使用すると、イメージレジストリ間のコンテナイメージの移動を簡素化できる。

# AWS ECRにログインする
$ crane auth login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com

# DockerHubからAWS ECRにコンテナイメージをコピーする例
$ crane copy nginx:<バージョン> *****.dkr.ecr.ap-northeast-1.amazonaws.com/nginx:<バージョン>

▼ krane

crane authコマンドを簡略化したコマンド


CPUアーキテクチャの指定

イメージの対応するCPUアーキテクチャ (例:Intel、AMD、ARM) を設定する。

ただし、DockerがホストのOSを認識して、自動的に選んでくれるため、ユーザーが設定する必要はない。

FROM --platform=linux/amd64 python:latest-slim


10. RUN

RUNとは

ベースイメージ上に、ソフトウェアをインストールする。


11. VOLUME

VOLUMEとは

ボリュームマウントを実行する。


12. WORKDIR

WORKDIRとは

ビルド中の各命令の作業ディレクトリを絶対パスで指定する。

また、コンテナ接続時の最初のディレクトリも定義できる。