写点什么

99% 的人不知道的 Docker 干货

  • 2023-11-28
    福建
  • 本文字数:3391 字

    阅读完需:约 11 分钟

99%的人不知道的Docker干货



一、容器镜像和容器

镜像是一个可执行包,包含运行应用程序所需的所有内容——代码、运行时、库、环境变量和配置文件。容器是通过运行镜像启动容器,是镜像的运行时实例。镜像实际上就是一个容器的模板,通过这个模板可以创建很多相同的容器。

通过 Java 去类比理解 Docker 的一些概念:


  • Class 文件 - 相当于 Docker 镜像,定义了类的一些所需要的信息

  • 对象 - 相当于容器,通过 Class 文件创建出来的实例

  • JVM - 相当于 Docker 引擎,可以让 Docker 容器屏蔽底层复杂逻辑,实现跨平台操作

二、容器与虚拟机的区别

容器在 Linux 上本地运行,并与其他容器共享主机的内核。它运行一个独立的进程,不占用比其他任何可执行程序更多的内存,使其轻量级。

虚拟机(VM) 运行一个成熟的“游客”操作系统,通过虚拟机监控程序对主机资源进行虚拟访问。通常,vm 提供的资源比大多数应用程序所需的要多。


总的来说,容器不需要依赖操作系统,减少了很多系统资源开销,使得容器可以更关注应用的需求,而虚拟机可以为每个应用灵活提供不同的操作系统,避免了 docker 容器直接依赖主体机器操作系统,两者结合使用,可以让整个系统架构更加灵活,扩展性更强。

三、Docker 引擎和架构

Docker 引擎是一个客户端-服务器应用程序,主要组件如下:

  • 服务器是一种长时间运行的程序,称为守护进程(dockerd)命令)。

  • 一个 REST API,它指定了程序可以用来与守护进程对话的接口指导它做什么。

  • 命令行接口(CLI)客户端(docker 命令)。



  • 我们使用的 docker 指令都是通过 docker 客户端去与 docker 服务端进行通讯。

3.1 Docker 架构体系

  • Docker 使用客户机-服务器架构。

  • Docker 客户机与 Docker 守护进程进行对话,后者负责构建、运行和分发 Docker 容器。

  • Docker 客户机和守护进程可以在同一系统上运行,也可以将 Docker 客户机连接到远程 Docker 守护进程。Docker 客户机和守护进程通过 UNIX 套接字或网络接口使用 RESTAPI 进行通信。



3.2 Docker 的镜像分层

Docker 镜像是由一系列层构成的。每一层代表镜像 Dockerfile 中的一条指令。除了最后一层之外,每一层都是只读的。Docker 镜像分层最大的好处是共享资源,其他相同环境的软件镜像都共同去享用同一个环境镜像,而不需要每个软件镜像要去创建一个底层环境。


以 Tomcat 镜像为例子,对于用户而言,用户面向的是一个叠加后的文件系统,我们对 Tomcat 容器做任何操作都会记录在容器层,底层镜像文件不会受影响。Docker 容器底层共享主机内核,只保留少量运行 Image 必须的组件,在容器启动时不需要启动内核空间,所以启动时比虚机较快,开销少,易迁移。

Docker Image 是有多层结构,实际上由一层一层的文件系统组成,底层都是共享宿主 Linux 内核,Image 的分层结构是是为了提高复用性。Image 可以看作是 Java 的 class 文件,容器可以看成是 JAVA 的对象去理解,下层的每一层镜像可以看作是 JAVA 中的父类,上层镜像可以共享底层镜像的组件,类似 JAVA 中的继承规则。Docker Image 基于 Union file systems 做镜像和容器分层,避免在每次以新容器运行图像时复制一组完整的文件。将更改分隔为其自身层中的容器文件系统,允许将同一容器置于从已知内容重新启动(因为在删除容器时,更改的图层将被关闭)。


面向用户的是 Container 层,所有用户新增环境依赖和数据都会保存在容器层,下层 Image 只可读、不可修改。Container 是一种轻量级的虚拟技术,不需要模拟硬件创建虚拟机启动内核空间,因此启动速度很快。Docker 是基于 Linux Kernel 的 Namespace、CGroups、UnionFileSystem 等技术封装成的一种自定义容器格式,从而提供一套虚拟运行环境。

Namespace:对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前 namespace 里的进程,对其他 namespace 中的进程没有影响,比如 pid[进程]、net[网络]、mnt[挂载点]等 CGroups: cgroup 和 namespace 类似,也是将进程进行分组,但它的目的和 namespace 不一样,namespace 是为了隔离进程组之间的资源,而 cgroup 是为了对一组进程进行统一的资源监控和限制,比如内存、CPU、进程数等 Union file systems:用来做 image 和 container 分层。

四、制作 Docker Image 的两种方式



  1. 通过 Dockerfile 制作(推荐) - Dockerfile 其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

  2. 通过 Docker commit 操作 - 通过 docker commit 命令反向基于容器副本创建一个新的镜像文件。但是使用 docker commit 看不到 Image 的创建过程,因此对排查问题不友好。

五、Docker 数据存储方式


Docker 容器对于宿主机器来说只是一个运行在 Linux 上的应用,因此它的数据存储还是会依赖宿主机器,Docker 是通过挂载宿主机文件系统或内存的方式来实现数据存储的,挂载方式有三种:volume、bind mount 和 tmpfs。

volumes - 在宿主的文件系统上的 docker 工作路径下创建一个文件夹(/var/lib/docker/volumes)来存储数据,其他非 docker 进程是不能修改该路径下的文件,完全由 docker 来管理 bind mounts - 可以存储在宿主机器任何一个地方,但是会依赖宿主机器的目录结构,不能通过 docker CLI 去直接管理,并且非 docker 进程和 docker 进程都可以修改该路径下的文件 tmpfs - 无论是在 Docker 主机上还是在容器内,tmpfs 挂载都不会持久保存在磁盘上,它会将信息存储在宿主机器内存里。 容器在其生存期内可以使用它来存储非持久状态或敏感信息。 例如,在内部,swarm services 使用 tmpfs 挂载将机密挂载到服务的容器中 或者 我们一些不需要持久化数据的开发测试环境,可以使用 tmpfs

5.1 Volumes

Volumes 是 Docker 推荐的挂载方式,与把数据存储在容器的可写层相比,使用 Volume 可以避免增加容器的容量大小,还可以使存储的数据与容器的生命周期独立。

  • 与 bind mounts 相比,volumes 更易于备份或迁移。

  • 可以使用 Docker CLI 命令或 Docker API 管理 Volumes。

  • volumes 在 Linux 和 Windows 容器上均可工作。

  • 可以在多个容器之间更安全地共享 volumes。

  • volumes 驱动程序使您可以将 volumes 存储在远程主机或云提供程序上,以加密 volumes 内容或添加其他功能。

5.1.1 通过–mount 方式

-v 能做的–mount 指令都可以做,与-v 指令对比,–mount 指令更灵活,支持更多复杂操作,并且不需要严格按照参数顺序,通过 key value 键值对方式进行配置,可读性更高。–mount 有以下几个参数:

  • type - type 可以是 bind、volume 或者 tmpfs,默认是 volume

  • source - 宿主机上的目录路径,可以用缩写 src

  • destination - 目标路径,容器上挂载的路径,可以用 dst 或者 target

  • readonly - 可选项,如果设置了,那么容器挂载的路径会被设置为只读

  • volume-opt - 可选项,当 volume 驱动接受同时多个参数作为选项时,可以以多个键值对的方式传入

5.2 bind mounts

与 volumes 相比,bind mount 的功能有限。 使用绑定安装时,会将主机上的文件或目录安装到容器中。 文件或目录由主机上的完整或相对路径引用。 相比之下,当您使用 volume 时,将在主机上 Docker 的存储目录中创建一个新目录,并且 Docker 管理该目录的内容。

该文件或目录不需要在 Docker 主机上已经存在。 如果尚不存在,则按需创建。 bind mounts 性能非常好,但是它们依赖于具有特定目录结构的主机文件系统。 如果要开发新的 Docker 应用程序,请考虑使用命名 volume。 您不能使用 Docker CLI 命令直接管理 bind mounts

5.3 tmpfs

使用 tmpfs 不会持久化数据,数据只会存放在宿主机器内存中.

六、相关内容拓展:(技术前沿)

近 10 年间,甚至连传统企业都开始大面积数字化时,我们发现开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。针对这类问题,低代码把某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子。极大的提高了程序员的生产效率。

介绍一款程序员都应该知道的软件 JNPF 快速开发平台,基于 Java/.Net 双技术引擎,专注于低代码,采用业内领先的 SpringBoot 微服务架构、支持 SpringCloud 模式,完善了平台的扩增基础,满足了系统快速开发、灵活拓展、无缝集成和高性能应用等综合能力;采用前后端分离模式,前端和后端的开发人员可分工合作负责不同板块,省事又便捷。

免费体验官网:https://www.jnpfsoft.com?infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
99%的人不知道的Docker干货_Docker_伤感汤姆布利柏_InfoQ写作社区