一次编写,随处运行(Sun Microsystems on Java 的跨平台能力,1995 年)
码头工人群(https://hub.docker.com/_/swarm)
什么是容器化?
您可能听说过虚拟机和虚拟盒,容器化与它们非常相似,但容器化更轻量级,因为它的目的只是将软件代码与操作系统及其依赖项一起打包。由于您正在打包包含其操作系统的代码,这意味着您可以在任何地方运行它并且仍然具有相同的行为,从而完全解决了在不同环境中可能发生的兼容性问题。
考虑到这一点,Docker 只是容器化的实现之一,但它是目前使用最广泛的容器化工具。在本文中,我们将只关注使用 Docker 作为容器化的手段。
码头工人术语
让我们从跳入 docker 之前必须了解的术语开始
- Docker 镜像:组件中的“镜像”,包含您的应用程序代码、操作系统及其依赖项
- Docker Image Tag:您可以将其视为 docker 映像的“版本”
- Docker Container : 一个镜像的实际运行实例,可以有多个容器运行同一个镜像
- Dockerfile:用于构建 docker 镜像的文件,您可以在此处指定新 docker 镜像将使用的基础镜像(Ubuntu?Debian?Windows Server?等),要复制的应用程序代码,以及要安装的依赖项(可以是pip installpython 或 linux 包)
- Dockerhub:这就像 GitHub,但你可以存储 docker 图像而不是代码
Dockerfile、镜像和容器(Source)
让我们尝试将应用程序容器化并运行它
对于这个例子,我们将尝试将这个在 Flask 上运行的简单 Python Web 应用程序容器化。代码可在此处获得。代码非常简单,只需要 3 个文件(crud.py, database.py, 并且requirements.txt包含所需的依赖项)。我们的高层计划如下:
- 使用已安装 Python 的基础镜像
- 复制这三个文件
- 安装所需的依赖项
- 运行应用程序
如果我们要对 Dockerfile 实施这些步骤,我们应该会得到类似这样的东西:
我们讨论过的应用程序的 Dockerfile
解释:
- FROM python:3.9.10-alpine3.15表示我们使用的是在 Alpine Linux(最轻量级的 linux)上运行的 Python 3.9.10 的基础镜像,您可以在此处使用许多其他 Python 镜像标签。(这与使用带有 Python 的基础图像的第 1 步相关)
- WORKDIR /crud_app/仅意味着我们所有的下一个命令都将在/crud_app/目录中运行
- COPY第 5 行和第 6 行中的命令与将应用程序代码复制到映像中的第 2 步相关
- EXPOSE 8000意味着我们告诉图像我们有一个在端口 8000 上运行的应用程序(您可以在此处查看应用程序配置)向外部公开
- RUN pip3 install -r requirements.txt意味着我们要运行给定的命令,即安装应用程序所需的那些要求,这与安装所需依赖项的步骤 3 相关
- CMD python3 crud.py当此映像作为容器运行时,运行此命令,即运行应用程序的命令。这与运行应用程序的第 4 步相关。
现在,最后一步是构建 docker 镜像本身,我将使用 namelaw-crud-files和 tag构建这个镜像1。用于运行它的命令是(假设我已经在文件和 Dockerfile 所在的目录中)
码头工人建造。-t law-crud-files:1
运行此命令后,您可以看到 Docker 运行了我们已经在 Dockerfile 中指定的步骤。
Docker,构建我的应用程序
最后一步是运行应用程序,让我们记住我们的应用程序在端口 8000 中运行的事实,因为我们需要将此端口映射出来,并且我们将图像命名为law-crud-files:1(格式为name:tag)。有了它,我们可以使用这个命令使用镜像运行我们的应用程序(假设我们在端口 7000 上本地运行应用程序)
docker run -d -p 7000:8000 law-crud-files:1
笔记:
- -d意味着我们将它作为后台进程运行(因为我们不必保持终端运行)
- -p 7000:8000意味着我们将本地端口 7000 映射到运行应用程序的端口 8000(还记得那EXPOSE 8000部分吗?)
您可以看到现在应用程序正在端口 7000 上运行,并且可以通过curl命令访问!
在容器化应用程序之前需要考虑的事项
如前所述,通过容器化应用程序,您解决了所有兼容性问题,并为水平升级开辟了一条更简单的途径,因为您只需为同一个图像运行多个容器。但不幸的是,在容器化应用程序之前,您应该考虑容器化的一些问题:
无国籍状态
所有将要容器化的应用程序必须是无状态的,这意味着不应在容器上保存任何数据。正如我们所说,容器不仅仅是应用程序,也是操作系统本身,这意味着如果我们要重新启动应用程序,这意味着我们也(实际上最好)需要从头开始重新启动容器,这意味着您将失去所有文件。
您可以通过使用容器外部的外部数据库(例如 AWS RDS 或 GCP Cloud SQL)来解决此问题,或者对于文件存储,您可以使用 AWS S3
图像注册表
由于有 docker 镜像,您不仅将代码文件保存在 Github 或 Gitlab 中,还可以保存使用代码文件构建的镜像。有一些服务提供了docker镜像注册服务,比如GCP中的GCR,Dockerhub,还有AWS ECR。但是这些不是免费的,所以为了你的预算也要记住它们!
自我恢复
理想情况下,docker 镜像不仅可以自己运行,还可以与更复杂的管理器一起使用,例如 Kubernetes 和 Docker Swarm,它们提供了一个自我修复系统。简单来说,如果容器的主进程宕机或者指定的健康检查方法失败,这个系统就会重启容器。有了这个,您应该确保您的应用程序能够在容器化时自行启动而无需任何手动干预。
我们的软件工程项目中的容器化
至于我们的项目(您可以在此处查看代码),它是一个 Python 网络应用程序。由于有关应用程序的几个问题,我们不会将我们的应用程序容器化:
1. Python 虚拟环境
Python 已经有一个出色的环境隔离系统,称为Virtual Environments。简单地说,它将依赖项分离到应用程序的新目录中。到目前为止,我们还没有发现任何关于 Python 依赖项的兼容性问题,无论是在每个成员的本地环境上还是在我们配置的 2 台服务器上。
2. 状态数据
尽管我们使用 AWS S3 存储文件,使用 AWS RDS 存储数据库,但我们仍然具有将用户凭证生成到文件中的功能。AWS S3 流量需要花钱,并且出于安全考虑,我们决定这些凭证文件应该只存储在 VM 中。
尽管我们没有将应用程序容器化,但 docker 和容器化仍然在我们的 CI/CD 管道中发挥着重要作用。由于通过容器化我们不必考虑任何兼容性问题,我们可以只使用 docker 镜像作为我们的 CI/CD 运行器的镜像,而无需关心 CI/CD 运行器的实际操作系统。例如在我们的部署工作中:
您可以在第 3 行中看到我们正在使用该ubuntu映像来运行管道中的命令。最好的部分是?我们不必关心运行器使用什么操作系统,只要它使用 docker 执行管道即可。
结论
容器化是开发和部署应用程序的绝佳概念,但它们的代价是对代码进行大量重构以确保它是无状态的,并且还需要额外花费来保存这些容器映像。
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除