Docker每日一阅(4):镜像层
文章目录
0 回顾
- 运行交互式的容器(
docker container run ... -i -t
) - 后台运行容器(
docker container run ... -d
) - 查看运行容器的日志(
docker container logs [container id]
) - 关闭正在运行的容器(
docker container stop [container id]
) - 创建镜像:
docker container commit [container id]
- Dockerfile创建镜像(
docker image build ...
)
0 任务描述
- Docker镜像层的概念
docker image inspect [image id]
- Dockfile的更多例子
1 Docker镜像层的概念
上一章节,我们学习了如何使用Dockerfile创建镜像。
现在,让我们来看一下,当我们在terminal中输入了docker image build -t python-cus:v1 .
之后,terminal打印出来的日志:
[+] Building 15.0s (11/11) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 315B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/python:3.7-slim 14.6s
=> [auth] library/python:pull token for registry-1.docker.io 0.0s
=> [1/5] FROM docker.io/library/python:3.7-slim@sha256:aeeccd46a37f57b9f28aa033982a9c51f44 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 1.00kB 0.0s
=> CACHED [2/5] RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources 0.0s
=> CACHED [3/5] RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list 0.0s
=> [4/5] COPY . /app 0.1s
=> [5/5] WORKDIR /app 0.1s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:55d1547e5aa75dd0ad227b963c704b5d9c788fce375cea6b3bb8830df52f801 0.0s
=> => naming to docker.io/library/python-cus:v1 0.0s
我们看到,整个流程非常清晰,从步骤[1/5]
导入FROM docker.io/library/python:3.7-slim
,到步骤[2/5]
以及[3/5]
更新阿里源,再到[4/5]
和[2/5]
的copy文件,以及默认进入镜像后的路径,最后导出镜像,导出层,写镜像,以及命名镜像。
现在,我们打开main.py
文件,在下面多加一行,变成如下所示:
print("Hello my friend")
print("Hello again.")
当我们在terminal中输入了docker image build -t python-cus:v2 .
之后,terminal打印出来的日志:
[+] Building 4.7s (11/11) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/python:3.7-slim 4.4s
=> [auth] library/python:pull token for registry-1.docker.io 0.0s
=> [1/5] FROM docker.io/library/python:3.7-slim@sha256:aeeccd46a37f57b9f28aa033982a9c51f44 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 3.25kB 0.0s
=> CACHED [2/5] RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources 0.0s
=> CACHED [3/5] RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list 0.0s
=> [4/5] COPY . /app 0.0s
=> [5/5] WORKDIR /app 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:71b1c0a5e3b44c11c122ff4025e9defe9c8a44e13460c17ec577b8e4959d333 0.0s
=> => naming to docker.io/library/python-cus:v2 0.0s
注意这次构建步骤中的一些有趣之处。在输出中,它经历了相同的五个步骤,但请注意,在某些步骤中,docker使用了缓存(cache
),比如步骤[2/5]
以及[3/5]
。
Docker意识到,我们在早期的镜像构建中已经构建了其中一些层,而且由于这些层中没有任何更改,所以它可以简单地使用该层的缓存版本,而不是再次下载代码并运行这些步骤。Docker的层管理对于IT团队在修补系统、更新或升级到最新版本的代码或对应用程序进行配置更改时非常有用。
Docker层的概念很重要,在之后的文章中,我们很可能又回过头来对层的解读更进一步。
2 docker image inspection
通过docker image inspect [image id]
,我们可以对特定镜像有非常细致地解读。比如,我们通过docker image list
找到了python-cus:v2
这个镜像的id:71b1c0a5e3b4
,然后在terminal中输入:docker image inspect 71b1c0a5e3b4
,terminal返回如下非常多的信息:
[
{
"Id": "sha256:71b1c0a5e3b44c11c122ff4025e9defe9c8a44e13460c17ec577b8e4959d333c",
"RepoTags": [
"python-cus:v2"
],
"RepoDigests": [],
"Parent": "",
"Comment": "buildkit.dockerfile.v0",
"Created": "2022-03-11T11:28:40.5492889Z",
"Container": "",
"ContainerConfig": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": null,
"Cmd": null,
"Image": "",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": null
},
"DockerVersion": "",
"Author": "",
"Config": {
...
},
"Architecture": "amd64",
"Os": "linux",
"Size": 138032881,
"VirtualSize": 138032881,
"GraphDriver": {
...
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:1401df2b50d5de5a743b7bac3238ef3b7ce905ae39f54707b0ebb8eda3ab10bc",
"sha256:7fce09c1d950fb8b08a2492bb088aeb0c5e00327dd4ab26310b00e9befe55c72",
"sha256:1daec571e2cb5145f39e53f45ff9b3219e5b8b69fc46c28fe8f8c10a97cd31aa",
"sha256:9e7155bb7167eccc6f5bd18da1e32bb87a309f50284f9105212c9b629baadbb0",
"sha256:5346dd72bba468a6c3014837bbbf970c093cd9337386fdf73fcd13d00e7096b5",
"sha256:317af9392e5dab06a71711713b8681352350e6f5c55b05e9599d41ef1a7891cb",
"sha256:c3de2f0457db39b3bc5384bd60a607c15fc4c6a3fb819609f9248a9ead9ffb45",
"sha256:8244fd26f92cecc4178591e73f3b2f791c105a3508d7a5a9be41e2f57e8855a9",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
]
},
"Metadata": {
"LastTagTime": "2022-03-11T11:28:40.6211519Z"
}
}
]
当然,这只是一个开始,我们目前浅尝即止。
3 Dockerfile的更多例子
这里,我们巩固并细化一下上一个章节关于Dockerfile的认知。这里举几个例子:
3.1 案例1:MAINTAINER的使用
#HTTP web Image
# define base image path
FROM centos
# Provide author name
MAINTAINER oc@gmail.com
RUN yum install –y httpd
CMD [“echo”, ” Web Image created”]
**MAINTAINER:**指明镜像维护者及其联系方式;
根据这个dockerfile,它将从docker repo中提取最新的centos镜像作为基础镜像,下载完成后,它将运行HTTP包并运行命令以显示Web Image created
。
3.2 案例2:PORT的使用
FROM centos
RUN yum install httpd -y
COPY index.html /var/www/html/
CMD [“/usr/sbin/httpd”,” -D”,” FOREGROUND”]
EXPOSE 80
**EXPOSE:**声明容器运行的服务端口。
centos镜像从docker repo下载,安装httpd包,复制index.html
到镜像/var/www/html/
路径下。最后运行httpd服务,并公开端口80以访问容器外部的web应用程序http://x.x.x.x:80。
3.3 案例2:VOLUME的使用
# base image set to centos
FROM centos
# copy the Mongo repository from host to docker image
COPY mongo.repo /etc/yum.repos.d/
# Update the yum repository
RUN yum update all
# Install MongoDB package
RUN yum install MongoDB-org -y
# mount volume
VOLUME [“/mnt/mongo_storage”, “/data”]
# create a directory for MongoDB
RUN mkdir -p /data/MongoDB
# Expose port
EXPOSE 27017
# (MongoDB)Port to execute the entrypoint
CMD ["--port 27017"]
# Set default container command
ENTRYPOINT usr/bin/mongod
**VOLUME:**容器数据卷,指定容器挂载点到宿主机自动生成的目录或者其他容器(数据保存和持久化工作,但是一般不会在 Dockerfile 中用到,更常见的还是命令 docker run 的时候指定 -v 数据卷。);
**ENTRYPOINT:**指定一个容器启动时要运行的命令,用法类似于CMD,只是有由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序;
上面的dockerfile是在centos映像上安装MongoDB,并提供从主机到容器的外部卷以及暴露端口。