1、什么是镜像
- Docker镜像是用于创建容器的只读模板,它包含文件系统。
- 一个Docker镜像可以包括一个应用程序以及能够运行它的基本操作系统环境。
-
镜像是创建容器的基础,通过版本管理和联合文件系统,Docker提供了一套十分简单的机制来创建镜像和更新现有的镜像。
2、镜像的基本信息
使用docker images命令可以列出本机主机上的镜像:
[root@docker-a ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ca2b0f26964c 7 weeks ago 77.9MB
hello-world latest d2c94e258dcb 11 months ago 13.3kB
REPOSITORY列表示镜像仓库,TAG列表示镜像的标签,IMAGE ID列表示镜像ID,CREATED列表示镜像创建时间,SIZE列表示镜像大小。
镜像ID是镜像的唯一标识,采用UUID形式表示,可以在docker images命令加上--no-trunc以显式完整的镜像ID
# 例如查看Ubuntu镜像的完整输出
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest sha256:ca2b0f26964cf2e80ba3e084d5983dab293fdb87485dc6445f3f7bbfc89d7459 7 weeks ago 77.9MB
# 镜像ID是镜像的摘要值(Digest),是由哈希函数sha256对镜像配置文件进行计算而得来的,只是引用镜像时不需要使用“sha256”前缀。实际操作中,通常使用前12个字符。
# 镜像的摘要值还可以通过--digests选项显示
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
ubuntu latest sha256:77906da86b60585ce12215807090eb327e7386c8fafb5402369e421f44eff17e ca2b0f26964c 7 weeks ago 77.9MB
总之,镜像可以通过镜像ID、镜像名称(包括标签)或者镜像摘要值来表示或引用。
3、镜像描述文件Dockerfile
Dockerfile是一个文本文件,包含了要构建镜像的所有命令。Docker通过Dockerfile中的指令自动构建镜像。
FROM scratch # 定义所用基础镜像,scratch表示空白镜像
COPY hello / # 将文件hello复制到镜像的根目录
CMD ["/hello"] # 通过该镜像启动容器时执行/hello这个可执行文件
对Dockerfile文件执行build命令可以构建镜像。
4、基础镜像
一个镜像的父镜像是指该镜像的Dockerfile文件中由FROM指定的镜像。所有后续指令都应用到这个父镜像中。
未提供FROM指令,或提供FROM scratch指令的Dockerfile所构建的镜像被称为基础镜像。
5、基于联合文件系统的镜像分层
6、基于Dockerfile文件的镜像分层
推荐Docker选择Dockerfile文件逐层构建镜像。大多数Docker镜像都是在其他镜像的基础上逐层建立起来的。采用这种方式,每一层都由镜像的Dockerfile指令所决定。除了最后一层,每层都是可读的。
7、Docker镜像操作命令
docker image 子命令 | docker子命令 | 功能 |
---|---|---|
docker image build | docker build | 从Dockerfile构建镜像 |
docker image history | docker history | 显示镜像的历史记录 |
docker image import | docker import | 从tarball文件导入内容以及穿那个键文件系统镜像 |
docker image inspect | docker inspect | 显示一个或多个镜像的详细信息 |
docker image load | docker load | 从tar档案文件或STDIN装载镜像 |
docker image ls | docker images | 输出镜像列表 |
docker image prune | 无 | 删除从未使用的镜像 |
docker image pull | docker pull | 从注册服务器拉取镜像或镜像仓库 |
docker image push | docker push | 将镜像或镜像仓库推送到注册服务器 |
docker image rm | docker rmi | 删除一个或多个镜像 |
docker image save | docker save | 将一个或多个镜像保存到tar存档(默认传输到STDOUT) |
docker image tag | docker tag | 为指向源镜像的目标镜像添加一个名称 |
8、操作
8.1、拉取镜像
若使用一个不存在的镜像,则Docker会自动下载这个镜像。
[root@docker-a~]# docker pull ubuntu:14.04
14.04: Pulling from library/ubuntu
2e6e20c8e2e6: Pull complete
0551a797c01d: Pull complete
512123a864da: Pull complete
Digest: sha256:64483f3496c1373bfd55348e88694d1c4d0c9b660dee6bfef5e12f43b9933b30
Status: Downloaded newer image for ubuntu:14.04
docker.io/library/ubuntu:14.04
8.2、显示本地的镜像列表
docker images [选项][仓库[:标签]]
# 不带任何选项或参数则会列出全部镜像,使用仓库、标签作为参数,将列出指定的镜像。
# -f选项可以通过dangline的布尔值列出无标签的镜像
docker images -f dangling=true
# -f选项还可以使用before或since过滤出指定镜像之前或之后创建的镜像
-f before=(<镜像名>[:标签]|<镜像ID>|<镜像DIGEST>)
-f since=(<镜像名>[:标签]|<镜像ID>|<镜像DIGEST>)
# 删除无标签的所有镜像
docker rmi $(docker images -f dangling=true -q)
8.3、设置镜像标签
每个镜像仓库可以有多个标签,而多个标签可能对应的是同一个镜像。标签常用于表述镜像的版本信息。使用docker tag命令为镜像添加一个新的标签,也就是给镜像命名,这实际上是为指向源镜像的目标镜像添加一个名称
docker tag 源镜像[:标签] 目标镜像[:标签]
一个镜像名称由以斜杠分隔的名称组件组成,名称组件通常包括命名空间和仓库名称,如centos/httpd-24-centos7。一个镜像可以有多个名称,相当于有多个别名。但无论采用何种方式保存和分发镜像,首先都要给镜像设置标签(重命名),这对镜像的推送特别重要。
# 示例
# 为由镜像ID标识的镜像加上标签
docker tag ca2b0f26964c dedora/httpd:version1.0
# 为由仓库名称标识的镜像加上标签
docker tag httpd fedora:httpd:version1.0
# 为由仓库名称和镜像ID组合标识的镜像加上标签
docker tag httpd:test fedora/httpd:version1.0
# 如果镜像推送的目的注册服务器不是默认的Docker公开注册中心,则为该镜像设置的标签心必须指定一个注册服务器的主机名(可能包含端口)
docker tag ca2b0f26964c myregistryhost:5000/defora/httpd:version1.0
8.4、查看镜像详细信息
使用docker inspect命令查看Docker对象(镜像、容器、任务)的详细信息。当只需要特定信息时,使用-f(--format)选项指定。
# 获取ubuntu镜像的体系结构
[root@docker-a ~]# docker inspect --format='{{.Architecture}}' ubuntu
amd64
#通过JSON格式的RootFS子节获取镜像的根文件系统信息
[root@docker-a ~]# docker inspect --format='{{json .RootFS}}' ubuntu
{"Type":"layers","Layers":["sha256:5498e8c22f6996f25ef193ee58617d5b37e2a96decf22e72de13c3b34e147591"]}
8.5、查看镜像的构建历史
使用docker history命令可以查看镜像的构建历史,也就是Dockerfile的执行过程。
# 查看ubuntu镜像的历史信息
[root@docker-a~]# docker history ubuntu
IMAGE CREATED CREATED BY SIZE
ca2b0f26964c 7 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:21c2e8d95909bec6f… 77.9MB
<missing> 7 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B
<missing> 7 weeks ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ARG RELEASE 0B
构建历史也反映了其层次,上述共有5层,每一层的构建操作命令都可以通过CREATED BY列显示。镜像各层相当于一个子镜像。
8.6、查找镜像
在命令行使用docker search命令可以搜索Docker Hub中的镜像。
# 查找httpd的镜像
[root@docker-a~]# docker search httpd
NAME DESCRIPTION STARS OFFICIAL
httpd
The Apache HTTP Server Project 4695 [OK]
clearlinux/httpd httpd HyperText Transfer Protocol (HTTP) ser… 5
paketobuildpacks/httpd 0
vulhub/httpd 0
jitesoft/httpd Apache httpd on Alpine linux. 0
openquantumsafe/httpd Demo of post-quantum cryptography in Apache … 12
wodby/httpd 0
dockette/httpdump 0
betterweb/httpd 0
dockette/apache Apache / HTTPD 1
centos/httpd-24-centos7 Platform for running Apache httpd 2.4 or bui… 46
manageiq/httpd Container with httpd, built on CentOS for Ma… 1
centos/httpd-24-centos8 3
dockerpinata/httpd 1
httpdocker/kubia 0
httpdss/archerysec ArcherySec repository 0
19022021/httpd-connection_test This httpd image will test the connectivity … 0
centos/httpd
e2eteam/httpd 0
manasip/httpd 0
publici/httpd httpd:latest 1
patrickha/httpd-err 0
solsson/httpd-openidc mod_auth_openidc on official httpd image, ve… 2
futdryt/httpd 0
amd64/httpd The Apache HTTP Server Project 1
其中NAME列显示镜像仓库(源)名称,OFFICIAL列指明是否为Docker官方发布。
8.7、删除本地镜像
使用docker rmi命令删除本地镜像
docker rmi [选项] 镜像 [镜像...]
可以使用镜像的ID、标签或镜像摘要标识符来指定要删除的镜像。如果一个镜像对应了多个标签,则只有当最后一个标签被删除时,镜像才被真正删除。
如果使用-f选项,则将删除该镜像标签,并删除与该ID匹配的所有镜像。
--no-prune选项表示不删除没有标签的父镜像
8.8、验证镜像的分层结构
# 建立一个项目目录,用来存放Dockerfile及相关文件
[root@docker-a ~]# mkdir -p ch02/imglayers && cd ch02/imglayers
# 建立app子目录并准备所需的文件
[root@docker-a imglayers]# mkdir app && cd app
[root@docker-a app]# vi app.py
[root@docker-a app]# cat app.py
#!/usr/bin/python
print("Hello,World!")
# 返回项目目录的根目录,编辑Dockerfile文件
[root@docker-a app]# cd ../
[root@docker-a imglayers]# vi Dockerfile
[root@docker-a imglayers]# cat Dockerfile
FROM ubuntu:16.04
COPY ./app /app
RUN apt-get -y update && apt-get install -y python
CMD python /app/app.py
# 基于Dockerfile构建一个镜像
[root@docker-a imglayers]# docker build -t imglayers-test .
[+] Building 36.1s (8/8) FINISHED
...
=> => naming to docker.io/library/imglayers-test
# 查看该镜像的分层信息
[root@docker-a imglayers]# docker history imglayers-test
IMAGE CREATED CREATED BY SIZE COMMENT
c4b3ec7ea510 55 seconds ago CMD ["/bin/sh" "-c" "python /app/app.py"] 0B buildkit.dockerfile.v0
<missing> 55 seconds ago RUN /bin/sh -c apt-get -y update && apt-get … 60.8MB buildkit.dockerfile.v0
<missing> About a minute ago COPY ./app /app # buildkit 41B buildkit.dockerfile.v0
<missing> 2 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 years ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 2 years ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B
<missing> 2 years ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B
<missing> 2 years ago /bin/sh -c #(nop) ADD file:11b425d4c08e81a3e… 135MB
8.9、离线环境中导入镜像
# 先从一个联网的Docker主机上拉取Docker镜像
docker pull hello-word
# 使用docker save命令将镜像导出到归档文件,也就是将镜像保存到本地文件中
docker save --output hello-world.tar hello-world
ls -sh hello-world
# 在另一台离线主机上使用docker load命令从归档文件加载该镜像
docker load --input hello-world.tar
# 使用docker images命令查看刚加载的镜像
docker images
# 基于该镜像启动一个容器
docker run hello-world