鏡像簡介
它是一個創(chuàng)建Docker 容器的只讀模板,通過DockerFile可以自定義鏡像。它也是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(如匿名卷、環(huán)境變量、用戶等)。鏡像不包含任何動態(tài)數據,其內容在構建之后也不會被改變。
Dockerfile簡介
Dockerfile是一個文本文件,其內包含了創(chuàng)建鏡像(image)所需要的所有指令(Instruction)。使用docker build有序的執(zhí)行文件中每一條指令,每一條指令構建一層,構建的層通過UnionFS組合起來形成一個只讀的鏡像。
UnionFS簡介
它是一個linux和FreeBSD的文件系統服務。通過它可以將多個不同文件系統(含文件或者目錄)組合形成一個虛擬的文件系統。比如: test1和test2兩個文件夾,各個文件夾下有各自的文件。
test1/n
test1/b
test2/l
test2/f
通過UnionFS虛擬成test文件夾之后,表面上會變成如下樣子。
test/n
test/b
test/l
test/f
它有一個很重要的特性:Copy on write
比如:把changed、test1、test2三個文件夾虛擬組合成test文件夾。虛擬組合時指定changed讀寫權限、test1與test2只讀權限。
├── changed
├── test
│ ├── n
│ ├── b
│ ├── l
│ └── f
├── test1
│ ├── n
│ └── b
└── test2
├── l
└── f
如果對 test/f 文件進行修改,將會復制 f 文件到具備讀寫權限的changed文件夾,而原始的 test2/f 不會更新。
├── changed
│ └── f #復制創(chuàng)建
├── test
│ ├── n
│ ├── b
│ ├── l
│ └── f #更新
├── test1
│ ├── n
│ └── b
└── test2
├── l
└── f #不更新
鏡像與容器關系
使用UnionFS與Copy on write特性之后,容器與鏡像的關系如下:
鏡像分層與容器層關系
只讀鏡像層的數據更新時,就會復制數據到可讀寫操作的容器層。這個復制處理的具體操作依賴系統選擇的Storage Driver。Storage Driver列表:
- overlay2, overlay
- aufs
- btrfs
- devicemApper
- vfs
- zfs
由上可以知道,由于共用了只讀鏡像層,從而縮小了容器的大小,加快了啟動速度。
鏡像內部分層結構
舉個例子看看鏡像里頭分層情況。第一步:創(chuàng)建DockerFile,內容如下
FROM centos:7
執(zhí)行docker build:
D:docker0-basic>docker build -t centos7 .
Sending build context to Docker daemon 2.048kB
Step 1/1 : FROM centos:7
7: Pulling from library/centos
ab5ef0e58194: Pull complete Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:7
---> 5e35e350aded
Successfully built 5e35e350aded
Successfully tagged centos7:latest
SECURITY WARNING: You are building a Docker image from windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
查看鏡像分層構造:
D:docker0-basic>docker history centos7
IMAGE CREATED CREATED BY SIZE COMMENT
5e35e350aded 5 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 5 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 5 months ago /bin/sh -c #(nop) ADD file:45a381049c52b5664… 203MB
第二步:修改DockerFile內容如下。
FROM centos:7
RUN echo "Hello world" > /tmp/newfile
執(zhí)行docker build:
D:docker0-basic>docker build -t centos7 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM centos:7
---> 5e35e350aded
Step 2/2 : RUN echo "Hello world" > /tmp/newfile
---> Running in 8bd61ed2d5e7
Removing intermediate container 8bd61ed2d5e7
---> cdbbf869ca90
Successfully built cdbbf869ca90
Successfully tagged centos7:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
查看鏡像分層構造:
D:docker0-basic>docker history centos7
IMAGE CREATED CREATED BY SIZE COMMENT
cdbbf869ca90 About a minute ago /bin/sh -c echo "Hello world" > /tmp/newfile 12B
5e35e350aded 5 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 5 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 5 months ago /bin/sh -c #(nop) ADD file:45a381049c52b5664… 203MB
對比兩次的分層結構,就可以知道第二步只在第一步的基礎上加了一個12B的分層。從而可以推導出:Docker 為了加速鏡像構建、重復利用資源,會利用這些中間層鏡像。
鏡像優(yōu)化
知道鏡像內部分層之后,我們就可以做一些處理來優(yōu)化我們的鏡像。
- 由于鏡像每層是只讀的,構建之后無法改變。所以在構建這一層時創(chuàng)建的臨時文件,也需要在這一層進行刪除,后續(xù)層中做的刪除只是表面效果。
優(yōu)化前:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
優(yōu)化后:
FROM ubuntu:18.04
RUN apt-get update && apt-get clean && rm -rf /var/lib/apt/lists/*
- 對于已經沒有任何依賴的中間層鏡像進行刪除。