記事ディレクトリ
プログラミングを学ぶための最速の方法は、最初に自分でいくつかの基本的な概念を学び、次にダニエルがどのようにコードを書くかを見に行くことだといつも感じていました 。ダニエルの書き方を模倣して理解することで、プログラミングを学ぶための最速の方法 です。一部の友人はこう言うかもしれません:どうしてあなたが見ることができる素晴らしいコードがたくさんあるのでしょうか、githubに行ってください。オープンソース組織の公式コードはたくさんあります。Dockerfileの調査も例外ではありません。公式のリソースを使用して、他のユーザーがどのように記述しているかを確認してください。この記事では、公式のnginxイメージビルドファイルDockerfileを1行ずつ解析します。この記事に含まれるスクリプト は、 github:docker-nginx の公式チャンネルから入手 できます。
1.Dockerfileとは何ですか
Dockerfileは、Dockerイメージを自動的にビルドするための構成ファイルです。イメージのビルドプロセスは、Dockerfileで指示に従って定義されます。コマンドラインを使用するdocker build
と、Dockerイメージの構築を自動化できます。
FROM debian:bullseye-slim
LABEL maintainer="NGINX Docker Maintainers <[email protected]>"
ENV NGINX_VERSION 1.20.2
ENV NJS_VERSION 0.7.0
ENV PKG_RELEASE 1~bullseye
RUN set -x \ #节省篇幅,主要是学习Dcokerfile语法,这里省略了若干行linux的shell脚本
COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
上の写真は、Dockerイメージのnginx:1.20.2バージョンのDockerfileです。1行ずつ解析してみましょう。
2.nginxのDockerfile構文を解析します
私たちが言語や文書の文法を学ぶとき、学ぶための最も速い方法は、他の人がそれをどのように書いているかを見ることです。この「他の人」が誰であるかは非常に重要であり、臭いチェスバスケットでチェスをするほど、臭いが増します。したがって、Dockerfileの構文を学ぶには、モデルを見つける必要があります。Dockerhubにアクセスして、オープンソースソフトウェアによって公式に提供されているイメージを確認し、対応するDockerfileを見つけて、他の人がどのように記述しているかを確認できます。
上記のDockerイメージのnginx:1.20.2バージョンのDockerfile(公式に提供されている)を使用し、その構文と構築プロセスを1行ずつ解析してみましょう。
から
通常、イメージを作成するには、基本的なLinuxオペレーティングシステムのディストリビューションイメージが必要です。これに基づいて、独自のイメージを作成します。
FROM debian:bullseye-slim
したがって、FROM命令の役割はベースイメージを指定することであり、ここでnginxが使用するベースLinuxイメージはですdebian:bullseye-slim
。その中にdebian:bullseye
は、debian linuxディストリビューションオペレーティングシステムのバージョンがあり、バージョン名はブルズアイです。slim
これは通常、このイメージがリリースバージョンの最小インストールバージョンであることを意味します。これは、ビルドするイメージが後続の継続的インテグレーションプロセスと、ウェアハウスとDockerサーバー間のネットワークで伝播されるためです。したがって、イメージのビルド結果をここまでにします。可能な限りサイズを最小化します。基本イメージの選択は、サイズのサイズに焦点を当てる必要があります。Linuxの基本機能とプログラムの操作を満たしている場合は、小さいほど良いです。
ラベル
LABELは、現在の画像のメンテナや連絡先情報など、現在の画像に説明的で説明的な情報を追加するために使用されます。キーと値のペアの形式でカスタマイズされ、1行で複数を定義できます。
LABEL <key>=<value> <key>=<value> <key>=<value> ...
メンテナメンテナ情報、説明画像説明情報など、複数の行を定義することもできます。説明情報を1行に書き込めない場合は、「\」を使用して行を折り返すことができます。Dockerfile構文にはMAINTAINERという命令があります。これは、イメージのメンテナー情報を記述するために特別に使用されますが、現在は非推奨であり、LABELは一律に使用されています。
LABEL maintainer="NGINX Docker Maintainers "
LABEL description="This is a Docker image \
for nginx 1.20.2. "
ENV
ENVの役割は、環境変数を設定することです。環境変数を設定すると、ビルドプロセスや、コンテナの実行時にシェルスクリプトで変数を使用できるようになります。使用方法は次のとおりです${NGINX_VERSION}
。JAVAを学んだ学生は、JAVA_HOME環境変数がどのように設定され、どのように使用されるかについて考えていますか?ENVは同じです。dockerの構文が変更されただけです。構文形式は次のとおりですENV 环境变量KEY 环境变量Value
。
ENV NGINX_VERSION 1.20.2
ENV NJS_VERSION 0.7.0
ENV PKG_RELEASE 1~bullseye
走る
RUN命令の機能は、Linuxシェルスクリプトを実行することです。次の図から、ENVで定義された環境変数をシェルスクリプトで使用できることがわかります。
nginxイメージの場合、RUN命令の役割は、一連のシェルコマンドライン(スクリプト)を実行してnginxのインストールを完了することです。したがって、RUNコマンドをマスターするための鍵は、RUNコマンド自体ではなく、次の鍵です。
- nginxを手動でインストールしますか?
- Linuxのシェルスクリプト構文を知っていますか?
- nginxのインストールプロセスをシェルスクリプトとして記述できますか?
上記の3つの質問に対する答えが「はい」の場合は、RUNコマンドを使用してシェルスクリプトを実行し、ソフトウェアのインストールを完了します。これはDockerfileのコンテンツの中核でもあります。Linuxシェルはこの記事で説明したいものではありません。
コピー
COPY命令の機能は、ローカルファイル(イメージビルドが実行されるサーバー)をイメージファイルにコピーすることです。構文は次のとおりです。 COPY <本地文件路径>:<镜像文件路径>
、イメージファイルパスは、コンテナランタイムファイルシステムへのパスでもあります。
COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ローカルファイルパスにファイル名しかない場合は、ファイルとDockerfileが同じディレクトリにあることを意味します(相対パス構文)。つまり、次のファイルが同じディレクトリにあります(これらのファイルは、上記の公式のnginx Dockerfileリンクで確認できます)。
または、WORKDIRディレクティブを使用して、Dockerfileでそれに続くRUN、CMD、ENTRYPOINT、COPY、ADDディレクティブのローカル作業ディレクトリを設定します。このように、上記の相対パスは、WORKDIRの指定されたパスを基準にした相対パスです。ただし、ビルドを実行する開発者の作業ホストの作業パスとDockerfileライターの作業パスが同じであることを確認するのは難しいため、一般にWORKDIRの使用はお勧めしません。
WORKDIR /root
エントリーポイント
Dockerfileで複数のENTRYPOINTが定義されている場合、最後のENTRYPOINTのみが有効になり、Dockerコンテナーが開始されるたびに、ENTRYPOINTで指定されたスクリプトが実行されます。nginx:1.20.2の場合、「/ docker-entrypoint.sh」スクリプトは、nginx構成チェックとnginxサービスの起動手順を定義します。したがって、ENTRYPOINTで指定されたスクリプトは、通常、イメージ内のコアサービスの起動スクリプトです。
ENTRYPOINT ["/docker-entrypoint.sh"]
このスクリプトは、最終的にnginxサービスの起動を実行します。これは、CMDコマンドで完了する必要があります。以下のCMDコマンドを参照してください。
公開
Dockerコンテナーは、実行時に指定されたネットワークポートを公開します。これは、コンテナーポートマッピングに使用できます。デフォルトのプロトコルはTCPです。形式は次のとおりです。
EXPOSE <端口号>
EXPOSE <端口号>/<协议>
コンテナポートが公開された後、ホストのポートとのマッピング関係を確立できるため、ホストのポートにアクセスすることでコンテナ内のサービスにアクセスできます。たとえば、TCPとUDPの両方で同時にコンテナのポート80を公開します。
EXPOSE 80/tcp
EXPOSE 80/udp
STOPSIGNAL
この手順は作成者によって一般的に使用されていません。githubでdocker-nginxの問題を確認しました。答えは、STOPSIGNALシグナルを追加する目的は、nginxサービスが正しく終了できず、dockerの後にゾンビプロセスが発生するのを防ぐことです。コンテナが停止しています。存在。
STOPSIGNAL SIGQUIT
CMD
CMDコマンドは、Linuxコマンドまたはスクリプトの実行にも使用されます。これはRUNコマンドと一致しています。2つの違いは
- CMD命令は
docker run
、命令の実行時、つまりコンテナの作成時に実行され、RUN命令は、イメージの構築時、つまりdocker bulid
すぐに実行されます。 - また、RUN名で実行される書き込み動作がミラー層に書き込まれるのは、命令の実行期間が異なるためです。CMD命令の実行結果には、コンテナ層に書き込まれる書き込み操作が含まれます。(以前の記事「ミラーレイヤリングの原則」を参照して、学習および理解することができます)。
- したがって、CMD命令とENTRYPOINT命令は多少似ており、どちらもコンテナの作成時に実行されます。ENTRYPOINT命令がDockerfileに含まれると、CMD命令はENTRYPOINTで指定されたスクリプトのパラメーターとして存在することに注意してください。以下のフォーマット構文を参照してください。
CMDには次の3つの形式があります。
- 1つ目は、ENTRYPOINTで指定されたパラメーターを渡すスクリプトです。上記のENTRYPOINTスクリプトの最後の行は、
exec "$@"
CMDで渡されたコマンドとパラメーターを実行することです。nginxサービスの起動を完了します。この使用法は、公式のDockerfiles(nginx、redisなど)で一般的に使用されます。これは、ENTRYPOINTで指定されたスクリプトで構成の準備を行いexec "$@"
、ENTRYPOINTスクリプトの最後の行でCMDコマンドを呼び出してコンテナーサービスを開始します。 。
CMD ["nginx", "-g", "daemon off;"]
- 2つ目は、コマンドまたはシェルスクリプトを実行することです。パラメーターを渡すことができ、二重引用符に注意を払うことができます。構文は最初の形式と同じですが、ENTRYPOINTで指定されたスクリプトがないため、ENTRYPOINTで指定されたスクリプトのパラメーターとして存在しません。
CMD ["executable","param1","param2"]
echo "This is a test." | wc -c
3つ目は、シェルコマンドラインの実行など、シェルスクリプトを実行するための一般的な構文です。著者は次のように述べています。Dockerfileでこのメソッドを使用しないでください。理由を知る必要はありません。
CMD echo "This is a test." | wc -c