Docker-镜像
参考文献
- 极客时间 <<Kubernetes入门实战课>>
镜像
- Docker镜像是静态的分层管理的文件组合,镜像底层的实现依赖于联合文件系统(
UnionFS
)
镜像是如何构建的
- 构建过程不是由
Docker
客户端进行的,而是将整个目录的文件上传到Docker
守护进程并在那里进行的.Docker
客户端和守护进程不要求在同一台机器上. - 如果要在一台
Linux
系统中使用Docker
,客户端就运行在你的宿主操作系统上,但是守护进程运行在一个虚拟机内.由于构建目录中的文件都被上传到了守护进程中,如果包含了大量的大文件而且守护进程不在本地运行,上传过程会花费更多的时间.- 注意: 不要在构建目录中包含任何不需要的文件,这样会减慢构建的速度-尤其当
Docker
守护进程运行在一个远端机器的时候.
- 注意: 不要在构建目录中包含任何不需要的文件,这样会减慢构建的速度-尤其当
镜像分层
- 镜像不是一个大的二进制块,而是由多层组成,不同镜像可能会共享分层,这会让存储和传输变得更加高效.所有组成基础镜像的分层只会被存储一次.拉取镜像的时候,
Docker
会独立下载一层.一些分层可能已经存储在机器上了,所以Docker
只会下载未被存储的分层. - 构建镜像时,
Dockerfile
中每一条单独的指令都会创建一个新层. - 容器镜像是由多个只读的Layer构成的,同一个Layer可以被不同的镜像共享,减少了存储和传输的成本
镜像基本操作
搜索镜像
1 | docker search [options] image_name |
--no-trunc
: 显示完整的镜像名称--filter=stars=3
: 列出收藏数不小于指定值的镜像--filter=automated=true
: 只列出automated build类型的镜像
拉取镜像
1 | docker pull [registry]/[respository]/[image_name]:[tag] |
registry
: 注册服务器respository
: 镜像仓库image_name
: 镜像名称tag
: 镜像标签,不指定则使用latest
- 拉取先从本地搜索,若本地搜索不到在到远程仓库拉取
查看镜像
1 | docker images |
-a
: 列出所有镜像(含中间镜像层)-q
: 只显示镜像ID--digests
: 显示摘要信息--no-trunc
: 不截断输出,显示完整的镜像ID- 查询指定的镜像
docker image ls [image_name]
或者docker images|grep [image_name]
重命名镜像
1 | docker tag [source_image_name][:tag] [target_image][:tag] |
- 示例:
docker tag cowboy:latest mycowboy:latest
删除镜像
1 | docker rmi [imange_name] |
删除版本号为none
的镜像
1 | docker images -a | grep none | awk '{print $3}' | xargs docker rmi |
构建镜像
-
通过
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名: [TAG]
-
通过
docker build
1
2
3#其中 -t 对镜像进行命名,一般的命名法:仓库名字/镜像名字:版本号
#注意:其中 .号,代表当前目录下的dockerfile文件
docker build -t 仓库名字/镜像名字:版本号 .
多阶段构建
-
dockerfile
1
2
3
4
5
6
7
8
9# syntax=docker/dockerfile:1
FROM ubuntu AS base
RUN echo "base"
FROM base AS stage1
RUN echo "stage1"
FROM base AS stage2
RUN echo "stage2" -
docker build --no-cache -f Dockerfile --target stage2 .
镜像的导入与导出
-
镜像压缩打包 (主机上进行操作),有两种方式
docker save
与docker load
和docker export 与 docker import
1
2
3
4
5
6
7
8
9
10
11
12
13# 将现有的镜像压缩打包
# docker save -o <image_save_path/image_file.tar> <image>
docker save nginx | gzip > nginx_test_image.tar.gz
docker save nginx | pv -s $(docker inspect -f '{{.Size}}' nginx) | gzip > nginx_test_image.tar.gz
# 使用 pigz(多线程压缩工具)替代 gzip 可加速压缩
docker save nginx | pv | pigz > nginx_test_image.tar.gz
nohup sh -c 'docker save nginx | pv -s $(docker inspect -f "{{.Size}}" nginx) | gzip > nginx.tar.gz' > logs.log 2>&1 &
# 压缩的镜像解压
docker load -i nginx_test_image.tar.gz
# 加载某个目录下所有的镜像压缩包 find /path/to/images -name '*.tar' -exec docker load -i {} \;
# 进行查看
docker images
docker save
和docker export
的区别
- 对于
docker save
方法,会保存该镜像的所有历史记录; - 对于
docker export
方法,不会保留历史记录,即没有commit
历史; docker save
保存的是镜像(image
),docker export
保存的是容器(container
);docker load
用来载入镜像包,docker import
用来载入容器包,但两者都会恢复为镜像;docker load
不能对载入的镜像重命名,而docker import
可以为镜像指定新名称.
Docker Hub
上镜像命名的规则
-
通常来说,镜像标签的格式是应用的版本号加上操作系统.
-
版本号基本上都是主版本号+次版本号+补丁号的形式,有的还会在正式发布前出
rc
版(候选版本,release candidate).而操作系统的情况略微复杂一些,-
Alpine、CentOS的命名比较简单明了,就是数字的版本号,像这里的
alpine3.15
,而Ubuntu、Debian则采用了代号的形式.比如Ubuntu 18.04是bionic
,Ubuntu 20.04是focal
,Debian 9是stretch
,Debian 10是buster
,Debian 11是bullseye
. -
另外,有的标签还会加上
slim
、fat
,来进一步表示这个镜像的内容是经过精简的,还是包含了较多的辅助工具.通常slim
镜像会比较小,运行效率高,而fat
镜像会比较大,适合用来开发调试.
-
-
nginx:1.21.6-alpine,表示版本号是1.21.6,基础镜像是最新的Alpine.
-
redis:7.0-rc-bullseye,表示版本号是7.0候选版,基础镜像是Debian 11.
-
node:17-buster-slim,表示版本号是17,基础镜像是精简的Debian 10.
构建多架构镜像
使用步骤
-
使用
Docker buildx
来构建镜像,若系统中没有buildx
可以在Github Release下载对应平台的二进制文件,并将其放置到对应目录OS Binary name Destination folder Linux
docker-buildx
$HOME/.docker/cli-plugins
macOS
docker-buildx
$HOME/.docker/cli-plugins
Windows
docker-buildx.exe
%USERPROFILE%\.docker\cli-plugins
-
开启
binfmt_misc
来运行非本地架构的Docker
镜像1
docker run --privileged --rm tonistiigi/binfmt --install all
-
将默认 Docker 构建器切换为多架构构建器
1
docker buildx create --use --name mybuilder
-
查看新的多架构构建器是否生效,需执行
docker buildx ls
1
2
3
4
5
6# docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running v0.21.1 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
default docker
default default running v0.11.7-0.20230525183624-798ad6b0ce9f linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/arm/v7, linux/arm/v6 -
构建多架构镜像,通过命令
docker buildx build -t <image-name> --platform=linux/arm64,linux/amd64 . --push
,构建一个支持arm64
和amd64
架构的多架构镜像,并推送至仓库
遇到的问题
-
docker buildx build
时报错ERROR: failed to solve: failed to push xxxxxxx:9091/test/test:latest: failed to do request: Head "https://xxxxxxx:9091/v2/test/test/blobs/sha256:a569e7431bce80cb7abd105bb0b25850948575d985ffd93967acd347eab3b1a2": http: server gave HTTP response to HTTPS client
-
解决方法
-
删除原有
builder
,设置支持HTTP
,重新创建builder
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16docker buildx rm mybuilder
cat <<EOF > ./config.toml
debug = true
# root is where all buildkit state is stored.
root = "/var/lib/buildkit"
# insecure-entitlements allows insecure entitlements, disabled by default.
insecure-entitlements = [ "network.host", "security.insecure"]
[registry."你的仓库地址"]
http = true
insecure = true
EOF
docker buildx create --use --name=mybuilder --config=./config.toml --bootstrap -
然后重新构建
-