24 Dockerfileと指示のベストプラクティス

24 Dockerfileと指示のベストプラクティス

キャッシュを構築する

イメージ構築プロセス中、Docker は Dockerfile で指定された順序で各命令を実行します。 Dockerfile 内の各命令により、新しいイメージがコミットされます。次の命令は、前の命令のミラーイメージに基づいて構築されます。

各命令を実行する前に、Docker はキャッシュを検索して、再利用可能なイメージがすでに存在するかどうかを確認します。その場合、再度イメージを作成するのではなく、既存のイメージを使用します。

したがって、キャッシュを効果的に使用するには、Dockerfile の一貫性を保ち、最後に変更するようにしてください。

 FROM ubuntu MAINTAINER author <[email protected]> RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" RUN apt-get update RUN apt-get upgrade -y

MAINTAINER 命令を変更すると、Docker はキャッシュを使用する代わりに、実行命令を実行して apt を更新するようになります。

キャッシュを使用しない場合は、docker build を実行するときにパラメータ --no-cache=true を追加します。

Docker では、キャッシュを構築するための基本的なルールは次のとおりです。

  1. キャッシュ内のベース イメージ (FROM 命令で指定) から開始して、次の命令はベース イメージのすべてのサブイメージを照合し、これらのサブイメージの作成時に使用された命令がチェック対象の命令とまったく同じかどうかを確認します。そうでない場合、キャッシュは無効になります。
  2. ほとんどの場合、サブイメージの 1 つを使用して Dockerfile 内の命令を比較するだけで十分です。ただし、特定の指示にはより多くの判断が必要です。
  3. ADD および COPY 命令の場合、イメージ内の対応するファイルの内容もチェックされ、各ファイルのチェックサム (通常はファイルのチェックサム) が計算されます。キャッシュ検索プロセス中に、これらのチェックサムはイメージ内にすでに存在するファイル チェックサムと比較されます。ファイルが何らかの形で変更されると、キャッシュは無効になります。
  4. ADD および COPY 命令を除き、キャッシュ一致チェックでは一時コンテナー内のファイルはチェックされません。たとえば、RUN apt-get -y update コマンドを使用してコンテナ内のファイルを更新する場合、そのコマンドはキャッシュ チェック ポリシーによるキャッシュ マッチングの基準として使用されません。
  5. キャッシュが無効になると、後続のすべての Dockerfile 命令によって新しいイメージが生成され、キャッシュは使用されなくなります。

マルチステージビルドの使用

マルチステージビルドでは、中間レイヤーやファイルの数を減らすことなく、最終イメージのサイズを大幅に削減できます。イメージはビルド プロセスの最後の段階で生成されるため、ビルド キャッシュを活用してイメージ レイヤーを最小限に抑えることができます。

たとえば、ビルドに複数のレイヤーが含まれている場合は、変更頻度の低いレイヤー (ビルド キャッシュが再利用可能であることを保証するため) から変更頻度の高いレイヤーの順に並べ替えることができます。

  • アプリケーションの構築に必要な依存関係をインストールする
  • 依存関係をインストールまたは更新する
  • アプリを構築する

たとえば、Go アプリケーションを構築するための Dockerfile は次のようになります。

 FROM golang:1.11-alpine AS build # 安装项目需要的工具# 运行`docker build --no-cache .` 来更新依赖RUN apk add --no-cache git RUN go get github.com/golang/dep/cmd/dep # 通过Gopkg.toml 和Gopkg.lock 获取项目的依赖# 仅在更新Gopkg 文件时才重新构建这些层COPY Gopkg.lock Gopkg.toml /go/src/project/ WORKDIR /go/src/project/ # 安装依赖库RUN dep ensure -vendor-only # 拷贝整个项目进行构建# 当项目下面有文件变化的时候该层才会重新构建COPY . /go/src/project/ RUN go build -o /bin/project # 将打包后的二进制文件拷贝到scratch 镜像下面,将镜像大小降到最低FROM scratch COPY --from=build /bin/project /bin/project ENTRYPOINT ["/bin/project"] CMD ["--help"]

タグを使用する

Docker を試していない限り、ビルドされたイメージにタグを付けるには、常に -t オプションを指定して docker build を実行する必要があります。人間が読めるシンプルなタグは、作成された各イメージを管理するのに役立ちます。

 docker build -t="tuxknight/luckypython"

常に -t フラグを使用してイメージをビルドします。

パブリックポート

Docker の中心的な概念は再現性と移植性です。イメージはどのホストでも実行でき、何度でも実行できる必要があります。 Dockerfile ではプライベート ポートとパブリック ポートの両方をマップできますが、Dockerfile を通じてパブリック ポートをマップすることはできません。このように、複数のイメージを実行すると、ポートの競合が発生する可能性があります。

 EXPOSE 80:8080 # 80映射到host的8080,不提倡这种用法EXPOSE 80 # 80会被docker随机映射一个端口

EXPOSE 命令は、コンテナがリッスンするポートを宣言するために使用されます。 EXPOSE 命令では、ポート番号の形式は <コンテナ ポート>/<プロトコル> です。コンテナ ポートは、コンテナ内でアプリケーションがリッスンするポートを指し、プロトコルはオプションで、デフォルトは TCP です。

この例では、EXPOSE 80:8080 は、コンテナがコンテナ ポート 80 をリッスンし、ホストがポート 8080 を使用してコンテナのポート 80 にアクセスできることを意味します。つまり、コンテナのポート 80 はホストのポート 8080 にマッピングされます。

EXPOSE 命令は、コンテナがリッスンするポートを宣言するだけで、ポート マッピングを自動的に実行しないことに注意してください。実際にポート マッピングを行うには、コンテナーを実行するときに -p または -P オプションを使用する必要があります。

CMD ENTRYPOINT 構文

CMD と ENTRYPOINT は次の 2 つの構文をサポートします。

 CMD /bin/echo CMD ["/bin/echo"]

最初の方法では、Docker はコマンドの前に /bin/sh -c を追加するため、予期しない問題が発生する可能性があります。 2 番目の方法では、CMD ENTRYPOINT は配列であり、実行されるコマンドは期待どおりになります。

コンテナは一時的なものである

コンテナ モデルはマシンではなくプロセスであり、起動時の初期化は必要ありません。必要なときに実行し、不要なときは停止し、削除して再構築することができ、構成と起動は最小限です。

.dockerignore ファイル

docker を使用してビルドする場合は、.dockerignore を使用して、ビルド用に送信する必要のない一部のファイルを無視します。未使用のファイルやディレクトリを無視すると、ビルドの速度が向上する場合があります。

ビルドのバージョンをアップグレードしない

コンテナ内で更新しないでください。更新はベースイメージによって処理されます。

アプリケーションの分離

各コンテナは 1 つのプロセスのみを実行し、各コンテナ アプリケーションは 1 つの側面のみを考慮します。複数のアプリケーションを異なるコンテナに分離することで、コンテナはアプリケーションとデータを分離し、コンテナの水平拡張と再利用を容易に実現できるようになります。

たとえば、Web アプリケーションには、Web アプリケーション、データベース、キャッシュという 3 つの独立したコンテナーが含まれる場合があります。各コンテナは独立したイメージであり、個別に実行されます。ただし、これはコンテナーが 1 つのプロセスしか実行できないことを意味するわけではありません。一部のプログラムは独自に他のプロセスを生成する場合があるためです。たとえば、Celery には多くの作業プロセスが存在する可能性があります。

コンテナごとに 1 つのプロセスを用意するのが良いルールですが、これは厳格なルールではありません。主なアイデアは、コンテナを 1 つのことに集中させ、できるだけクリーンかつモジュール化された状態に保つことです。コンテナが相互に依存している場合は、Docker コンテナ ネットワークを使用してこれらのコンテナを接続できます。

画像レイヤーの数を最小限に抑える

初期のバージョンでは、画像レイヤーの数を最小限に抑えることが非常に重要でしたが、現在のバージョンではある程度改善されています。

  • RUN、COPY、ADD 命令のみがレイヤーを作成します。その他の命令は一時的な中間イメージを作成しますが、構築されたイメージのサイズを直接増加させることはありません。
  • マルチステージ ビルドのサポートにより、必要なデータを最終イメージに直接コピーできるため、最終イメージのサイズを増やすことなく、中間段階でいくつかのツールやデバッグ情報を含めることができます。

Dockerfile の読みやすさとファイル システム レイヤーの数のバランスを取る必要があります。ファイルシステムレイヤーの数を制御すると、Dockerfile の読みやすさが低下します。 Dockerfile が読みやすくなると、多くの場合、ファイル システム レイヤーが増えます。

不要なパッケージのインストールを避ける

複雑さ、依存関係、ファイル サイズ、ビルド時間を削減するには、追加パッケージや不要なパッケージのインストールを避ける必要があります。たとえば、データベース イメージにテキスト エディターを含めないでください。

特定のタグを使用する

Dockerfile 内の FROM には、依存するベース イメージの完全なリポジトリ名とタグが常に含まれている必要があります (たとえば、FROM debian ではなく FROM debian:jessie を使用する)。

複数行パラメータのソート

可能な場合は、複数行の引数はアルファベット順にソートされます。これにより、同じパッケージが 2 回含められることがなくなり、パッケージ リストの更新が容易になり、読み取りとレビューが容易になります。読みやすさを向上させるために、バックスラッシュ文字 \ の前にスペースを追加することをお勧めします。

 RUN apt-get update && apt-get install -y \ bzr \ cvs \ git \ mercurial \ subversion

Dockerfile 命令のベストプラクティス

これらの手順の使用に関する推奨事項は、効率的で保守可能な Dockerfile を作成するのに役立ちます。以下は、Dockerfile の指示セクションのベスト プラクティスです。

から

可能な限り、現在の公式イメージをベースイメージとして使用してください。サイズが約 100 MB に抑えられ、完全なディストリビューションである Debian イメージを使用することをお勧めします。

あるいは、Alpine イメージの使用を検討することもできます。これは、厳密に制御されており、サイズが小さい (現在 5 MB 未満) にもかかわらず、完全な Linux ディストリビューションであるためです。

LABELタグ

イメージにタグを追加して、イメージの整理、ライセンス情報の記録、自動ビルドの支援などに役立てることができます。各ラベルは 1 行で記述され、LABEL で始まり、その後に 1 つ以上のラベル ペアが続きます。

次の例は、さまざまな可能な形式を示しています。 # で始まる行はコメントです。

 # Set one or more individual labels LABEL com.example.version="0.0.1-beta" LABEL vendor="ACME Incorporated" LABEL com.example.release-date="2015-02-12" LABEL com.example.version.is-production=""

画像には複数のタグを含めることができます。もちろん、上記の内容は次のように記述することもできますが、必ずしもそうする必要はありません。

 # Set multiple labels at once, using line-continuation characters to break long lines LABEL vendor=ACME\ Incorporated \ com.example.is-production="" \ com.example.version="0.0.1-beta" \ com.example.release-date="2015-02-12"

PS: 文字列にスペースが含まれている場合は、引用符で囲むか、スペースをエスケープする必要があります。文字列に内部引用符 (") が含まれている場合は、これらもエスケープできます。

走る

Dockerfile ファイルを読みやすく保守しやすい状態に保つには、長いまたは複雑な RUN 命令をバックスラッシュ \ を使用して複数行に分割し、読みやすさと保守性を向上させることをお勧めします。

RUN 命令の最も一般的な使用法は、apt-get を使用してパッケージをインストールすることです。 RUN apt-get コマンドはパッケージをインストールするため、注意すべき問題がいくつかあります。

  • apt-get upgrade または dist-upgrade を実行しないでください。多くの必要なパッケージは、権限のないコンテナでは適切にアップグレードできません。ベースイメージが古い場合は、メンテナーに連絡する必要があります。 foo などの特定のパッケージをアップグレードする必要があることが確実な場合は、apt-get install -y foo を使用するだけで、foo パッケージが自動的にアップグレードされます。
  • apt-get update と apt-get install を常に一緒に実行してください。そうしないと、apt-get install は失敗します。
  • 推奨される方法は、apt-get update && apt-get install -y package-a package-b です。これは、最初に更新してから、最新のソフトウェア パッケージをインストールします。
 RUN apt-get update && apt-get install -y \ aufs-tools \ automake \ btrfs-tools \ build-essential \ curl \ dpkg-sig \ git \ iptables \ libapparmor-dev \ libcap-dev \ libsqlite3-dev \ lxc=1.0* \ mercurial \ parallel \ reprepro \ ruby1.9.1 \ ruby1.9.1-dev \ s3cmd=1.1.0*

apt-get update を別の RUN ステートメントに配置すると、キャッシュの問題が発生し、その後 apt-get install が失敗する可能性があります。たとえば、次のような Dockerfile があるとします。

 FROM ubuntu:14.04 RUN apt-get update RUN apt-get install -y curl

イメージをビルドすると、すべてのレイヤーが Docker のキャッシュに保存されます。後で apt-get install を変更してパッケージを追加したとします。

 FROM ubuntu:14.04 RUN apt-get update RUN apt-get install -y curl nginx

Docker は、変更された RUN apt-get update 命令が以前のものとまったく同じであることを見つけます。そのため、apt-get update は実行されず、以前にキャッシュされたイメージが使用されます。 apt-get update が実行されなかったため、その後の apt-get install で curl と nginx の古いバージョンがインストールされる可能性があります。

RUN apt-get update && apt-get install -y を使用すると、Dockerfiles によって常に最新バージョンのパッケージがインストールされるため、このプロセスでは追加のコーディングや介入は必要ありません。この手法はキャッシュバスティングと呼ばれます。

EXPOSE命令

EXPOSE 命令は、コンテナがリッスンするポートを指定するために使用されます。したがって、アプリケーションには共通のポートを使用してください。

たとえば、Apache Web サーバーを提供するイメージでは EXPOSE 80 を使用し、MongoDB サーバーを提供するイメージでは EXPOSE 27017 を使用する必要があります。

外部アクセスの場合、ユーザーは docker run を実行するときに -p パラメータを使用して、指定したポートを任意のポートにマップする方法を指定できます。

ENV命令

新しいプログラムの実行を容易にするために、ENV 命令を使用して、コンテナーにインストールされているプログラムの PATH 環境変数を更新できます。たとえば、ENV PATH /usr/local/nginx/bin:$PATH を使用して、CMD ["nginx"] が正しく実行されることを確認します。

ENV 命令は、Postgres に必要な PGDATA などのコンテナ化されたサービスに必要な環境変数を提供するためにも使用できます。最後に、次の例のように、ENV を使用して共通のバージョン番号を設定することもできます。

 ENV PG_MAJOR 9.3 ENV PG_VERSION 9.3.4 RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && … ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

この方法では、プログラム内の定数と同様に、ENV 命令を変更するだけで、コンテナ内のソフトウェア バージョンを自動的に変更できます。

CMDF

CMD 命令は、コンテナの起動後のデフォルトの実行コマンドです。このデフォルトの意味を理解することが重要です。つまり、実行コマンドを指定せずに docker run を実行した場合、または Dockerfile に ENTRYPOINT が指定されていない場合は、CMD で指定された実行コマンドが実行に使用されます。これは、ENTRYPOINT がコンテナの起動後に実際に実行されるコマンドであることも示しています。

したがって、CMD が上書きされる状況に遭遇することはよくあります。なぜカバーされているのですか?主な理由は、CMD の配置がデフォルトであることです。追加で指定しない場合は、CMD コマンドが実行されます。ただし、これを指定すると、CMD コマンドは実行されず、CMD が上書きされてしまいます。

CMD を使用するには 3 つの方法があります。

 CMD ["executable", "param1", "param2"] # exec 形式CMD ["param1", "param2"] # 作为ENTRYPOINT 的默认参数CMD command param1 param2 # shell 形式

CMD ["executable","param1","param2"] の形式を使用することをお勧めします。イメージを使用してサービスを実行する場合は、CMD["apache2","-DFOREGROUND"]を使用する必要があります。このコマンド形式は、あらゆるサービスの性質を持つイメージに適用できます。

ENTRYPOINT命令

公式の定義によると、ENTRYPOINT はコンテナの起動後に実行プログラムを定義するために使用され、イメージをコマンド自体として実行できるようになります (CMD を使用してデフォルト オプションを提供します)。名前の通り、コンテナの入り口です。

ENTRYPOINT を使用するには 2 つの方法があります。

 ENTRYPOINT ["executable", "param1", "param2"] (exec 形式) ENTRYPOINT command param1 param2 (shell 形式)

対応するコマンドライン実行モード、つまり角括弧は、CMD の角括弧形式と一致しています。しかし、これは cmd とは異なるシェル環境で実行されるようです。

実行コマンドの後に実行コマンドが続く場合、次のすべてが ENTRYPOINT のパラメータとして使用されます。実行後に追加のコマンドがないが、CMD が定義されている場合は、CMD の内容全体が ENTRYPOINT のパラメータとして使用されます。これは、上で述べた CMD の 2 番目の使用法でもあります。

したがって、ENTRYPOINT は上書きされません。もちろん、実行時に上書きしたい場合は、--entrypoint パラメータを使用する方法があります。

通常、Docker コンテナの起動後のデフォルトの実行コマンドとして、ENTRYPOINT の角括弧形式が使用されます。変更されていない部分がその中に配置されます。コマンド パラメータなどの変数部分は、CMD の形式で提供して、デフォルト バージョン、つまり実行時にパラメータがない場合に使用されるデフォルト パラメータを提供できます。デフォルトのパラメータを使用する場合は、直接実行してください。それ以外の場合、他のパラメータを使用する場合は、実行するパラメータを追加します。

コピーを追加

ADD と COPY は似たような機能を持っていますが、COPY が推奨されます。 ADDよりも透明度が高いからです。 COPY は基本的なファイルコピー機能のみをサポートし、より制御可能です。 ADD には、tar ファイルの自動抽出や URL のサポートなど、さらに多くの機能があります。 ADD は通常、tarball からコンテナにファイルを抽出する必要がある場合に使用されます。

Dockerfile で複数のファイルを使用する場合は、各ファイルで個別の COPY 命令を使用する必要があります。この方法では、ファイルの変更の指示のみがキャッシュを使用しません。

画像のサイズを制御するために、ADD 命令を使用して URL ファイルを取得することはお勧めしません。正しい方法は、RUN 命令で wget または curl を使用してファイルを取得し、不要になったらファイルを削除することです。

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

音量

VOLUME 命令は、コンテナ内のディレクトリが永続化されること、つまりコンテナ内で作成されたディレクトリがホストまたは他のコンテナにマウントされ、コンテナ間でデータを共有できることを宣言するために使用されます。

VOLUME ディレクティブは、データベースが保存される場所、構成ファイルが保存される場所、およびコンテナー内でファイルまたはディレクトリが作成される場所を公開する必要があります。コンテナの終了後は変更が保存されないため、すべてのデータは VOLUME 経由でホストに保存する必要があります。

イメージの変更可能な部分とユーザーが変更できる部分を管理するには、VOLUME を使用することを強くお勧めします。

ユーザー

サービスを実行するために権限が必要ない場合は、USER コマンドを使用して非ルート ユーザーに切り替えます。 RUN groupadd -r mysql && useradd -r -g mysql mysql を使用し、次に USER mysql を使用してユーザーを切り替えます。

sudo を使用して権限を昇格することは避けてください。予測できない TTY およびシグナル転送動作により、解決するよりも多くの問題が発生する可能性があるためです。本当に sudo と同様の機能が必要な場合 (たとえば、デーモンを root 権限で初期化し、非 root 権限で実行するなど)、gosu を使用できます。いくつかの公式画像を確認することができますが、その多くは Gosu を使用しています。

最後に、ユーザーを繰り返し切り替えないようにし、不要なレイヤーを減らします。

ワークディレクトリ

明確さと信頼性を確保するため、WORKDIR パスは常に絶対パスにする必要があります。また、メンテナンスが難しい RUN cd ... && do-something の代わりに WORKDIR を使用してください。後者は、読み取り、デバッグ、保守が困難です。

<<:  クラスタの平均CPU使用率は45%に達し、Xiaohongshuの大規模コロケーション技術の実践が明らかになった。

>>:  Q: Kafka のアプリケーション シナリオは何ですか?いくつか挙げていただけますか?

推薦する

あなたのウェブサイトの基本的な SEO は最適化されていますか?

ネットワークマーケティング業界は成長を続けています。ユーザーエクスペリエンスを向上させるために、検索...

Tektonを物理マシンに接続して構築する方法

[[396376]]この記事はWeChatの公開アカウント「Ask Qi」から転載したもので、著者は...

インターネット住宅リフォームスタートアッププロジェクトの総合評価:荘心通、金家、成家住宅リフォーム、ゼブラ住宅リフォーム

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますiMedi...

XPRIZE創設者ピーター・ディアマンディスがデジタル変革のリーディングカンファレンスLiveWorxで基調講演

PTC (NASDAQ: PTC) は、ピーター・ディアマンディス医学博士が、6 月 11 日火曜日...

ネットワークマーケティングにおける新しいビジネスチャンスのスキルについての簡単な議論

インターネット マーケティングは、結局のところ、販売です。販売といえば、顧客を惹きつけて製品やサービ...

ライセンスか消費習慣か、海外のクラウドベンダーが中国市場に参入する際に直面する壁はどちらでしょうか?

数日前、有名なアマゾンAWSが光環新網絡に20億元(分割払い)を超えない金額で買収され、業界で大きな...

Alwyzon: オーストリア VPS、年間 35 ユーロ、2G メモリ/2 コア (EPYC)/40g NVMe/20T トラフィック

alwyzon は現在イースター セールを実施しており、オーストリアのウィーンで 100 個の VP...

テンセントクラウドストレージ製品マトリックスが全面アップグレード、立体生態戦略を発表

テンセントクラウドは5月10日、北京でストレージ製品戦略発表会を開催し、業界初となる10マイクロ秒の...

新しいウェブマスターがウェブサイトのプロモーションで注意すべき点を分析する

新しいウェブマスターのウェブサイトの開発が遅かったり、満足のいく結果が得られなかったりする主な理由の...

Zcncms ウェブサイト管理システム評価

zcncms とは何ですか? zcncms は PHP で開発された新しい CMS です。今日は、将...

カップルがブラインドボックスを販売して年間16億元を稼ぎ、ポップマートの儲かるビジネスを明らかにする

「ブラインドボックス」コンセプトで有名になった国内有名トレンド玩具メーカー「ポップマート」が、ついに...

Baidu プロモーション入札広告がウェブマスターのグループによってクリックされた場合、勝者は誰でしょうか?

7月16日以降、さまざまなSEMグループで大量の写真が次々と公開されています。内容はほぼ同じです。下...

音声は沈黙よりも優れています。オーディオ小説のプロモーションとマーケティング方法についての簡単な説明

2012年現在、オーディオ小説は再び活発な発展の時代を迎えています。現在、百度インデックスは1日あた...

Microsoft Azure Stack ハイブリッド クラウドが中国に進出

北京、2017 年 11 月 1 日 - Microsoft CEO の Satya Nadella...

ツール型ウェブサイトのホームページデザイン検討 ホームページデザインタイプ分析

ツールウェブサイトとは何ですか?まず、Wikipedia の 3 つの概念グループを理解しましょう。...