docker镜像管理

镜像结构和原理

镜像就是创建容器的模板,含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于方便和快速的创建并启动容器

镜像理由是一层一层的文件系统:Union FS(联合文件系统),可以将几层目录挂载到一起(类似俄罗斯套娃),形成一个虚拟文件系统,虚拟文件系统的目录结构就像普通 linux 目录结构一样,镜像通过这些文件,再加上宿主机的内核共同构成了一个 linux 的虚拟环境,每一层文件系统叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限:readonly、readwrite、writeout-able。但是镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建提交的操作都相当与做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,当使用镜像的时候,我们只会看见一个整体,并不知道里面有几层,实际上也不需要知道

一个典型的 Linux 文件系统由 bootfs 和 rootfs 两部分组成

bootfs(boot file system)主要包含 bootloader 和 kernel,bootloader 主要用于引导加载 kernel。系统刚启动时会加载 bootfs 文件系统,kernel 加载到内存后,接管系统的控制权,bootfs 就会被 umount 掉

rootfs(root file system)就是我们看到的/dev、/proc、/bin、/etc 等目录和文件,不同的 linux 发行版本(如 ubuntu 和 centos)主要在 rootfs 这一层会有所区别

一般的镜像通常都比较小,镜像直接调用宿主机的内核,镜像中只提供 rootfs,也就是只需包括最基本的命令、配置文件和程序库等相关文件就可以了

容器、镜像和父镜像关系:

alpine 介绍

Alpine 操作系统是一个面向安全的轻型 Linux 发行版。它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐。在保持瘦身的同时,Alpine 还提供了自己的包管理工具 apk,可以通过https://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种软件。

Alpine 由非商业组织维护的,支持广泛场景的 Linux 发行版,它特别为资深/重度 Linux 用户而优化,关注安全,性能和资源效能。Alpine 镜像可以适用于更多常用场景,并且是一个优秀的可以适用于生产的基础系统/环境。

Alpine Docker 镜像也继承了 Alpine Linux 发行版的这些优势。相比于其他 Docker 镜像,它的容量非常小,仅仅只有 5 MB 左右(对比 Ubuntu 系列镜像接近 200 MB),且拥有非常友好的包管理机制。官方镜像来自 docker-alpine 项目。

目前 Docker 官方已开始推荐使用 Alpine 替代之前的 Ubuntu 做为基础镜像环境。这样会带来多个好处。包括镜像下载速度加快,镜像安全性提高,主机之间的切换更方便,占用更少磁盘空间等。

1
2
3
4
5
6
7
8
9
10
11
12
#修改源替换成阿里源:将/etc/apk/repositories中的 dl-cdn.alpinelinux.org 改成 mirrors.aliyun.com
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories
#更新源
apk update
# 查找可用软件包
apk search [vim]
# 列出软件信息
apk info [vim]
#安装软件
apk add vim
#删除软件
apk del openssh openntp vim

搜索镜像

如果联网下载,一般不会使用命令搜索,而是去官网搜索

docker 镜像加速

登录阿里云 –> 容器镜像服务 –> 镜像中心 –> 镜像加速器

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://3417nt4m.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

docker image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# docker help image
Usage: docker image COMMAND

Commands:
build # 从Dockerfile中构建镜像
history # 显示镜像分层历史
import # 从tar包中的内容创建一个新的文件系统映像[对应 container export]
inspect # 显示容器详细信息
load # 从一个tar包中加载一个镜像[对应save]
ls List images
prune # 移除未使用的镜像
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rm # 移除一个或多个镜像
save # 保存一个镜像为一个tar包[对应load]
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

下载镜像 pull

1
2
3
4
5
6
7
8
9
10
11
12
# docker help pull
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

Options:
-a, --all-tags Download all tagged images in the repository
--disable-content-trust Skip image verification (default true)
--platform string Set platform if server is multi-platform capable
-q, --quiet Suppress verbose output

NAME 镜像名,仓库服务器:端口/项目名称/镜像名称
:TAG 版本号,如果不指定:TAG,则下载最新版镜像
@DIGEST 摘要
1
2
3
4
5
6
7
[root@ubuntu1804 ~]#docker pull hello-world
Using default tag: latest # tag 默认下载tag为latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete # 分层下载
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f # 摘要
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest # 下载的完整地址
1
2
3
4
5
6
7
8
9
10
11
$ docker pull nginx:stable-alpine
stable-alpine: Pulling from library/nginx
97518928ae5f: Pull complete
a15dfa83ed30: Pull complete
acae0b19bbc1: Pull complete
fd4282442678: Pull complete
b521ea0d9e3f: Pull complete
b3282d03aa58: Pull complete
Digest: sha256:74694f2de64c44787a81f0554aa45b281e468c0c58b8665fafceda624d31e556
Status: Downloaded newer image for nginx:stable-alpine
docker.io/library/nginx:stable-alpine

下载后的镜像位于:

1
/var/lib/docker/overlay2/镜像ID

查看镜像分层历史 history

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ docker image history nginx:latest
IMAGE CREATED CREATED BY SIZE COMMENT
605c77e624dd 11 months ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 11 months ago /bin/sh -c #(nop) STOPSIGNAL SIGQUIT 0B
<missing> 11 months ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 11 months ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B
<missing> 11 months ago /bin/sh -c #(nop) COPY file:09a214a3e07c919a… 4.61kB
<missing> 11 months ago /bin/sh -c #(nop) COPY file:0fd5fca330dcd6a7… 1.04kB
<missing> 11 months ago /bin/sh -c #(nop) COPY file:0b866ff3fc1ef5b0… 1.96kB
<missing> 11 months ago /bin/sh -c #(nop) COPY file:65504f71f5855ca0… 1.2kB
<missing> 11 months ago /bin/sh -c set -x && addgroup --system -… 61.1MB
<missing> 11 months ago /bin/sh -c #(nop) ENV PKG_RELEASE=1~bullseye 0B
<missing> 11 months ago /bin/sh -c #(nop) ENV NJS_VERSION=0.7.1 0B
<missing> 11 months ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.21.5 0B
<missing> 11 months ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 11 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 11 months ago /bin/sh -c #(nop) ADD file:09675d11695f65c55… 80.4MB

查看容器详细信息 inspect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
$ docker image inspect nginx:latest
[
{
"Id": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
"RepoTags": [
"nginx:latest"
],
"RepoDigests": [
"nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31"
],
"Parent": "",
"Comment": "",
"Created": "2021-12-29T19:28:29.892199479Z",
"Container": "ca3e48389f7160bc9d9a892d316fcbba459344ee3679998739b1c3cd8e56f7da",
"ContainerConfig": {
"Hostname": "ca3e48389f71",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.5",
"NJS_VERSION=0.7.1",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"nginx\" \"-g\" \"daemon off;\"]"
],
"Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGQUIT"
},
"DockerVersion": "20.10.7",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"80/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NGINX_VERSION=1.21.5",
"NJS_VERSION=0.7.1",
"PKG_RELEASE=1~bullseye"
],
"Cmd": [
"nginx",
"-g",
"daemon off;"
],
"Image": "sha256:82941edee2f4d17c55563bb926387c3ae39fa1a99777f088bc9d3db885192209",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
},
"StopSignal": "SIGQUIT"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 141479488,
"VirtualSize": 141479488,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/7e01f99d0c11ed39e85b19c848a5593a5e9ebc65d339a266c07cd1f7bd7431ba/diff:/var/lib/docker/overlay2/d74f65dcbc4304207be8a4591b8c83f1d7faa4659da1612d0468e34f507902af/diff:/var/lib/docker/overlay2/ee3d6bfb887a97e99debff027624cc44f7e927852f10ad685c07468175b2f50b/diff:/var/lib/docker/overlay2/9589ebb2cd873d1a650ef2f9d540505edccbb13f838b13b660f1d49a060be769/diff:/var/lib/docker/overlay2/c81f555278e6da337860aebbe14978402627d46d4beb3ad5eaed34ec2b9264fe/diff",
"MergedDir": "/var/lib/docker/overlay2/efe3607d46ef55d39a59cf896b34e8e186d657969a48b121f89dca639f8541f4/merged",
"UpperDir": "/var/lib/docker/overlay2/efe3607d46ef55d39a59cf896b34e8e186d657969a48b121f89dca639f8541f4/diff",
"WorkDir": "/var/lib/docker/overlay2/efe3607d46ef55d39a59cf896b34e8e186d657969a48b121f89dca639f8541f4/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
"sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8",
"sha256:b8d6e692a25e11b0d32c5c3dd544b71b1085ddc1fddad08e68cbd7fda7f70221",
"sha256:f1db227348d0a5e0b99b15a096d930d1a69db7474a1847acbc31f05e4ef8df8c",
"sha256:32ce5f6a5106cc637d09a98289782edf47c32cb082dc475dd47cbf19a4f866da",
"sha256:d874fd2bc83bb3322b566df739681fbd2248c58d3369cb25908d68e7ed6040a6"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]

查看本地镜像 ls

等同于 docker images

1
2
3
4
5
6
7
8
9
10
11
12
13
# docker image ls --help
docker image ls [OPTIONS] [REPOSITORY[:TAG]]

Options:
-a, --all Show all images (default hides intermediate images)
--digests Show digests
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print images using a Go template
--no-trunc # 不截断输出,即展示完整的容器ID
-q, --quiet # 只展示容器ID

REPOSITORY # 镜像所属的仓库名称
TAG # 镜像版本号(标识符),默认为latest
1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 11 months ago 141MB

$ docker image ls -q
605c77e624dd

$ docker image ls --no-trunc
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85 11 months ago 141MB


IMAGE ID # 镜像唯一ID标识,如果ID相同,说明是同一个镜像有多个名称

REPOSITORY 仓库:

  • 由某特定的 docker 镜像的所有迭代版本组成的镜像仓库
  • 一个 Registry 中可以存在多个 Repository
  • Repository 可分为“顶层仓库”和“用户仓库”
  • Repository 用户仓库名称一般格式为“用户名/仓库名”
  • 每个 Repository 仓库可以包含多个 Tag(标签),每个标签对应一个镜像

镜像导出 save

将本地镜像导出为一个文件(tar 格式),然后复制到其他服务器,导入使用

1
2
3
4
5
# docker help image save
Usage: docker image save [OPTIONS] IMAGE [IMAGE...]

Options:
-o, --output string Write to a file, instead of STDOUT

常见用法:以下两种用法等价

1
2
docker save -o /path/file.tar IMAGE1 IMAGE2 ...
docker save IMAGE1 IMAGE2 ... > /path/file.tar

镜像导入 load

save 导出的镜像 tar 文件,使用load导入

1
2
3
4
5
6
7
# docker help image load

Usage: docker image load [OPTIONS]

Options:
-i, --input string Read from tar archive file, instead of STDIN
-q, --quiet Suppress the load output

常见用法:以下两种用法等价

1
2
docker load -i /data/myimages.tar
docker load < /data/myimages.tar

删除镜像 rm

删除本地镜像

1
2
3
4
5
6
7
8
9
# docker help image rm
Usage: docker image rm [OPTIONS] IMAGE [IMAGE...]

Aliases:
rm, rmi, remove

Options:
-f, --force Force removal of the image # 强制删除
--no-prune Do not delete untagged parents
1
alias rmi='docker image ls -aq | xargs -n1 docker image rm'

镜像打标签 tag

给镜像打标签,类似于起别名,但通常要遵守一定的命名规范,才可以上传到指定的仓库

1
2
3
4
5
6
docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

# TARGET_IMAGE[:TAG] 格式一般为
1.仓库主机FQDN或IP[:端口]
2.项目名(或用户名)
3.image名字:版本 # docker tag alpine alpine:3.11

tag 默认为 latest

先 tag 给镜像打标签,然后再 save 导出镜像,拷贝到其他机器,其他机器可以 load 导入