DockerFile ファイルを理解するには 5 分

基本情報

とは

Dockerfile はイメージの説明ファイルであり、Docker はこのファイルを読み取って新しいイメージを生成できます。
画像.png

Dockerfile、イメージ、コンテナの関係

アプリケーション ソフトウェアの観点から見ると、Dockerfile、Docker イメージ、Docker コンテナはソフトウェアの 3 つの異なる段階を表します。

  • Dockerfileはソフトウェアの原材料です
  • Docker イメージはソフトウェア成果物です
  • Docker コンテナは、ソフトウェア イメージの実行状態、つまりイメージに従って実行されるコンテナ インスタンスと考えることができます。

開発中心の Dockerfile、配信標準となる Docker イメージ、デプロイと運用保守を行う Docker コンテナは、これら 3 つが不可欠であり、連携して Docker システムの基礎となります。
画像.png
3 つのステップを構築します。

  1. Dockerfile の書き込み
  2. イメージをビルドするための Docker build コマンド
  3. Docker runはイメージに従ってコンテナインスタンスを実行します

DockerはDockerfileの一般的な処理を実行します。

  1. Docker はベースイメージからコンテナを実行します
  2. 命令を実行してコンテナに変更を加える
  3. Docker commit と同様の操作を実行して、新しいイメージ レイヤーを送信します。
  4. Docker は送信されたばかりのイメージに基づいて新しいコンテナを実行します
  5. すべての命令が実行されるまで、Dockerfile 内の次の命令を実行します。

Dockerfile の書き込み

Docker ハブのイメージには Dockerfile ファイルへのリンクも含まれており、クリックしてリファレンスを表示できます。

Dockerfile の基本情報:

  1. 各予約語命令は大文字で、その後に少なくとも 1 つのパラメータが続く必要があります。
  2. 命令は上から下へ順番に実行されます
  3. #コメントを表します
  4. 各コマンドは新しいイメージレイヤーを作成し、イメージをコミットします

Dockerfile の予約語

から

ベース イメージ (現在の新しいイメージのベースとなるイメージ) は、既存のイメージをテンプレートとして指定します。最初の項目は FORM である必要があります。

メンテナー

ミラー管理者の名前と電子メール アドレス

走る

イメージのビルド時に実行されるコマンド (Docker ビルド)

2つのフォーマット

  • シェル形式:RUN 命令
    • RUN の後のコマンドは、FORM の基本イメージ上のインスタンス化されたコンテナー内のターミナルで実行するのと同じです。
      • たとえば、centos7 をベースにしたノード環境で centos7Plus イメージを構築する場合、
      • RUN yum install -y node
      • それは元のcentos7のターミナルで実行するのと同等ですyum install -y node
  • exec形式(json配列形式):RUN ["可执行文件", "参数1", "参数2"]
    • 例:RUN ["./test.php", "dev", "offline"と同等RUN ./test.php dev offline

公開

現在のコンテナによって外部に公開されるポート

作業ディレクトリ

コンテナーの作成後、足場となるターミナルのデフォルトのログイン作業ディレクトリが指定されます。たとえば、Tomcat イメージの場合、コンテナターミナルに入ると、現在のディレクトリは次のようになります。/usr/local/tomcat

ユーザー

イメージを実行するユーザーを指定します。指定しない場合、デフォルトは root です。
USER ユーザー名: ユーザーグループまたは
USER ユーザー ID: グループ ID

環境

イメージの構築中に環境変数を設定するために使用されます。

たとえば、
ENV MY_PATH /usr/mytest
この環境変数は、コマンドの前にエイリアスが定義されているのと同じように、後続の RUN コマンドで使用でき、これらの環境変数は他のコマンドでも直接使用できます。
たとえば、デフォルトの作業ディレクトリを設定するには、次のようにします。WORKDIR $MY_PATH

追加してコピー

ADD <src> <dest>

  • 詳細説明: このコマンドは、指定されたパス下のコンテンツをイメージ内のパスにコピーします。
  • : Dockerfile が配置されているディレクトリの相対パス (ファイルまたはディレクトリ)、URL、tar ファイル (ディレクトリに自動的に解凍される) のいずれかにすることができます。
  • : イメージ内の絶対パス、または作業ディレクトリ (WORKDIR) を基準とした相対パスにすることができます。
  • パス: 正規表現をサポートします。

COPY は ADD に似ており、ファイルとディレクトリをイメージにコピーします。
ファイル/ディレクトリをビルド コンテキスト ディレクトリの <ソース パス> から新しいレイヤーのミラー内の <宛先パス> の場所にコピーします。

2 つの形式の RUN と同じ:

  • COPY src dest
  • COPY ["src", "dest"]

<src source path>: ソースファイルまたはソースディレクトリ
<dest destination path>: コンテナ内の指定されたパス。このパスは事前に作成する必要はありません。パスが存在しない場合は自動的に作成されます。

知らせ

  1. リモート URL からのリソースは解凍されません。ディレクトリがコピーまたは抽出される場合、tar -x と同じように動作します。
  2. 絶対パス、または WORKDIR を基準とした相対パスです。これは、ディレクトリがスラッシュで終わる必要があることを意味します。そうでない場合、ディレクトリはファイルとみなされ、コンテンツがファイルに追加されます。
# 使用相对路径的栗子
ADD test.txt relativeDir/
# 等价于
ADD test.txt <WORKDIR>/relativeDir/

# 使用绝对路径的栗子
# 将 test.txt 添加到 /absoluteDir/ 目录下
ADD test.txt /absoluteDir/
  1. ディレクトリの場合は、ディレクトリ内の内容のみがコピーされ、ディレクトリ自体はコピーされません。** は、Dockerfile ファイルが配置されているディレクトリの相対パスです。**
    1. .../something 、 /something のようなディレクトリを追加することはできません。Docker ビルドの最初のステップは、Dockerfile が存在するディレクトリ (およびサブディレクトリ) であるコンテキスト ディレクトリを Docker デーモンに送信することであるためです。
# test.txt 是相对路径,相对于构建上下文
COPY test.txt /mkdir/

# 错误写法,文件均不在上下文目录中,并不会被找到
# 这个找的就是构建上下文的上级目录的 test.txt
COPY ../test.txt /mkdir/

# 这个找的是本机根目录下的 test.txt
COPY /test.txt /mkdir/

Dockerfile の公式ベスト プラクティスによると、リモート URL からファイルを追加するか、圧縮ファイルを自動的に抽出する必要が本当に必要な場合を除き、ADD を使用し、それ以外の場合は COPY を使用します。

  • リモート URL からファイルを ADD フェッチしてコピーすることは、ファイルにより Docker イメージの最終サイズが増加するため、理想的ではありません。
  • 代わりに、curl または wget を使用してリモート ファイルを取得し、不要になったら削除する必要があります。

要約:

  • ADD はリモート URL の追加と圧縮形式でのファイルの自動抽出をサポートします。COPY はこのマシンからのファイルのコピーのみを許可します
  • COPY は、他のビルド フェーズ (-from) からのソース ファイルのコピーをサポートします。
  • 公式の Dockerfile ベスト プラクティスによると、リモート URL からファイルを追加するか、圧縮ファイルを自動的に抽出する必要がない限り、ADD を使用し、それ以外の場合は COPY を使用します。

音量

データのストレージと永続化のためのコンテナ データ ボリューム

CMD とエントリーポイント

どちらも、新しく作成されたイメージ ランタイム (docker run) を指定するときに、コンテナー ターミナルでデフォルトで実行されるコマンドです。
たとえば、ubuntu イメージを実行すると、docker run -it ubuntuUbuntu システムの bash は実行後すぐに直接起動されます。ubuntu イメージをビルドするとき、Dockerfile は CMD または ENTRYPOINT を介してデフォルトの起動 bash を指定する必要があります。

この 2 つによって指定されるコマンドは、ブロッキング コマンド、つまり bash や tail などのフォアグラウンド タスクを伴うコマンドであることが好ましい。それ以外の場合、非ブロッキング コマンドの場合、コマンドの実行が終了するとすぐにコンテナーが終了し、実行が停止されます。

Dockerfile にはこれら 2 つの命令のいずれかが存在する必要があります。そうでない場合は、親イメージから継承されます。親イメージにそれがない場合、イメージのビルドは失敗します。

どちらも RUN と同様、コマンドを定義するための 2 つの形式、shell と exec があります。

  • シェル形式: . 例: apt-get install python3
  • 実行形式: ["実行可能ファイル", "param1", "param2", ...]。例: ["apt-get"、"install"、"python3"]

コマンドが読みやすく理解しやすいため、CMD および ENTRYPOINT には Exec 形式をお勧めします。どちらの形式も RUN に使用できます。

違い

  1. Dockerfile には複数の CMD 命令を含めることができますが、有効になるのは最後の命令だけであり、CMD で指定されたデフォルトのコマンドは、docker の実行後に手動で渡されたコマンドに置き換えられます。

たとえば、Redis をdocker run -it redis直接実行すると、Redis 制御コマンド ラインに直接入力できます。実行するとdocker run -it redis /bin/bash、Redis コンテナーの仮想 Linux 環境ターミナルに入ります。Redisredis-cliコマンド ラインに入るには、再度実行する必要があります。

[root@192 app]# docker run -it redis
1:C 08 Feb 2023 19:57:36.965 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
......
1:M 08 Feb 2023 19:57:36.968 * Ready to accept connections

(ctrl + c)
1:M 08 Feb 2023 19:58:37.474 # Redis is now ready to exit, bye bye...

[root@192 app]# docker run -it redis /bin/bash
root@b5df641baaa0:/data# redis-cli
  1. ENTRYPOINT がシェル形式の場合、ENTRYPOT が優先され、CMD および docker 実行後に手動で追加されたコマンドは無視されます。
  2. ENTRYPOINT が exec 形式で、CMD も exec 形式の場合、CMD か手動入力コマンドかに関係なく、ENTRYPOINT コマンドの後にパラメータとして接続されます。
    1. 注: docker run の背後にコマンドがある場合、CMD のコマンドは常に上書きされます。
FROM alpine
WORKDIR /docker
RUN echo 111 >> 1.txt
RUN echo 222 >> 2.txt
RUN echo 333 >> 3.txt
CMD ["cat","/docker/2.txt"]
ENTRYPOINT ["cat","/docker/1.txt"]
docker build -t test1 .

docker run test1 #执行的命令相当于 cat 1.txt cat 2.txt
> cat: can't open 'cat': No such file or directory
> 111
> 222

docker run test1 3.txt #执行的命令相当于 cat 1.txt 3.txt
> 111
> 333 #docker run 后面参数代替了 CMD
  1. ENTRYPOINT が exec 形式で、CMD がシェルの場合、コマンド全体の途中に[ENTRYPOINT命令] /bin/sh -c [CMD命令]もう 1 つのコマンドが存在するために結合結果が発生し、通常はコマンド全体が無効になります。/bin/sh -cしたがって、この種の混合形式の使用は慎重に行う必要があります。
    • sh -cこれにより、bash は文字列を完全なコマンドとして実行できるようになります。
FROM alpine
WORKDIR /docker
RUN echo 111 >> 1.txt
RUN echo 222 >> 2.txt
RUN echo 333 >> 3.txt
CMD cat /docker/2.txt
ENTRYPOINT ["cat","/docker/1.txt"]
docker build -t test1 .

docker run test2 #执行的命令相当于 cat 1.txt /bin/sh -c cat 2.txt
#因为 cat 命令无法识别 -c 选项,所以导致整个命令无效报错
cat: unrecognized option: c
BusyBox v1.34.1 (2021-11-23 00:57:35 UTC) multi-call binary.

Usage: cat [-nbvteA] [FILE]...

Print FILEs to stdout

        -n      Number output lines
        -b      Number nonempty lines
        -v      Show nonprinting characters as ^x or M-x
        -t      ...and tabs as ^I
        -e      ...and end lines with $
        -A      Same as -vte

docker run test2 3.txt #覆盖了CMD,所以命令正常
> 111
> 333

公式ウェブサイトで紹介されている違いは次のとおりです。

CMD と ENTRYPOINT がどのように相互作用するかを理解する

と の両方の命令は、コンテナーの実行時に実行されるコマンドを定義します。彼らの協力を説明するルールはほとんどありません。CMD ENTRYPOINT

  1. Dockerfile では、 または コマンドの少なくとも 1 つを指定する必要があります。CMD ENTRYPOINT
  2. ENTRYPOINTコンテナを実行可能ファイルとして使用する場合は定義する必要があります。
  3. CMDコマンドのデフォルト引数を定義する方法として、またはコンテナ内でアドホック コマンドを実行する方法として使用する必要があります。ENTRYPOINT
  4. CMD代替引数を使用してコンテナを実行するときにオーバーライドされます。

以下の表は、さまざまな / 組み合わせでどのようなコマンドが実行されるかを示しています。ENTRYPOINTCMD
画像.png

注:
がベース イメージから定義されている場合、設定は空の値にリセットされます。このシナリオでは、値を持つように現在のイメージで定義する必要があります。CMD ENTRYPOINT CMD CMD

要約する

さまざまな段階で役割を果たすキーワード。

建てる 両方 走る
形状 作業ディレクトリ CMD
メンテナー ユーザー 環境
コピー 公開
追加 音量
走る エントリーポイント
オンビルド
.dockerignore

練習

要件: vim+ifconfig+jdk17 を使用して centos イメージをビルドします。
jdk17 を Dockerfile が存在するディレクトリ (ここでは /docker) にダウンロードします。

wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz -P /docker/

Dockerfile を書きます:

FROM centos7
MAINTAINER ikun
 
ENV MYPATH /usr/local
WORKDIR $MYPATH
 
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java

#ADD 是相对路径jar,把jdk添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-17_linux-x64_bin.tar.gz /usr/local/java/

#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk-17.0.6
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
 
EXPOSE 80

#CMD的覆盖不影响CMD输出
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash

ビルドイメージ

build コマンドはイメージをビルドします

構文:docker build -t <镜像名>:<tag> <Dockerfile文件目录>
例:docker build -t myCentos .

  • タグは省略されており、デフォルトは最新です
  • . は現在のディレクトリを表します

ぶら下がりイメージ

ダミーイメージとは、イメージ名とタグが両方とも none であるイメージです。
ビルド中に、うっかりイメージ名とタグを入力するのを忘れてしまい、docker build .ダミーのイメージがビルドされてしまいました。
このマシンの仮想ミラー リストを確認してください。docker image ls -f dangling=true
仮想ミラーには値がありません。削除することをお勧めします。docker image prune

おすすめ

転載: blog.csdn.net/qq_43220213/article/details/129608582