Docker概念篇

Docker架构图

从下面这张图中可以看出Docker的工作流程是什么样的,有哪些部分组成。点击这里查看官方文档
在这里插入图片描述

Docker Image

Docker Image由多个只读层(layer)组成的,这些层叠加起来就形成了一个完整的镜像。每一层都是在前一层的基础上做出的一些变更(比如添加、修改或删除文件等)。这些层被设计成只读的,以确保镜像的不变性和可重复性。当容器从镜像启动时,Docker会在这些只读层的顶部添加一个可写层,供容器运行时使用。

Docker 的分层概念可以通过以下例子来理解:
1. 基础镜像层:假设你想创建一个运行Python应用的容器,你会从一个基础镜像开始,例如一个最小化的Ubuntu系统。这个Ubuntu系统包含了运行Python应用所需的最基本的文件和目录,这构成了镜像的第一层。
2. 添加应用层:在Ubuntu系统的基础上,你可能需要安装Python。当你通过Dockerfile指令RUN apt-get install -y python3安装Python时,安装过程的所有变更会构成新的一层。
3. 添加依赖层:如果你的Python应用需要外部库,比如requests,你会再添加一条RUN pip install requests指令,这个安装库的过程会创建又一层。
4. 应用代码层:最后,你将自己的Python代码添加到镜像中,这又是一个新的层。这可能通过COPY . /app这样的Dockerfile指令完成,将当前目录下的所有文件复制到镜像的/app目录。
每一步都创建了一个新的镜像层,如果其他镜像需要相同的底层系统或者相同的依赖库,它们可以重用已有的层。这就是Docker镜像分层极大地节约了存储空间和传输时间的原因。
例如,如果另一个项目也是基于Ubuntu并且需要Python环境,它可以重用前两层(基础Ubuntu系统和安装了Python的层),然后只添加自己特定的依赖和应用代码作为新的层。
这种分层的结构同样使得镜像的更新和分发更加高效。当你更新了应用代码,只有包含代码的那一层需要被更新和推送到Docker仓库,而不是整个镜像,这样可以加快构建和部署的速度。
由于每个层都是不变的,它还保证了一致性和可重复性,你可以确信在不同环境中使用相同镜像时,得到的容器是一致的。

Q&A

  1. 通过什么命令可以查看构成Image的层信息?
    可以使用 docker history 命令来查看镜像的层(layer)信息,这能帮助判断不同镜像是否使用了相同的层。每一层都有一个唯一的标识符,称为SHA256摘要,通过这个摘要,可以比较不同镜像的层是否相同。
下面是如何操作的:
1. 查看镜像历史记录:你可以运行 docker history IMAGE_NAME:TAG,其中 IMAGE_NAME 是镜像名,TAG 是标签(如果没有指定,默认为 latest)。这条命令将列出构成该镜像的所有层及其元数据。
2. 对比镜像层:运行上述命令后,会得到一个列表,每行代表一个层,包括层的大小、创建时间和层的摘要(SHA256)。通过比较两个镜像的层摘要,可以判断哪些层是相同的。

举个例子,如果你想比较 ubuntu:18.04 和 python:3.7 这两个镜像是否有相同的层,可以使用下面的命令,
在输出结果中,你可以逐个检查每个层的摘要。如果两个镜像有相同的摘要序列,那么它们就使用了相同的层。
    docker history ubuntu:18.04
    docker history python:3.7
还有另外一种方法,你可以使用 docker inspect 命令来获取更详细的信息,包括层的精确 SHA256 摘要:
    docker inspect --format='{{json .RootFS.Layers}}' IMAGE_NAME:TAG
用上述命令,可以得到一个JSON格式的层摘要列表。比较两个镜像返回的JSON列表,就能看出它们共享了哪些层。
  1. Docker是怎么判断不同的Image之间是否存在可重用的镜像层?
    Docker实现不同镜像间相同层重用的核心是其镜像分层存储和联合文件系统(Union File System)。
联合文件系统允许多个不同的文件系统被叠加在一起,形成一个单一的文件系统。在Docker中,每一个镜像层都是一个只读的文件系统。
当创建一个新的容器时,Docker会叠加这些只读的镜像层,并在最顶层添加一个可写层供容器运行时使用。
下面是 Docker 如何实现镜像层重用的具体步骤:
1. 层的共享存储:
当第一次下载或构建一个镜像时,Docker会将这个镜像的每一层保存在宿主机的本地存储中。
每一层都会被赋予一个唯一的SHA256哈希值来标识它的内容,而不是依赖文件名或者标签。
当下载或构建另一个镜像时,如果这个新镜像有一些层与已经存在的层相同(即内容的SHA256哈希值相同),Docker就不会再次下载或创建这些层,而是直接重用已经存在的层。
2. 构建缓存:
在构建镜像的过程中,Docker会检查每一步操作(比如一个 RUN 指令或者 COPY 指令)是否之前已经执行过,并且检查之前的输出是否可以重用。
如果可以重用,Docker就会使用现有的镜像层,而不是创建一个新层。这不仅节省了时间,也减少了存储空间的消耗。
3. 联合文件系统:
当启动一个容器时,Docker 使用联合文件系统将所有的只读层和一个可写层叠加在一起,形成容器的文件系统。
对于容器内的应用来说,它们看到的是一个统一的文件系统,尽管这个文件系统实际上是由多个独立的层组成的。
这种设计使得 Docker 镜像非常高效,因为不需要复制或移动任何数据就可以在多个镜像之间共享相同的层。
由于层是不可变的,这还保证了一致性和安全性,因为你无法更改已经存在的层,只能在上面添加新的层或者创建新的镜像。

综上所述,Docker通过对镜像层的细粒度管理和联合文件系统的使用,实现了在不同镜像之间高效地共享和重用层,这大大加快了镜像的下载、分发和部署过程。
  1. 因为某一层构建失败导致整个Docker Image构建失败,怎么查找这个Image层的错误日志?
    当 Docker镜像构建失败时,Docker通常会在控制台输出错误的详细信息。这些信息包括失败的步骤、执行的命令和具体的错误消息。要查找特定层构建失败的错误日志,可以按照以下步骤进行:
1. 检查构建输出
执行docker build命令时,Docker会逐步输出每层的构建过程。如果某一层构建失败,Docker会在终端中显示错误消息。这通常是找到问题的首要方式。
2. 定位错误层
在构建输出中,寻找类似于 "Step X/Y : COMMAND" 的行,其中 "X/Y" 表示当前步骤和总步骤数,"COMMAND" 是执行的命令。失败的层会紧跟着包含错误信息的行。
3. 分析错误信息
错误信息通常包括错误的原因,可能是命令找不到、权限问题、网络问题等。
4. 使用 --progress 参数
docker build --progress=plain -t your-image:tag .
在docker build命令中添加 --progress=plain 参数可以得到更详细的输出,这对于诊断问题非常有用。
5. 使用 --no-cache 参数
docker build --no-cache -t your-image:tag .
如果怀疑问题与缓存有关,可以添加 --no-cache 参数来忽略所有缓存的层,并重新执行所有步骤。
6. 查看构建历史
docker history your-image:tag
如果构建过程中断,你可以使用 docker history 查看已经成功构建的层的历史记录。
7. 调试Dockerfile
如果错误不明显,你可能需要调试 Dockerfile。一种方法是将 Dockerfile 分解成较小的部分并逐个构建,或者在Dockerfile 中添加临时的RUN命令来检查环境变量、文件位置等。
以下是一些常用的 RUN 命令的示例,用于调试 Dockerfile:
    1. RUN env / RUN echo $PATH,检查环境变量,可以使用env命令列出所有环境变量,或者使用echo命令打印特定的环境变量。      
    2. RUN ls -la /path/to/directory,列出文件和目录,使用ls命令可以列出特定目录下的文件和文件夹,这可以帮助确认文件是否存在或是否在预期的位置。
    3. RUN pwd,检查当前工作目录,使用pwd命令可以打印出当前工作目录,确保你在预期的目录中执行命令。
    4. RUN cat /path/to/file,查看文件内容:如果需要确认文件的内容是否正确,可以使用cat,head,tail等命令查看文件内容。
    5. RUN curl -I https://example.com,检查网络连接,如果构建过程中需要下载资源或访问外部服务,使用curl或wget可以测试网络连接。
    6. RUN apt update && apt list --upgradable,检查包管理器状态,如果使用的是 Linux 系统,可以检查包管理器(如 apt, yum, apk 等)的状态。
    在添加这些命令后,重新构建镜像,观察控制台输出中的信息,构建完毕后,不要忘记移除或注释掉这些调试用的RUN命令,以避免它们影响最终镜像的大小和构建效率。
    请记住,RUN命令每执行一次就会创建一个新的层,因此仅在调试时添加这些命令,并在解决问题后将其清理。这样做可以避免不必要的层堆积,保持镜像的精简。
8. 使用日志收集工具
如果使用的是像Docker Swarm / Kubernetes这样的集群管理工具,需要查看这些工具的日志收集系统来获取构建日志。
如果错误发生在构建过程的后期,前面的层可能已经被缓存,因此重试构建时可以更快地到达失败的步骤。确保仔细阅读错误信息,并根据信息对Dockerfile进行必要的调整。如果错误信息不够明确,尝试上述的不同策略,直到你能够定位问题并解决它。

Docker 数据存储

在这里插入图片描述

  1. 数据卷(Volumes)
    数据卷是由Docker创建,用来存储容器产生的数据文件。(数据卷在Linux上存在的位置路劲:/var/lib/docker/volumes/)。
    Volumes are created and managed by Docker. You can create a volume explicitly using the docker volume create command, or Docker can create a volume during container or service creation.

  2. 绑定挂载(Bind Mounts)
    绑定安装可以存储在主机系统上的任何位置。 它们甚至可能是重要的系统文件或目录。 Docker主机或Docker容器上的非Docker进程可以随时修改它们。

  3. tmpfs挂载
    tmpfs 安装仅存储在主机系统的内存中,并且永远不会写入主机系统的文件系统。

Docker 网络配置

Docker 镜像中央仓库(Docker Hub)

docker hub,docker官方的中央仓库,这里面存放着各种各样的images,类似于maven的中央仓库,可以直接pull images from hub,然后在本地运行这些image,生成Container。
当然也可以搭建个人docker hub,这个需要自己去找资料。

Docker 常用命令

  1. docker pull redis:6,从docker hub拉去指定版本的images
  2. docker run -d -p port1:port2 redis:6,启动容器,并将容器的port2映射到宿主机的port1上,然后可以通过port1访问api, -d是表明容器要后台运行
  3. docker ps,查看当前docker上运行的所有容器
  4. docker exec -it containerID,进入某个指定的容器内部
  5. docker logs containerID,查看指定容器的日志
  6. docker build -t imageName:tagVersion .,这个.指代的是当前目录的DockerFile文件,image的构建就是根据DockerFile来的
  7. docker-compose,容器编码,是一个中间件,用来管理和编排Docker容器,基本不用,已经被k8s取代
  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值