title: 【転載】Docker イメージの原理
date: 2021-08-16 09:24:01
comment: false
toc: true
category:
- Docker
tags: - 転載
- Docker
- イメージ
- 原理
この記事は、Docker イメージの原理から転載されています。
Docker イメージの原理#
イメージは、ソフトウェアの実行環境とその環境に基づいて開発されたソフトウェアをパッケージ化するための軽量で実行可能な独立したソフトウェアパッケージです。これには、特定のソフトウェアに必要なすべての内容が含まれており、コード、ランタイムライブラリ、環境変数、設定ファイルなどが含まれます。
UnionFs(ユニオンファイルシステム)#
UnionFS(ユニオンファイルシステム):Union ファイルシステム(UnionFS)は、階層的で軽量かつ高性能なファイルシステムであり、ファイルシステムの変更を一度のコミットとして層ごとに重ね合わせることをサポートします。同時に、異なるディレクトリを同じ仮想ファイルシステムにマウントすることができます(unite several directories into a single virtual filesystem)。Union ファイルシステムは Docker イメージの基盤です。イメージは階層を通じて継承でき、基礎イメージ(親イメージがない)に基づいてさまざまな具体的なアプリケーションイメージを作成できます。 特性 :同時に複数のファイルシステムをロードできますが、外部から見ると 1 つのファイルシステムしか見えません。ユニオンロードは各層のファイルシステムを重ね合わせ、最終的なファイルシステムにはすべての下層のファイルとディレクトリが含まれます。
Docker イメージをダウンロードする際に、一層一層の実体は実際にはユニオンファイルシステムの表れです。
Docker イメージのロード原理#
Docker のイメージは実際には層ごとのファイルシステムで構成されており、この階層的なファイルシステムは UnionFS です。bootfs(ブートファイルシステム)は主にブートローダーとカーネルを含み、ブートローダーは主にカーネルを起動します。Linux が起動するとき、bootfs ファイルシステムがロードされ、Docker イメージの最下層は bootfs です。この層は、典型的な Linux/Unix システムと同じで、ブートローダーとカーネルを含みます。ブートが完了すると、カーネル全体がメモリにロードされ、この時点でメモリの使用権は bootfs からカーネルに移譲され、システムは bootfs をアンマウントします。
rootfs(ルートファイルシステム)は bootfs の上にあり、典型的な Linux システムの /dev、/proc、/bin、/etc などの標準ディレクトリとファイルを含みます。rootfs はさまざまな異なるオペレーティングシステムのディストリビューション、例えば Ubuntu や CentOS などです。
通常、私たちがインストールする仮想マシンの CentOS は数 GB ですが、なぜ Docker は数百 MB なのか。
簡素化された OS の場合、rootfs は非常に小さくできます。最も基本的なコマンド、ツール、ライブラリだけを含めればよく、基盤はホストのカーネルを直接使用するため、rootfs だけを提供すればよいのです。このように、異なる Linux ディストリビューションに対して、bootfs は基本的に一致し、rootfs には違いがあるため、異なるディストリビューションは bootfs を共有できます。
層の理解#
Docker イメージをダウンロードする際に、一層一層の実体は実際には層の最も直感的な表れです(すでにダウンロードされたものは再度ダウンロードされません)。
$ docker pull redis
Using default tag: latest
latest: Pulling from library/redis
33847f680f63: Already exists
26a746039521: Pull complete
18d87da94363: Pull complete
5e118a708802: Pull complete
ecf0dbe7c357: Pull complete
46f280ba52da: Pull complete
Digest: sha256:cd0c68c5479f2db4b9e2c5fbfdb7a8acb77625322dd5b474578515422d3ddb59
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
以前の記事で言及した inspect コマンドを使用することもできます。
docker image inspect redis:latest
イメージの具体的な層情報が表示され、上記のイメージダウンロード時の 6 層に対応しています。
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4",
"sha256:dd1ebb1f5319785e34838c7332a71e5255bda9ccf61d2a0bf3bff3d2c3f4cdb4",
"sha256:11f99184504048b93dc2bdabf1999d6bc7d9d9ded54d15a5f09e36d8c571c32d",
"sha256:e461360755916af80821289b1cbc503692cf63e4e93f09b35784d9f7a819f7f2",
"sha256:45f6df6342536d948b07e9df6ad231bf17a73e5861a84fc3c9ee8a59f73d0f9f",
"sha256:262de04acb7e0165281132c876c0636c358963aa3e0b99e7fbeb8aba08c06935"
]
},
層の利点 :
最大の利点は - リソースの共有です。
例えば、複数のイメージが同じベースイメージから構築されている場合、Docker ホストはディスク上にベースイメージの 1 つだけを保存する必要があります。また、メモリ内にもベースイメージを 1 つだけロードすれば、すべてのコンテナにサービスを提供できます。そして、イメージの各層は共有可能です。
この時、誰かが質問するかもしれません:複数のコンテナが 1 つの基盤イメージを共有している場合、あるコンテナが基盤イメージの内容を変更した場合、例えば /etc のファイルが変更された場合、他のコンテナの /etc も変更されるのでしょうか? 答え:変更は単一のコンテナ内に制限されるため、変更されません。
これが、次に学ぶコンテナの Copy-on-Write 特性です。
コンテナの書き込み可能層#
コンテナが起動すると、新しい書き込み可能層がイメージの上にロードされます。この層は通常「コンテナ層」と呼ばれ、「コンテナ層」の下はすべて「イメージ層」と呼ばれます。すべての操作はコンテナ層に対して行われ、コンテナ層のみが書き込み可能で、コンテナ層の下のすべてのイメージ層は読み取り専用です。
commit イメージ#
docker commit コンテナを新しいコピーとしてコミット
以下の例で説明します。
私は以前に tomcat のイメージをダウンロードしました。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat latest 710ec5c56683 7 days ago 668MB
redis latest aa4d65e670d6 3 weeks ago 105MB
mysql latest c60d96bd2b77 3 weeks ago 514MB
centos centos7 8652b9f0cb4c 9 months ago 204MB
tomcat を起動します。
-- イメージを実行し、ポートをホストポートにマッピングします。
docker run -it -p 8080:8080 tomcat
別のコマンドを使用して現在実行中のコンテナを確認すると、tomcat が実行中です。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b294cd7074e tomcat "catalina.sh run" 29 seconds ago Up 28 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp zealous_cohen
f42ae22e4b72 centos:centos7 "/bin/bash" 3 weeks ago Up 46 hours centos-test
次に、tomcat コンテナに入ってみましょう。
docker exec -it 8b294cd7074e /bin/bash
$ docker exec -it 8b294cd7074e /bin/bash
root@8b294cd7074e:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
次に、webapp(プロジェクトファイルの場所)に入ってみると、webapp は空であることがわかります。
root@8b294cd7074e:/usr/local/tomcat# cd webapps
root@8b294cd7074e:/usr/local/tomcat/webapps# ls
root@8b294cd7074e:/usr/local/tomcat/webapps#
次に、tomcat にアクセスすると、404 が表示され、tomcat は正常に起動していますが、対応するページが見つからないことがわかります。これは webapp が空であるため、理解しやすいです。
それでは、webapp に内容のあるイメージを作成してみましょう。
webapps.dist のファイルを webapp にコピーします。
root@8b294cd7074e:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@8b294cd7074e:/usr/local/tomcat# cd webapps
root@8b294cd7074e:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
変更後、tomcat に正常にアクセスできることがわかります。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b294cd7074e tomcat "catalina.sh run" 27 minutes ago Up 27 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp zealous_cohen
この tomcat は簡単な変更を加えました。私のこの tomcat は公式のものより少し良いと思いますので、このイメージをコミットします。
$ docker commit -a="cb" -m "add init file" 8b294cd7074e newtomcat:1.0
sha256:44cf4d44be664d9704a3fc38ddef1f03fa7f113ad83f4049cced322a14dc216b
docker images を通じて新しいイメージが作成されたことが確認でき、注意深く観察すると、私たちがコミットした newtomcat は公式の tomcat よりも少し大きいことがわかります。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
newtomcat 1.0 44cf4d44be66 46 seconds ago 673MB
tomcat latest 710ec5c56683 7 days ago 668MB
redis latest aa4d65e670d6 3 weeks ago 105MB
mysql latest c60d96bd2b77 3 weeks ago 514MB
centos centos7 8652b9f0cb4c 9 months ago 204MB
今後は自分のイメージを直接使用したり、他の人に配布したりすることができます。これについては後で説明します。
この例を通じて、上記の層の考え方を振り返ることができます。newtomcat は、以前のコンテナ層で変更を加えた後に生成されたイメージであり、このイメージは仮想マシンのイメージスナップショットに似ています。
Docker のイメージについてはここまでです。今のところ、Docker は簡単に入門したと言えます。今後も Docker に関連する内容を学び続けますので、皆さんも一緒に頑張りましょう!
日々の努力は無駄にならず、最終的には海に入る。