あなたはDockerに少し精通しており、Dockerコンテナの実行などの基本を知っていると思います。
以前の記事では、Dockerコンテナの更新とDockerファイルの作成について説明しました。
Dockerイメージを変更するのは正確には何ですか?
コンテナイメージはレイヤーに組み込まれ(またはレイヤーのコレクションです)、各Dockerfile命令はイメージのレイヤーを作成します。たとえば、次のDockerfileについて考えてみます。
FROM alpine:latest
RUN apk add --no-cache python3
ENTRYPOINT ["python3", "-c", "print('Hello World')"]
合計3つのDockerfileコマンドがあるため、このDockerfileから構築されたイメージには、合計3つのレイヤーが含まれます。
イメージを作成することで確認できます:
docker image built -t dummy:0.1 .
次に、コマンドdocker image history
を使用します 構築されたイメージ上。
articles/Modify a Docker Image on modify-docker-images [?] took 12s
❯ docker image history dummy:0.1
IMAGE CREATED CREATED BY SIZE COMMENT
b997f897c2db 10 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["python3" "-c… 0B
ee217b9fe4f7 10 seconds ago /bin/sh -c apk add --no-cache python3 43.6MB
28f6e2705743 35 hours ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 35 hours ago /bin/sh -c #(nop) ADD file:80bf8bd014071345b… 5.61MB
最後の「
これらの各レイヤーは読み取り専用です。これらのレイヤーは読み取り専用であるため、このイメージの実行中のインスタンスに関連付けられたプロセスはこのイメージのコンテンツを変更できません。したがって、これらのレイヤーは、保持しなくても多くのコンテナーで共有できます。インスタンスごとにコピーします。ただし、コンテナのプロセスでr / wを実行できるようにするには、コンテナの作成時に既存のROレイヤーの上に別のレイヤーが追加されます。これは書き込み可能であり、他のコンテナと共有されません。
このr/wレイヤーの欠点は、このレイヤーで行われた変更が永続的ではないことです。ただし、ボリュームを使用して一部のデータを永続化することはできますが、既存のレイヤーの前にレイヤーを追加したり、レイヤーを削除したりする必要がある場合があります。画像または単にレイヤーを置き換えます。これらが、既存のdocker
を変更したい理由です。 画像。
この記事では、さまざまな方法を使用して、上記のすべてのケースについて説明します。
Dockerイメージを変更する方法は2つあります。
- Dockerfilesを介して。
- コマンド
docker container commit
の使用 。
両方の方法について説明し、最後に、コンテキスト内の方法にどちらのユースケースが適しているかを追加します。
方法1:Dockerfileを介してDockerイメージを変更する
Dockerイメージを変更することは、基本的にイメージのレイヤーを変更することを意味します。これで、各Dockerfileコマンドはイメージの1つのレイヤーを表すため、Dockerfileの各行を変更すると、それぞれのイメージも変更されます。
したがって、画像にレイヤーを追加する場合は、別のDockerfile命令を追加するだけで、1つを削除するには行を削除し、レイヤーを変更するには、それに応じて行を変更します。
Dockerfileを使用してイメージを変更する方法は2つあります。
- 変更するイメージをベースイメージとして使用し、子イメージを作成します。
- 変更するイメージの実際のDockerfileを変更します。
どの方法をいつ、どのように使用すべきかを説明しましょう。
1。画像をベース画像として使用する
これは、変更する画像を取得し、それにレイヤーを追加して新しい子画像を作成する場合です。イメージが最初から作成されない限り、すべてのイメージは同じ親ベースイメージへの変更です。
以前のDockerfileについて考えてみます。その画像から構築された画像の名前がdummy:0.1
であるとします。 。ここで、「Hello World」を印刷するためにPython3の代わりにPerlを使用する必要があると思ったが、Python3も削除したくない場合は、dummy:0.1
を使用できます。 ベースイメージとしてのイメージ(Python3はすでに存在するため)、次のようにそれからビルドします
FROM dummy:0.1
RUN apk add --no-cache perl
ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]
ここでは、dummy:0.1
の上に構築しています 、適切と思われるレイヤーを追加します。
この方法は、既存のレイヤーを変更または削除する場合にはあまり役に立ちません。そのためには、次の方法に従う必要があります。
2。イメージのDockerfileを変更する
イメージの既存のレイヤーは読み取り専用であるため、新しいDockerfileを使用してそれらを直接変更することはできません。 FROM
を使用 Dockerfileでコマンドを実行すると、ベースとしてイメージを取得し、上にビルドします。 それ、またはそれにレイヤーを追加します。
一部のタスクでは、既存のレイヤーを変更する必要がある場合がありますが、以前の方法を使用して、矛盾するRUN
の束を使用して変更することができます。 手順(ファイルの削除、前のレイヤーで追加されたパッケージの削除/置換など)は、理想的なソリューションではなく、私がお勧めするものでもありません。レイヤーが追加され、画像サイズが大幅に増加するためです。
より良い方法は、イメージをベースイメージとして使用せずに、そのイメージの実際のDockerfileを変更することです。以前のDockerfileをもう一度考えてみてください。そのイメージにPython3を保持する必要がなく、Python3パッケージとコマンドをPerlのものに置き換える必要がなかった場合はどうなりますか?
前の方法に従うと、次のような新しいDockerfileを作成する必要がありました-
FROM dummy:0.1
RUN apk del python3 && apk add --no-cache perl
ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]
構築された場合、この画像には合計5つのレイヤーが含まれます。
articles/Modify a Docker Image on modify-docker-images [?] took 3s
❯ docker image history dummy:0.2
IMAGE CREATED CREATED BY SIZE COMMENT
2792036ddc91 10 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["perl" "-e" "… 0B
b1b2ec1cf869 11 seconds ago /bin/sh -c apk del python3 && apk add --no-c… 34.6MB
ecb8694b5294 3 hours ago /bin/sh -c #(nop) ENTRYPOINT ["python3" "-c… 0B
8017025d71f9 3 hours ago /bin/sh -c apk add --no-cache python3 && … 43.6MB
28f6e2705743 38 hours ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 38 hours ago /bin/sh -c #(nop) ADD file:80bf8bd014071345b… 5.61MB
また、画像のサイズは83.8MBです。
articles/Modify a Docker Image on modify-docker-images [?]
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dummy 0.2 2792036ddc91 19 seconds ago 83.8MB
これを行う代わりに、最初のDockerfileを取得し、Python3のものをPerlに変更します
FROM alpine:latest
RUN apk add --no-cache perl
ENTRYPOINT ["perl", "-e", "print \"Hello World\n\""]
レイヤーの数が3に減り、サイズは40.2MBになりました。
articles/Modify a Docker Image on modify-docker-images [?] took 3s
❯ docker image history dummy:0.3
IMAGE CREATED CREATED BY SIZE COMMENT
f35cd94c92bd 9 seconds ago /bin/sh -c #(nop) ENTRYPOINT ["perl" "-e" "… 0B
053a6a6ba221 9 seconds ago /bin/sh -c apk add --no-cache perl 34.6MB
28f6e2705743 38 hours ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 38 hours ago /bin/sh -c #(nop) ADD file:80bf8bd014071345b… 5.61MB
articles/Modify a Docker Image on modify-docker-images [?]
❯ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dummy 0.3 f35cd94c92bd 29 seconds ago 40.2MB
画像が正常に変更されました。
前の方法は、既存のレイヤーの上にレイヤーを追加する場合に便利ですが、既存のレイヤーを削除、置換、並べ替え、すぐ。そこで、この方法が光ります。
方法2:dockercommitを使用して画像を変更する
実行中のコンテナのスナップショットを取り、それを独自のイメージに変換できる別の方法があります。
dummy:0.1
を作成しましょう 同一のイメージですが、今回はDockerfileを使用していません。 alpine:latest
を使用したので dummy:0.1
として のベース、その画像のコンテナをスピンアップします。
docker run --rm --name alpine -ti alpine ash
コンテナ内に、Python3パッケージを追加します。apk add --no-cache python3
。完了したら、新しいターミナルウィンドウを開き、次のコマンド(または同様のコマンド)を実行します
docker container commit --change='ENTRYPOINT ["python3", "-c", "print(\"Hello World\")"]' alpine dummy:0.4
--change
を使用 フラグ新しいdummy:04
にDockerfile命令を追加しています 画像(この場合、ENTRYPOINT
指示)。
docker container commit
を使用 コマンドでは、基本的に最も外側のr/wレイヤーをr/oレイヤーに変換し、それを既存の画像のレイヤーに追加して、新しい画像を作成します。この方法はより直感的でインタラクティブなので、Dockerfilesの代わりにこれを使用することをお勧めしますが、これはあまり再現性がないことを理解してください。また、既存のレイヤーの削除または変更にも同じルールが適用されます。少なくともほとんどの場合、何かを削除したり、前のレイヤーで行った何かを変更したりするためだけにレイヤーを追加することは最善の方法ではありません。
これでこの記事は終わりです。これがお役に立てば幸いです。ご不明な点がございましたら、下にコメントしてください。