Docker 이미지 "레이어"란 무엇입니까?
Docker를 처음 접했고 Docker 이미지 가 무엇인지 정확하게 이해하려고합니다 . Docker 이미지의 모든 단일 정의는 "layer"라는 용어를 사용하지만 layer의 의미를 정의하지는 않습니다 .
공식 Docker 문서에서 :
Docker 이미지는 Docker 컨테이너가 시작되는 읽기 전용 템플릿이라는 것을 이미 알고 있습니다. 각 이미지는 일련의 레이어로 구성됩니다. Docker는 통합 파일 시스템을 사용하여 이러한 레이어를 단일 이미지로 결합합니다. 통합 파일 시스템을 사용하면 분기라고하는 별도의 파일 시스템의 파일과 디렉토리를 투명하게 겹쳐 단일 일관성있는 파일 시스템을 만들 수 있습니다.
그래서 나는 층이 무엇인지 묻습니다. 누군가가 그들에게 몇 가지 구체적인 예를 줄 수 있습니까? 그리고이 레이어들은 어떻게 이미지를 형성하기 위해 "함께 스냅"합니까?
나는 늦을지도 모르지만 여기에 10 센트가 있습니다 (ashishjain의 답변을 보완 함).
기본적으로 레이어 또는 이미지 레이어 는 이미지 또는 중간 이미지의 변경 입니다. 사용자가 지정하는 모든 명령 ( FROM
, RUN
, COPY
당신 Dockerfile에서, 등) 따라서 새 레이어를 생성, 변화에 이전 이미지가 발생합니다. git을 사용할 때 스테이징 변경으로 생각할 수 있습니다. 파일 변경 사항을 추가 한 다음 다른 변경 사항을 추가하십시오.
다음 Dockerfile을 고려하십시오.
FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]
먼저 시작 이미지를 선택합니다 . rails:onbuild
이 레이어 에는 여러 레이어가 있습니다. 시작 이미지 위에 다른 레이어를 추가 RAILS_ENV
하고 ENV
명령으로 환경 변수 를 설정합니다 . 그런 다음 docker에게 bundle exec puma
(레일 서버를 부팅) 실행하도록 지시합니다 . 그것은 또 다른 층입니다.
레이어 개념은 이미지를 만들 때 유용합니다. 레이어는 중간 이미지이므로 Dockerfile을 변경하면 docker 는 변경된 레이어와 그 이후의 레이어 만 빌드 합니다. 이것을 레이어 캐싱이라고합니다.
docker 컨테이너 이미지는 dockerfile을 사용하여 생성됩니다 . dockerfile의 모든 줄은 레이어를 만듭니다. 다음 더미 예제를 고려하십시오.
FROM ubuntu #This has its own number of layers say "X"
MAINTAINER FOO #This is one layer
RUN mkdir /tmp/foo #This is one layer
RUN apt-get install vim #This is one layer
그러면 총 레이어 수가 X + 3 인 최종 이미지가 생성됩니다.
그들은 예를 들어 나에게 가장 의미가 있습니다 ...
docker diff로 자신의 빌드 레이어 검사
독창적 인 Dockerfile 예제를 보자.
FROM busybox
RUN mkdir /data
# imagine this is downloading source code
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN chmod -R 0777 /data
# imagine this is compiling the app
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN chmod -R 0777 /data
# and now this cleans up that downloaded source code
RUN rm /data/one
CMD ls -alh /data
이러한 각 dd
명령은 1M 파일을 디스크에 출력합니다. 임시 컨테이너를 저장하기 위해 추가 플래그를 사용하여 이미지를 빌드 할 수 있습니다.
docker image build --rm=false .
출력에서 실행중인 각 명령이 자동 컨테이너 대신 삭제되는 임시 컨테이너에서 발생하는 것을 볼 수 있습니다.
...
Step 2/7 : RUN mkdir /data
---> Running in 04c5fa1360b0
---> 9b4368667b8c
Step 3/7 : RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
---> Running in f1b72db3bfaa
1024+0 records in
1024+0 records out
1048576 bytes (1.0MB) copied, 0.006002 seconds, 166.6MB/s
---> ea2506fc6e11
docker diff
각 컨테이너 ID에서 를 실행하면 해당 컨테이너에서 어떤 파일이 생성되었는지 확인할 수 있습니다.
$ docker diff 04c5fa1360b0 # mkdir /data
A /data
$ docker diff f1b72db3bfaa # dd if=/dev/zero bs=1024 count=1024 of=/data/one
C /data
A /data/one
$ docker diff 81c607555a7d # chmod -R 0777 /data
C /data
C /data/one
$ docker diff 1bd249e1a47b # dd if=/dev/zero bs=1024 count=1024 of=/data/two
C /data
A /data/two
$ docker diff 038bd2bc5aea # chmod -R 0777 /data
C /data/one
C /data/two
$ docker diff 504c6e9b6637 # rm /data/one
C /data
D /data/one
Each line prefixed with an A
is adding the file, the C
indicates a change to an existing file, and the D
indicates a delete.
Here's the TL;DR part
Each of these container filesystem diffs above goes into one "layer" that gets assembled when you run the image as a container. The entire file is in each layer when there's an add or change, so each of those chmod
commands, despite just changing a permission bit, results in the entire file being copied into the next layer. The deleted /data/one file is still in the previous layers, 3 times in fact, and will be copied over the network and stored on disk when you pull the image.
Examining existing images
You can see the commands that goes into creating the layers of an existing image with the docker history
command. You can also run a docker image inspect
on an image and see the list of layers under the RootFS section.
Here's the history for the above image:
IMAGE CREATED CREATED BY SIZE COMMENT
a81cfb93008c 4 seconds ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ls -… 0B
f36265598aef 5 seconds ago /bin/sh -c rm /data/one 0B
c79aff033b1c 7 seconds ago /bin/sh -c chmod -R 0777 /data 2.1MB
b821dfe9ea38 10 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
a5602b8e8c69 13 seconds ago /bin/sh -c chmod -R 0777 /data 1.05MB
08ec3c707b11 15 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
ed27832cb6c7 18 seconds ago /bin/sh -c mkdir /data 0B
22c2dd5ee85d 2 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:2a4c44bdcb743a52f… 1.16MB
The newest layers are listed on top. Of note, there are two layers at the bottom that are fairly old. They come from the busybox image itself. When you build one image, you inherit all the layers of the image you specify in the FROM
line. There are also layers being added for changes to the image meta-data, like the CMD
line. They barely take up any space and are more for record keeping of what settings apply to the image you are running.
Why layers?
The layers have a couple advantages. First, they are immutable. Once created, that layer identified by a sha256 hash will never change. That immutability allows images to safely build and fork off of each other. If two dockerfiles have the same initial set of lines, and are built on the same server, they will share the same set of initial layers, saving disk space. That also means if you rebuild an image, with just the last few lines of the Dockerfile experiencing changes, only those layers need to be rebuilt and the rest can be reused from the layer cache. This can make a rebuild of docker images very fast.
Inside a container, you see the image filesystem, but that filesystem is not copied. On top of those image layers, the container mounts it's own read-write filesystem layer. Every read of a file goes down through the layers until it hits a layer that has marked the file for deletion, has a copy of the file in that layer, or the read runs out of layers to search through. Every write makes a modification in the container specific read-write layer.
Reducing layer bloat
One downside of the layers is building images that duplicate files or ship files that are deleted in a later layer. The solution is often to merge multiple commands into a single RUN
command. Particularly when you are modifying existing files or deleting files, you want those steps to run in the same command where they were first created. A rewrite of the above Dockerfile would look like:
FROM busybox
RUN mkdir /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/one \
&& chmod -R 0777 /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/two \
&& chmod -R 0777 /data \
&& rm /data/one
CMD ls -alh /data
And if you compare the resulting images:
- busybox: ~1MB
- first image: ~6MB
- second image: ~2MB
Just by merging together some lines in the contrived example, we got the same resulting content in our image, and shrunk our image from 5MB to just the 1MB file that you see in the final image.
Since Docker v1.10, with introduction of the content addressable storage, the notion of 'layer' became quite different. Layers have no notion of an image or belonging to an image, they become merely collections of files and directories that can be shared across images. Layers and images became separated.
For example, on a locally built image from a base image, let's say, ubuntu:14.04
, the docker history
command yields the image chain, but some of the image IDs will be shown as 'missing' because the build history is no longer loaded. And the layers that compose these images can be found via
docker inspect <image_id> | jq -r '.[].RootFS'
The layer content is stored at /var/lib/docker/aufs/diff
if the storage driver selection is aufs
. But the layers are named with a randomly generated cache ID, it seems the link between a layer and its cache ID is only known to Docker Engine for security reasons. I am still looking for a way to find out
- The corresponding relation between an image and its composing layer(s)
- Actual location and size of a layer on the disk
This blog provided much insight.
Per Docker's image spec
Images are composed of layers. Each layer is a set of filesystem changes. Layers do not have configuration metadata such as environment variables or default arguments - these are properties of the image as a whole rather than any particular layer.
So, essentially, layer is just a set of changes made to the filesystem.
I think the official document gives a pretty detailed explanation: https://docs.docker.com/engine/userguide/storagedriver/imagesandcontainers/.
(source: docker.com)
An image consists of many layers which usually are generated from Dockerfile, each line in Dockerfile will create a new layer, and the result is an image, which is denoted by the form repo:tag
, like ubuntu:15.04
.
For more information, please consider reading the official docs above.
Thank you @David Castillo for the useful information. I think the layer is some binary change or instruction of a image that can be done or undone easily. They are done step by step that is same as a layer on a layer, so we called "layer".
For more information you can see the "docker history" like this:
docker images --tree Warning: '--tree' is deprecated, it will be removed soon. See usage. └─511136ea3c5a Virtual Size: 0 B Tags: scratch:latest └─59e359cb35ef Virtual Size: 85.18 MB └─e8d37d9e3476 Virtual Size: 85.18 MB Tags: debian:wheezy └─c58b36b8f285 Virtual Size: 85.18 MB └─90ea6e05b074 Virtual Size: 118.6 MB └─5dc74cffc471 Virtual Size: 118.6 MB Tags: vim:latest
My personal understanding is that we can compare docker layer to github commit. For your base image(your fresh master repo), you make several commits, every commit is changing your master status, it's the same in docker, every layer is doing some operation based on previous intermediate layer. And then, this layer become a new intermediate layer to the next layer.
참고URL : https://stackoverflow.com/questions/31222377/what-are-docker-image-layers
'development' 카테고리의 다른 글
ASP.NET Core Dependency Injection 오류 : 정품 인증을 시도하는 동안 형식에 대한 서비스를 확인할 수 없습니다 (0) | 2020.06.29 |
---|---|
파이썬에서의 부정 (0) | 2020.06.28 |
500 내부 서버 오류가 발생하지 않고 PHP가 오류를 표시하도록하려면 어떻게해야합니까 (0) | 2020.06.28 |
이벤트가 사람에 의해 트리거되는지 확인 (0) | 2020.06.28 |
자바 스크립트 정규식-대안을 보시겠습니까? (0) | 2020.06.28 |