docker import 和 docker load 有什么区别?
想要了解 docker load
与 docker import
命令的区别,还必须知道 docker save
与 docker export
- docker save:将一个镜像导出为文件,再使用
docker load
命令将文件导入为一个镜像,会保存该镜像的的所有历史记录,比docker export
命令导出的文件大。 - docker export:将一个容器导出为文件,再使用
docker import
命令将容器导入成为一个新的镜像,但是相比docker save
命令,容器文件会丢失所有元数据和历史记录,仅保存容器当时的状态,相当于虚拟机快照。
因此,既可以使用 docker load
命令来导入镜像库存储文件到本地镜像库,也可以使用docker import
命令来导入一个容器快照到本地镜像库。
两者的区别在于容器快照将会丢弃所有的历史记录和元数据信息,而镜像存储文件将保存完整记录,体积也会更大。
bind mount和volume模式创建存储卷
- 在bind mount模式下,如果容器本身目录有文件,容器该目录本身存在的文件将会消失不见, 这是 bind mount 模式和 volume 模式最大的不同点
- 在bind mount模式下,使用–mount方式创建卷,如果宿主机目录不存在,会报错。而使用-v模式则不会
临时卷 tmpfs
- 临时卷数据位于内存中,在容器和宿主机之外。
- 不同于卷和绑定挂载,不能在容器之间共享 tmpfs 挂载。
- 这个功能只有在 Linux 上运行 Docker 时才可用。
- tmpfs 也会覆盖容器里面的文件
什么时候用 Volume ,什么时候用 bind 、tmpfstmpfs?
volume:volume 是 docker 的宿主机文件系统一部分,用于不需要规划具体目录的场景
bind:bind mount 完全是依赖于主机的目录结构和操作系统,用于目录需要提前规划,比如 mysql 的目录需要个空间大的,其他服务有不占用的时候,用 volume 就不太合适了
tmpfs:用于敏感文件存储,文件不想存储的宿主机和容器的可写层之中
镜像制作dockfile
如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,这个脚本就是Dockerfile。
1. ADD 与 COPY 的区别
ADD:不仅能够将构建命令所在的主机本地的文件或目录,而且能够将远程 URL所对应的文件或目录,作为资源复制到镜像文件系统。所以,可以认为 ADD 是增强版的 COPY,支持将远程 URL 的资源加入到镜像的文件系统。
COPY:COPY 指令能够将构建命令所在的主机本地的文件或目录,复制到镜像文件系统。
2. CMD 与 EntryPoint 的区别
ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与 CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给 ENTRYPOINT 指令的参数。
Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递 给ENTRYPOINT
组合使用 ENTRYPOINT 和 CMD, ENTRYPOINT 指定默认的运行命令, CMD指定默认的运行参数
3. 多个 From 指令如何使用
多个 FROM 指令并不是为了生成多根的层关系,最后生成的镜像,仍以最后一条FROM 为准,之前的 FROM 会被抛弃,那么之前的 FROM 又有什么意义呢?每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。
最大的使用场景是将编译环境和运行环境分离.
4. 什么是空悬镜像(dangling )
仓库名、标签均为 的镜像被称为虚悬镜像,一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的。
造成虚悬镜像的原因:
原因一:
原本有镜像名和标签的镜像,发布了新版本后,重新 docker pull *** 时,旧的镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消;
原因二:
docker build 同样可以导致这种现象。比如用 dockerfile1 构建了个镜像 tnone1:v1,又用另外一个 Dockerfile2 构建了一个镜像 tnone1:v1,这样之前的那个镜像就会变成空悬镜像。
可以用下面的命令专门显示这类镜像:
docker image ls -f dangling=true
5. 中间层镜像是什么?
为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的 docker image ls 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。
docker image ls -a
这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,因为之前说过,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如何你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。
编写dockerfile准则
- 善用.dockerignore 文件
使用它可以标记在执行 docker build 时忽略的路径和文件,避免发送不必要的数据内容,从而加快整个镜像创建过程。 - 镜像的多阶段构建
通过多步骤创建,可以将编译和运行等过程分开,保证最终生成的镜像只包括运行应用所需要的最小化环境。当然,用户也可以通过分别构造编译镜像和运行镜像来达到类似的结果,但这种方式需要维护多个 Dockerfile。 - 合理使用缓存
如合理使用 cache,减少内容目录下的文件,内容不变的指令尽量放在前面,这样可以尽量复用; - 基础镜像尽量使用官方镜像,并选择体积较小镜像
容器的核心是应用,大的平台微服务可能几十上百个。选择过大的父镜像(如 Ubuntu系统镜像)会造成最终生成应用镜像的臃肿,推荐选用瘦身过的应用镜像(如
node:slim),或者较为小巧的系统镜像(如 alpine、busybox 或 debian); - 减少镜像层数
如果希望所生成镜像的层数尽量少,则要尽量合并 RUN、ADD 和 COPY 指令。通常情况下,多个 RUN 指令可以合并为一条 RUN 指令;如 apt get update&&apt install 尽量写到一行 - 尽量让每个镜像的用途都比较集中单一,避免构造大而复杂、多功能的镜像;
- 减少外部源的干扰
如果确实要从外部引入数据,需要指定持久的地址,并带版本信息等,让他人可以复用而不出错。 - 减少不必要的包安装
只安装需要的包,不要安装无用的包,减少镜像体积。