大家好,我们一起了解什么是 Docker ?关于 Docker 的介绍比较多,这里也不想过多的介绍,我们来聊一聊 Docker 能做啥?
让我们来回想一下,如何使用虚拟机 (VM) 来安装 Web 应用程序及其依赖项。 诸如 VMware 和 VirtualBox 之类的 VM 软件被称为管理程序。 它们允许您创建新的虚拟机,然后安装具有所需应用程序堆栈(Web 服务器、运行时、数据库等)的适当操作系统:
在某些情况下,可能无法在单个 VM 中安装所有应用程序,因此需要多个 VM:
每个虚拟机都是一个完整的操作系统,在主机操作系统中的模拟硬件上运行,可以通过管理程序访问网络等资源。这是一个相当大的开销,尤其是当依赖项可能很小时。
Docker 在单独的容器中启动每个依赖项。将容器视为具有自己的操作系统、库和应用程序文件。
容器实际上是可执行文件的隔离包装器,因此 Docker 需要的主机操作系统资源比 VM 少得多。
在一个容器中运行所有应用程序的依赖项在技术上是可行的,但这样做并没有实际的好处,而且管理变得更加困难。
每个容器都可以在 localhost 或 127.0.0.1 上使用,但必须开放对应的 TCP 端口才能与其运行的应用程序通信,例如
Docker 还允许您访问容器外壳以输入终端命令并公开更多端口以附加调试检查相关问题。
写入容器文件系统的数据在关闭的那一刻就丢失了!
可以从同一个基础镜像启动任意数量的容器。 这使得扩展变得容易,因为每个容器实例都是相同且一次性的。
如果您想在生产服务器上使用 Docker,这可能会改变您处理应用程序开发的方式。 假设您的应用程序有一个变量来计算登录用户的数量。 如果它在两个容器中运行,任何一个都可以处理登录,因此每个容器都有不同的用户数。
因此,Dockerized Web 应用程序应避免将状态数据保留在变量和本地文件中。 您的应用程序可以将数据存储在 redis、MySQL 或 MongoDB 等数据库中,以便在容器实例之间保持状态。
如果从一开始就以非无状态方式开发现有应用程序,那么使用 Docker 容器部署现有应用程序可能是不切实际的。但是,您仍然可以在开发期间在 Docker 容器中运行应用程序。
这就引出了一个问题:如果您的数据库在容器中运行怎么办?
它在重新启动时也会丢失数据,因此 Docker 提供卷(volumes)和主机文件夹绑定挂载。
你可能会想,“啊,我可以通过永不停止容器来解决状态问题!”确实如此。假设您的应用程序 100% 没有错误。您的运行时是 100% 可靠的。而且操作系统永远不会崩溃。而且您永远不需要更新主机操作系统或容器本身。如果有这样的系统,你就放心使用吧!
Docker 镜像是包含库和应用程序可执行文件的文件和操作系统的快照。 本质上,镜像是创建容器的配置文件或模板。 (类似于某些计算机语言允许您定义可重用的类模板来实例化相同类型的对象。)
可以从单个镜像启动任意数量的容器。 这允许在生产服务器上进行扩展,尽管您不太可能在开发期间从同一个映像启动多个容器。
Docker Hub 提供了一个常用镜像的存储库,用于:
依赖项,例如 NGINX、MySQL、MongoDB、Elasticsearch、redis 等。 语言运行时或框架,例如 Node.js、PHP、Python、Ruby、Rust 以及您听说过的任何其他语言。 WordPress、Drupal、Joomla、Nextcloud 等应用程序(这些通常需要额外的容器,例如数据库。)
提醒:如果您想发布自己的镜像,请注册 Docker Hub 帐户。
使用 Dockerfile 配置镜像。 它通常定义:
它通常会启用日志记录、调试和远程访问。 例如,在 Node.js 开发期间,您可能希望使用 Nodemon 启动应用程序,以便在文件更改时自动重新启动它。
这将以更有效和更安全的模式运行。 对于 Node.js 部署,很可能使用标准的节点运行命令。
Docker Hub 的 Docker 镜像就像 Github 的 Git 存储库。
您创建的任何镜像都可以推送到 Docker Hub。 很少有开发人员这样做,但对于部署目的或当您想与他人共享您的应用程序时,它可能是实用的。
映像与您的 Docker Hub ID 进行名称空间分隔,以确保没有人可以使用相同的名称。 它们还有一个标签,因此您可以创建同一图像的多个版本,例如 1.0、1.1、2.0、最新等
<Your-Docker-ID>/<Your-Docker-Hub-Repository>:<tag>
例如: yourname/yourapp:latest
, craigbuckler/myapp:1.0
Docker Hub 上的官方镜像不需要 Docker ID,例如 mysql(假定 mysql:latest)、mysql:5、mysql:8.0.20 等。
容器在重新启动时不保留数据状态。 这通常是一件好事。 任何数量的容器都可以从同一个基础镜像启动,并且每个容器都可以处理传入的请求,无论它们是如何或何时启动的。
然而,一些容器——比如数据库——绝对必须保留数据,因此 Docker 提供了两种存储机制类型:
Volumes:Docker 管理的文件系统
Bind mounts:主机上的卷。
两者都可以映射到容器上的目录,例如 /data/db 用于 MongoDB 存储。
卷是持久化数据的推荐方式。 在某些情况下,这是唯一的选择——例如,MongoDB 目前不支持 Windows 或 macOS 文件系统上的绑定挂载。
bind mounts 适用在开发模式中使用,主机操作系统上的应用程序文件夹可以挂载在容器中,因此任何文件更改都会触发应用程序重启、浏览器刷新等。
可以在两个或多个容器上挂载相同的卷或绑定挂载。只读访问应该没问题,但是如果多个容器同时尝试写入同一个文件,就有可能有问题。
任何 TCP/IP 端口都可以在容器上公开,例如 MySQL 的 3306。这允许主机上的应用程序与位于 localhost:3306 的数据库系统进行通信。
在另一个容器中运行的应用程序无法与 MySQL 通信,因为 localhost 解析为自身。出于这个原因,Docker 创建了一个虚拟网络,并为每个正在运行的容器分配一个唯一的 IP 地址。然后,一个容器可以使用其地址与另一个容器进行通信。
不幸的是,每次启动容器时,Docker IP 地址都会发生变化。一个更简单的选择是创建自己的 Docker 虚拟网络。添加到该网络的任何容器都可以使用其名称与另一个容器进行通信,即 mysql:3306 解析为正确的地址。
在开发过程中,您希望两个端口都暴露给主机。该应用程序可以在 Web 浏览器中的 http://localhost/(默认端口 80)中启动,MySQL 客户端可以连接到 http://localhost:3306/。
在生产环境中,mysql 端口不需要暴露给主机。 phpapp 容器仍然可以与 mysql:3306 通信,让黑客无法破解主机上的 3306 端口。
通过仔细规划,可以创建安全性更复杂 Docker 网络,例如mysql和redis容器可以被phpapp访问,但是不能互相访问。
我们使用单个 docker 命令启动单个容器。 当需要多个容器(例如 Node.js、NGINX 和 MongoDB)的应用程序必须使用三个命令启动。 您可以按正确的顺序在三个终端中启动每一个(可能是 MongoDB,然后是 Node.js 应用程序,然后是 NGINX)。
Docker Compose 是一种用于管理具有关联卷和网络的多个容器的工具。 单个配置文件,通常命名为 docker-compose.yml,定义容器并可以在必要时覆盖 Dockerfile 设置。
为开发环境创建一个 Docker Compose 配置是很实用的。 您还也可以创建一个用于生产环境的,或许你有更好的选择……
注:本文属于原创文章,版权属于「前端达人」公众号及 qianduandaren.com 所有,未经授权,谢绝一切形式的转载