我在 Docker 上犯的错误

今天犯了一个错误,犯这个错误的原因是没有理解 docker 的设计哲学,大概花了 3 个小时来折腾一个事情。

起因

一个容器没有安装 python 的一些依赖库,我在容器里面安装了依赖库,不想每次都安装这些依赖库,所以我想把这个容器保存成新的镜像。

错误的方法

有两种方式来解决这个问题。
方式一,构建新的 Dockerfile。
方式二,对一个正在运行的容器,通过 commit 来创建新的镜像。

反思

我选择了方式二,我把容器当虚拟机使了,这是没有理解 Docker 设计的哲学。

找了一文章,这文章总结的很好,有利于我去了解 docker 的设计哲学,我就把他翻译在下面。

使用 Docker 不要做的几件事情

所以你最终屈服于容器,发现它们解决了很多问题并且有很多优势

  1. 第一:容器是不可变的——操作系统、库版本、配置、文件夹和应用程序都包含在容器中。您保证在 QA 中测试过的相同镜像将以相同的行为到达生产环境。
  2. 第二:容器是轻量级的——容器的内存占用很小。容器将只为主进程分配内存,而不是数百或数千 MB。
  3. 第三:容器速度快——您可以像启动典型的 Linux 进程一样快地启动容器。您可以在几秒钟内启动一个新容器,而不是几分钟。

然而,许多用户仍然像对待典型的虚拟机一样对待容器,而忘记了容器有一个重要的特性:容器是一次性的。
“容器是短暂的”。

这种特性迫使用户改变他们应该如何处理和管理容器的思维方式;我将解释您应该做的事情以继续发挥容器的最大优势:

1) 不要将数据存储在容器中——容器可以被停止、销毁或替换。在容器中运行的应用程序版本 1.0 应该很容易被版本 1.1 替换,而不会产生任何影响或数据丢失。因此,如果您需要存储数据,请在一个卷中进行。在这种情况下,您还应该注意两个容器是否在同一卷上写入数据,因为这可能会导致损坏。确保您的应用程序设计为写入共享数据存储。

2) 不要将你的应用程序分成两部分——正如一些人将容器视为虚拟机一样,他们中的大多数人倾向于认为他们应该将他们的应用程序部署到现有的正在运行的容器中。在需要持续部署和调试的开发阶段可能是这样;但是对于QA和 p_production_ 的持续交付 (CD) 管道,您的应用程序应该是镜像的一部分。请记住:容器是不可变的。

**3) 不要创建大镜像——大镜像将更难分发。确保您只有运行应用程序/进程所需的文件和库。不要安装不必要的包或运行将许多文件下载到新图像层的“更新” *(yum 更新)* 。

4) 不要使用单层镜像——为了有效利用分层文件系统,总是为你的操作系统创建你自己的基础镜像层,另一层用于用户名定义,另一层用于运行时安装,另一层用于配置,最后是您的应用程序的另一层。重新创建、管理和分发您的图像将更加容易。

5) 不要从正在运行的容器创建镜像——换句话说,不要使用“docker commit”来创建镜像。这种创建镜像的方法不可重现,应完全避免。始终使用 Dockerfile 或任何其他完全可重现的 S2I(源到图像)方法,如果将 Dockerfile 存储在源代码控制存储库 (git) 中,则可以跟踪对 Dockerfile 的更改。

6) 不要只使用“latest”标签– latest 标签就像 Maven 用户的“SNAPSHOT”。由于容器的分层文件系统性质,因此鼓励使用标签。当您在几个月后构建您的镜像并发现您的应用程序无法运行时,您不希望有惊喜,因为父层(Dockerfile 中的 FROM)被新版本替换,它不向后兼容或因为错误从构建缓存中检索到“最新”版本。在生产环境中部署容器时也应避免使用“最新”标签,因为您无法跟踪正在运行的镜像版本。

7) 不要在单个容器中运行多个进程——容器非常适合运行单个进程(http 守护进程、应用程序服务器、数据库),但如果你有多个进程,你可能会在管理上遇到更多麻烦,检索日志,并单独更新进程。

8) 不要在容器中存储凭据。使用环境变量——您不想在图像中硬编码任何用户名/密码。使用环境变量从容器外部检索该信息。这个原则的一个很好的例子是Postgres 图像

9) 不要以 root 用户身份运行进程—— “默认情况下,docker 容器以 root 身份运行。(…)随着 docker 的成熟,可能会出现更安全的默认选项。目前,要求 root 对其他人来说是危险的,可能不会在所有环境中都可用。您的映像应使用 USER 指令为容器指定一个非根用户以“身份运行” 。 (来自Docker Image 作者指南

10) 不要依赖 IP 地址——每个容器都有自己的内部 IP 地址,如果您启动和停止容器,它可能会改变。如果您的应用程序或微服务需要与另一个容器通信,请使用环境变量将正确的主机名和端口从一个容器传递到另一个容器。

10 things to avoid in docker containers | Red Hat Developer

docker commit新镜像之后删除旧镜像 – GoldLeaf的个人空间 – OSCHINA – 中文开源技术交流社区

发表评论