写点什么

面向 WEB 开发的 Docker(二):什么是 Docker、镜像、编排?

作者:devpoint
  • 2021 年 12 月 14 日
  • 本文字数:5362 字

    阅读完需:约 18 分钟

面向WEB开发的Docker(二):什么是Docker、镜像、编排?

什么是 Docker 容器?有什么的特点:轻量,在一台机器上运行的多个 Docker 容器可以共享这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的,并共享一些公共文件。这样就能尽量降低磁盘用量,并能更快地下载镜像。


先来看看几个概念。

  • Docker 在单个容器中运行 MySQL 之类的应用程序。

    这是一个类似于虚拟机的轻量级软件包,包含操作系统,应用程序文件和所有依赖项。

  • Web 应用程序可能需要几个容器。代码(和 runtime),数据库,Web 服务器等。

  • 从图像启动容器。

    本质上,它是一个容器模板,用于在 Dockerfile 配置中定义操作系统,安装过程,设置等。可以从同一映像启动任意数量的容器。

  • 容器以干净(映像)状态启动,因此不会永久存储数据。

    可以挂载 Docker 卷或绑定主机文件夹以保留状态。

  • 容器与主机和其他容器隔离。

    可以定义网络并打开 TCP / IP 端口以允许通信。

  • 每个容器都通过一个 Docker 命令启动。

    Docker Compose是一个实用程序,可以使用配置文件一步启动多个容器。 docker-compose.yml

  • 可选地,编排工具(例如Docker SwarmKubernetes)可用于容器管理和生产系统上的复制。

容器

回忆一下如何使用虚拟机(VM)安装 Web 应用程序及其依赖项。诸如 VMware、Parallels Desktop 和 VirtualBox 之类的 VM 软件被称为管理程序。它们可以创建新的虚拟机,然后使用所需的应用程序堆栈(Web 服务器,runtime,数据库等)安装适当的操作系统,如下图为单个虚拟机:


在某些情况下,可能无法在单个 VM 中安装所有应用程序,因此需要多个 VM:



每个 VM 是在主机 OS 的仿真硬件上运行的完整 OS,可以通过管理程序访问资源(例如网络)。这是相当大的开销,尤其是在依赖性很小的情况下。


Docker 在一个单独的容器中启动每个依赖项。它有助于将容器视为具有自己的操作系统,库和应用程序文件的微型 VM。


事实上:

  • 虚拟机管理程序可仿真硬件,因此可以运行完整的操作系统

  • Docker 模拟了一个操作系统,因此可以在各自的文件系统中运行独立的应用程序。



因此,Docker 使用的主机 OS 资源少于 VM。


从技术上讲,可以在单个容器中运行应用程序的所有依赖项,但是这样做没有任何实际好处,并且管理变得更加困难。因此,应为应用程序,数据库和所需的任何其他依赖项使用单独的容器。


Docker 技术使用 Linux 内核和内核功能(例如 Cgroups 和 namespaces)来分隔进程,以便各进程相互独立运行。这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性


容器工具(包括 Docker)可提供基于镜像的部署模式。这使得它能够轻松跨多种环境,与其依赖程序共享应用或服务组。Docker 还可在这一容器环境中自动部署应用(或者合并多种流程,以构建单个应用)。

容器是隔离的

每个运行的容器都是可用的,但是必须公开一个 TCP 端口才能使用它,例如 localhost 127.0.0.1

  • 端口或 HTTP 或 HTTPS Web 服务器 80 443

  • 3306 对于MySQL

  • 27017 对于MongoDB

Docker 还允许访问容器外壳并公开其他端口,以便可以附加调试器查看问题。

容器是无状态且可丢弃的

一旦关闭,写入容器文件系统的数据就会丢失!


可以从同一基本映像启动任何数量的容器(请参见下文)。因为每个容器实例都是相同且可抛弃的,所以这使缩放变得容易。


这可能会改变应用程序开发的方式,特别是如果想在生产服务器上使用 Docker。假定应用程序具有一个变量,该变量计算已登录用户的数量。如果它在两个容器中运行,则两个容器都可以处理登录,因此每个容器都有不同的用户数。


因此,Docker 化的 Web 应用程序应避免将状态数据保留在变量和本地文件中。应用程序可以将数据存储在数据库中,例如 redis,MySQL 或 MongoDB,这样状态在容器实例之间保持不变。


如果从一开始就以非无状态方式开发使用 Docker 容器的现有应用程序,则可能不切实际。但是,在开发期间,仍然可以在 Docker 容器中运行应用程序。


哪个提出了问题:如果数据库在容器中运行该怎么办?


重新启动时,它也会丢失数据,因此 Docker 提供了卷和主机文件夹绑定安装。


可能会想:“啊,我可以通过不停止容器来解决状态问题!” 确实如此。假定您的应用程序是 100%无错误的。而且您的运行时是 100%可靠的。而且操作系统永不崩溃。而且您永远不需要更新主机操作系统或容器本身。

在 Linux 上运行的容器

所使用的主机操作系统无关紧要:Docker 容器在 Linux 上本地运行。因此,Windows 和 macOS 在 Linux VM 内运行 Docker 容器!

Docker 的 macOS 版本需要 VirtualBox。

Windows 版本的 Docker 要求:

  1. Hyper-V 的。

    Windows 10 专业版和企业版免费提供的 Microsoft 虚拟机管理程序

  2. 在的 Windows 子系统为 Linux(WSL)2。

    Windows 2020 年 5 月更新提供了此工具,它实际上是高度集成的无缝 VM,可以安装在所有版本的 Windows 上。

    Windows 上的 Docker Desktop 可让您在两种类型之间切换。

    因此,在 Linux 上运行 Docker 效率更高,但这在开发 PC 上几乎没有关系。使用您喜欢的任何操作系统和工具。

    但是,如果您使用 Docker 部署应用程序,则 Linux 是实时服务器的最佳选择。

映像

Docker 映像是具有库和应用程序可执行文件的文件和操作系统的快照。本质上,image 是用于创建容器的控制器或模板。(以类似于某些计算机语言的方式,您可以定义可重复使用的 class 模板以实例化相同类型的对象。)


单个镜像可以启动任意数量的容器。尽管在开发过程中不太可能从同一映像启动多个容器,但这允许在生产服务器上进行扩展。


Docker Hubprovides 提供通用的流行的应用映像,如 NGINX、MySQL、MongoDB、Elasticsearch,Redis 的等等。


还有针对 Node.js,PHP,Python,Ruby,Rust 以及您听说过的任何其他语言的运行时映像。


提醒:如果想发布自己的映像,请注册 Docker Hub 帐户。

Dockerfile

使用Dockerfile配置映像。它定义:

  1. 起始基本映像,通常是操作系统

  2. 工作目录和用户权限

  3. 所有必要的安装步骤,例如定义环境变量,从主机复制文件,运行安装过程等。

  4. 容器是否应附加一个或多个卷以进行数据存储

  5. 容器是否应加入网络以与他人通信

  6. 主机上公开了哪些端口(如果有) localhost

  7. 应用程序启动命令。

在某些情况下,将按原样使用 Docker Hub 中的映像,例如 MySQL。但是,您的应用程序将需要它自己的自定义 Dockerfile。

开发和生产 Dockerfile

可以为应用程序创建两个 Dockerfile 配置:

  • 一个开发环境

    通常,它将激活日志记录,调试和远程访问。例如,在 Node.js 开发过程中,您可能希望使用 Nodemon 启动应用程序,以在更改文件时自动重新启动它。

  • 一个生产环境

    这将以更有效和更安全的模式运行。对于 Node.js 部署,可能会使用标准的运行时命令。

映像标签

Docker Hub 管理 Docker 映像,而 Github 则用于 Git 存储库。


创建的任何映像都可以推送到 Docker Hub。很少有开发人员执行此操作,但是对于部署目的或与其他人共享应用程序而言,这可能是实用的。


映像使用Docker Hub ID进行名称分隔,以确保没有人可以使用相同的名称。他们也有一个标签,所以你可以创建相同的映像,例如多个版本  1.0 1.1 2.0 latest 等。


例子:

yourname/yourapp:latest , craigbuckler/myapp:1.0 .

Docker Hub上的官方映像不需要 Docker ID,例如 (假定)mysql:latest mysql mysql:latest mysql:5mysql:8.0.20

volumes

容器在重新启动之间不会保持状态。这通常是件好事; 可以从同一基本映像启动任意数量的容器,并且每个容器都可以处理传入的请求,而不管它们是如何启动或何时启动的(请参阅业务流程)。


但是,某些容器(例如数据库)绝对必须保留数据,因此 Docker 提供了两种存储机制类型:


  1. Volumes:由 Docker 管理的文件系统

  2. Bind mounts:主机上的文件或目录。


两者都可以在容器上安装目录,例如用于 MongoDB 存储的目录 /data/db


建议使用 Volumes 来保留数据。在某些情况下,它是唯一的选择–例如,MongoDB 当前不支持 Windows 或 macOS 文件系统上的绑定安装。


但是,绑定安装在开发过程中很实用。主机 OS 上的应用程序文件夹可以安装在容器中,因此任何文件更改都会触发应用程序重新启动,浏览器刷新等。

网络

任何TCP/IP端口都可以暴露在容器中,例如MySQL 3306。这允许主机上的应用程序与localhost:3306上的数据库系统通信。


另一个容器无法与 MySQL 通信,因为 localhost 将解析为它自己。出于这个原因,Docker 创建了一个虚拟网络,并为每个正在运行的容器分配一个唯一的 IP 地址。然后,一个容器就可以使用其地址与另一个容器通信。


不幸的是,Docker IP 地址在每次启动一个容器时都可能改变。一个更简单的选择是创建您自己的 Docker 虚拟网络。任何添加到该网络的容器都可以使用其名称与另一个容器进行通信,例如mysql:3306解析到正确的地址。


容器 TCP/IP 端口可以暴露:

  • 仅在虚拟网络内

  • 在虚拟网络和主机之间。


假设你在同一个 Docker 网络上运行两个容器:


  1. 一个名为phpapp的容器,它在端口80上公开一个 web 应用程序

  2. 一个名为mysql的容器,它在端口3306上公开一个数据库。


在开发期间,可能希望两个端口都公开给主机。应用程序可以在http://localhost/(端口 80 是默认)的 web 浏览器中启动,MySQL 客户端可以连接到 http://localhost:3306/


在生产环境中,mysql端口不需要向主机公开。phpapp容器仍然可以与mysql:3306通信,但是肆无忌惮的黑客将不能探测主机上的端口3306


通过仔细的规划,可以创建复杂的 Docker 网络来提高安全性,例如,mysqlredis容器可以被phpapp访问,但它们不能互相访问。

Docker Compose

单个 Docker 命令用于启动单个容器。一个需要Node.jsNGINXMongoDB容器的应用程序以三个命令启动-可能在三个终端中以正确的顺序执行(可能是MongoDB,然后是Node.js应用程序,然后是NGINX)。


Docker Compose是一个用于管理具有关联volumes和网络的多个容器的工具。单个配置文件,通常命名为docker-compose.yml,定义容器,并可以在必要时覆盖Dockerfile设置。


为开发创建 Docker 组合配置是很实际的。也可以创建一个用于生产,但是还有更好的选择……

编排

容器是便携式且可复制的。这样,您可以通过在世界另一端的同一服务器,另一台服务器甚至不同的数据中心上启动相同的容器来扩展单个应用程序。

管理,扩展和维护容器的过程称为业务流程。Docker Compose可以用于基本的编排,但是最好使用专业工具,例如:

云主机还提供了自己的编排解决方案,通常基于Kubernetes,但可能具有自定义选项或工具。

Docker 开发策略

如何使用 Docker 容器化取决于自己。

仅将 Docker 用于开发

Docker 用于在开发 PC 上复制实时服务器的生产环境。可以在具有三个 Docker 容器的开发环境中模拟具有 Node.js、MongoDB 和 NGINX 的生产系统。

在可行的地方使用 Docker

生产服务器将 Docker 用于某些应用程序。Node.js进程将是理想的选择,但是 MongoDB 数据库可以由云服务提供,而 NGINX 可以作为负载平衡器安装在主机 OS 上。


开发 PC 可以使用三个 Docker 容器模拟此环境。或者,也许在容器中运行 Node.js 和 NGINX,但是访问同一 MongoDB 云服务上的测试数据库以消除兼容性问题。


并发处理

Node.js 应用程序通常在单个处理线程上运行。运行有 16 个 CPU 内核(例如应用程序)的服务器将有 15 个处于闲置状态!对于其他运行时也是如此,尽管 Apache 和类似的 Web 服务器会随着请求的增加而启动其他线程(这有其自身的资源问题)。

Node.js 应用程序可以实现群集或使用流程管理器(例如 PM2)启动其他线程。但是,在资源允许的情况下,Docker 启动和管理多个容器通常更为实用。

使用 Docker 进行开发和生产

可以在开发和生产中使用几乎相同的 Docker 容器。可能有必要为每个创建略有不同的启动配置。

更简单的开发和生产

  1. 应用程序 Dockerfile 仅配置生产环境。

  2. 出于开发目的,Docker Compose 用于覆盖此基本配置。

因此,无论选择哪种编排或部署选项,都可以在生产服务器上按原样使用映像。

何时不使用 Docker

在开发过程中使用 Docker 的缺点很少。它使您可以在任何 PC 上安装依赖项并模拟实时系统。您可以轻松地与其他人共享该隔离的环境,同时保留您喜欢的编辑器和工具。

但是,Docker 并不是可以解决您所有生产难题的神奇解决方案!


在某些情况下,Docker 可能不合适。


  1. 应用程序不是无状态的

如果最初不是为基于容器的部署设计的,则对现有的整体应用程序进行 Docker 可能会很困难。将状态存储在变量或文件中的程序将需要进行修改以使用其他数据存储。


2.正在使用 Windows Server

Docker 在 Linux 上是本机,但是 Windows 在 Hyper-V 虚拟机或 WSL2(实际上是另一个 VM)中运行容器。这是额外的开销,尽管 Docker 可以让您运行 Linux 依赖项,但置备 Linux 服务器可能更有效。


  1. 性能至关重要

Docker 容器已施加 CPU 和 RAM 限制。这些是可配置的,但是在主机 OS 上运行的应用程序始终会更快。

也就是说,如果您的应用程序通常在单个 CPU 内核上运行,则 Docker 可以通过水平扩展来实现并行处理。


  1. 稳定性很重要

Docker 已经成熟,但它是安装,更新和管理的另一个依赖项。您是否拥有内部容器管理专业知识?

由于容器可以缩放并自动重新启动,因此您的应用程序似乎更健壮。这并不意味着它崩溃的频率不会比以前少!


  1. 存储关键任务数据

卷和绑定装载可以存储持久性数据,但是与标准文件系统选项相比,它们更难以管理和备份。


  1. 为了提高安全性

容器是隔离的,但是与真实的 VM 不同,容器没有从主机 OS 完全沙盒化。Docker提供了用于隐藏依赖项的选项,但它不能替代强大的安全性。


  1. 创建 GUI 应用程序

某个地方的人将使用容器创建一个跨平台的图形界面应用程序。但这并不是Docker理想的解决方案!

发布于: 2 小时前阅读数: 7
用户头像

devpoint

关注

细节的追求者 2011.11.12 加入

专注前端开发,用技术创造价值!

评论

发布
暂无评论
面向WEB开发的Docker(二):什么是Docker、镜像、编排?