1 容器镜像概述
容器镜像(Image)所承载的是封装了应用程序及其所有软件依赖的二进制数据。
容器镜像是可执行的软件包,可以单独运行;该软件包对所处的运行时环境具有良定(Well
Defined)的假定。
容器镜像与容器的关系,类似于可执行文件与进程的关系。也就是说,可以将容器理解为容器镜像的动态形式,容器镜像则容器的静态形式。一般地,实现某特定业务功能的容器镜像都是在某一个基础镜像的基础上构建的。
image-20250117211509892
Docker
容器镜像是符合OCI
规范的,而Containerd
支持所有符合OCI
规范的容器镜像。但Containerd
本身附带的ctr
工具并不提供创建容器镜像的能力,但Containerd
的子项目
nerdctl
,它兼容 docker cli
,可以像
docker
命令一样来管理本地的镜像和容器。笔者目前使用的容器场景与云原生环境下,暂时还是以Docker
命令管理镜像与容器居多,但正在往使用Containerd
及其子项目nerdctl
转移中。
容器镜像实际上是由一层一层的系统文件组成,这种层级的文件系统被称为UnionFS(
Union file system
统一文件系统),镜像可以基于Dockerfile构建,Dockerfile是一个描述文件,里面包含了若干条密令,每条命令都会对基础文件系统创建新的层次结构。docker build与nerdctl
及buildctl
命令都可以使用Dockerfile文件来构建容器镜像。
2 容器镜像的获取与生成方法
• 方法一:在DockerHub直接下载
DockerHub是docker容器镜像的官网上传与下载网站(当然全球还有很多公司如阿里云提供了公开的容器镜像可供下载与使用),下载下来的容器镜像可以直接用来创建容器,也可以作为自定义容器镜像的基础镜像。
• 方法二:把操作系统中文件系统打包为容器镜像
利用Docker容器引擎的功能,可以将物理机或虚拟机上正在运行的操作系统的全部或部分内容打包成一个容器镜像。
• 方法三:把正在运行的容器打包为容器镜像
类似地,利用Docker容器引擎的功能可以将一个容器保存为一个容器镜像。这也可以更形象具体地将容器镜像理解为容器的静止状态。
•
方法四:通过Dockerfile实现容器镜像的自定义与构建
这是开发与生产环境中经常用到一种构建容器的方式。
容器镜像获取后,可以保存到本地的registry或自己搭建的harbor镜像仓库中,以便后续使用。
2.1 方法一:在DockerHub直接下载
访问DockerHub官网: https://hub.docker.com/ 。
image-20250117213321848
(1)可以看到DockerHub可以注册登录,登录后可以上传镜像到用户空间内。这些上传的镜像可以设置为public,这样其他人都可以使用它。与此相应地,镜像设置为private时,其他人则是不可见的。
(2)可以看到DockerHub上的容器镜像支持多种不同构架,同一个镜像不同的构架在拉取时,使用不同的Digest
(3)同时,
DockerHub已经检测并告诉用户,当前镜像有多少个不同级别的漏洞或安全隐患,并可以查看这些漏洞的详情。对容器镜像安全性有较高要求时要注意
(4)下载镜像。
image-20250117213552141
比如我们要下载nginx:stable-perl
镜像在arm64构架平台上对应的镜像文件时,有如下两种方法:
已有Docker服务运行在一个arm64构架平台上
此时可以直接docker pull nginx:stable-perl
拉取此镜像,docker服务会拉取一个跟自己构架一样的nginx:stable-perl
镜像
已有Docker服务运行在一个非arm64构架平台上,比如常见的x86_64构架的windows电脑或一个amd64构架的Linux服务器上
此时并不能直接使用docker pull nginx:stable-perl
,要是要像上图中展示的一样,单击此构架镜像对应的Digest
即61eaeb2c1479
,跳转到如下图界面。然后复制下图中Index
digest对应的值,如下是sha256:746bca4640fce6b18814e47162c26da63f185a2b4a1bbc5fd137cbf9bc8293e8
,然后组合成命令如下命令拉取nginx:stable-perl镜像在arm64构架平台上对应的镜像文件:
1 docker pull nginx@sha256:746bca4640fce6b18814e47162c26da63f185a2b4a1bbc5fd137cbf9bc8293e8
image-20250117213752425
可以看到DockerHub可以注册登录,登录后可以上传镜像到用户空间内。这些上传的镜像可以设置为public,这样其他人都可以使用它。
可以看到DockerHub上的容器镜像支持多种不同构架,同一个镜像不同的构架在拉取时,使用不同的Digest。
同时,还需要DockerHub已经检测并告诉用户,当前有多少个不同级别的漏洞或安全隐患,并可以查看这些漏洞的详情。对容器镜像安全性有较高要求时要注意。
2.2
方法二:把操作系统中文件系统打包为容器镜像
1 2 3 4 5 6 7 8 # 打包镜像(其中--exclude参数指定不打包的目录,可以指定多次、取并集) tar --numeric-owner --exclude=/proc --exclude=/sys -cvf centos7u6.tar /# 导入镜像到本地 docker import centos7u6.tar centos7u6:v1# 使用此镜像创建并进入容器 docker run -it centos7u6:v1 bash
image-20250117220842655
2.3
方法三:把容器打包为容器镜像
现有一个容器test01
,创建一个新文件/opt/test01.txt
,并在其中写入字符串内容container test01
。
1 2 3 4 5 6 7 8 # 查看所有容器 docker ps -a# 进入容器,打开一个交互式命令虚拟终端 docker exec -it test01 bash root@271b105e357f:/# echo "container test01" > /opt/test01.txt root@271b105e357f:/# cat /opt/test01.txt# 使用组合键“ctrl+p+q”退出容器
image-20250117214428285
1 2 3 # 将容器保存为镜像(容器处于Up或Exited状态都无所谓) root@ubuntu20:~# docker commit -a "a good man" -m "测试" test01 ubuntu:test01 root@ubuntu20:~# docker images | grep ubuntu
image-20250117214858751
1 2 3 4 5 # 使用上述打包后的镜像创建一个新的容器test001,可以看到容器中的/opt/test01.txt 文件内容跟前面写入的一样 root@ubuntu20:~# docker run -it --name test001 ubuntu:test01 bash root@66a8e5be6b13:/# ls -al /opt/ root@66a8e5be6b13:/# cat /opt/test01.txt root@ubuntu20:~# docker ps -a | egrep "NAME|test001"
image-20250117214936732
2.4
方法四:通过Dockerfile实现容器镜像的自定义与构建
1 2 3 4 5 6 7 8 9 10 11 12 13 root@ubuntu20:/opt/manual-for-ppt# cat Dockerfile FROM centos:centos7 MAINTAINER "a good man" RUN yum makecache && yum -y install wget RUN wget -O /etc/yum.repos.d/epel.repo \ http://mirrors.aliyun.com/repo/epel-7.repo RUN yum -y install nginx RUN echo "nginx index page!" > \ /usr/share/nginx/html/index.html RUN echo "daemon off;" >> /etc/nginx/nginx.conf EXPOSE 80 CMD /usr/sbin/nginx
相关指令的意义如下。
image-20250117215021189
1 2 3 4 5 6 7 8 9 10 11 12 上述Dockerfile文件中有一个指令“MAINTAINER”在上表中未列出,它指定的是镜像的维护人员信息一般也就是镜像作者# 如果本地没有镜像“centos:centos7”,建议先执行如下命令将此镜像拉取下来,减少dcoker build阶段的时间 docker pull centos:centos7# 接下来就可以构建镜像了,编译镜像的命令如下 # 其中build是docker的子命令 # ./ 表示编译镜像时宿主的工作目录 # -f参数指定要使用的Dockerfile文件。如果有另外一个nginx.Dockerfile则使用这个名字 # -t 参数指定编译完成生成的镜像的名称与标签 root@ubuntu20:/opt/manual-for-ppt# docker build ./ -f Dockerfile -t nginx:v001# 从下图中可以看到,本地docker环境中有了一个镜像 nginx:v001
image-20250117215154332
1 2 3 # 查看镜像信息 root@ubuntu20:/opt/manual-for-ppt# docker inspect nginx:v001 | grep -i "good"# 可以看到Dockerfile文件中MAINTAINER指令指定的值就是镜像的Authtor属性值。
image-20250117215246362
1 2 3 4 5 6 # 利用上述生成的镜像创建一个启动nginx进程的容器 # 以下命令指定容器名称为nginx01,-d表示以后台模式运行,-p做宿主机与容器端口映射 # 因为制作容器nginx:v001时,已经指定” CMD /usr/sbin/nginx”表示容器启动后就会自动执行/usr/sbin/nginx,不需要再在docker run命令后面再添加指令参数,添加指令参数如/bin/bash将会替换“/usr/sbin/nginx”,则此容器将不会自动启动nginx相关进程 docker run -d --name nginx01 -p 8080:80 nginx:v001 docker ps -a | egrep "NAME|nginx01" curl 127.0.0.1:8080
image-20250117215313476
此时,比如当前宿主机的ip是10.10.0.51,自己笔记本电脑上或其他有桌面的操作系统通过浏览器访问
http://10.10.0.51:8080 ,也可以访问上述nginx主页。
关于Dockerfile更详细的用法,可以参考 官网文档Dockerfile
reference 或 菜鸟教程Dockerfile文档
3 docker save与docker load
命令
docker save
命令的功能是将一个容器镜像保存为一个本地文件(相当于被持久化保存了),docker load
命令将docker save
生成的本地镜像文件导入到本地docker环境中。
1 2 # 将容器镜像保存为本地文件nginx-v001.tar root@ubuntu20:~# docker save -o nginx-v001.tar nginx:v001
image-20250117215708133
image-20250117215716903
1 2 # 可以将文件传输到其他安装了docker容器引擎的服务器上,再使用docker load命令导入即是一个可用的容器镜像 # 比如传输此文件到另外一个服务器controller01上,然后导入并使用
1 2 3 root@controller01:~# docker load -i nginx-v001.tar root@controller01:~# docker run -d --name nginx-test -p 8085:80 nginx:v001 root@controller01:~# curl 127.0.0.1:8085
image-20250117215853043
4 docker export与docker
import命令
docker export
命令,类似于docker save
,但前者是将一个容器保存成一个文件,后者是将一个容器镜像保存成一个文件。
docker import
命令,有点类似于docker load
,将docker export
保存的文件导入成docker
镜像。
注意 :docker import
与docker export
是一对的,它们成对使用。docker import
不能跟docker save
混用。
1 2 # 将centos01容器打包保存成镜像文件centos-v0.2.tar到本地 root@kafka:/opt# docker export -o centos-v0.2.tar centos01
image-20250117220238284
1 2 # docker import时,强烈建议设定好镜像名与标签(否则就像下图最底行一样,镜像名与标签都没有,只能通过镜像id 来引用) root@kafka:/opt/msb_study# docker import centos-v0.2.tar centos:v0.2
image-20250117220654638