docker - 为什么通过 ENTRYPOINT 和 tini 安装依赖项?
问题描述
我有一个关于在dask- docker上实现 Dockerfile 的问题。
FROM continuumio/miniconda3:4.8.2
RUN conda install --yes \
-c conda-forge \
python==3.8 \
[...]
&& rm -rf /opt/conda/pkgs
COPY prepare.sh /usr/bin/prepare.sh
RUN mkdir /opt/app
ENTRYPOINT ["tini", "-g", "--", "/usr/bin/prepare.sh"]
prepare.sh只是方便通过 conda、pip 和 apt 安装其他软件包。
有两件事我不明白:
- 为什么不把这些指令放在 Dockerfile 中呢?可能通过复制专用文件(requirements.txt,environment.yaml,...)间接(模块化)
- 为什么要通过 tini 执行此操作?最后,它
exec "$@"
可以启动调度程序或工作程序 - 这就是我与 tini 相关的更多内容。
这样每次您从构建的映像运行容器时,您都必须重复安装过程!?
也许我想多了,但它似乎很不寻常——但也许这是一个有充分理由的 Dockerfile 模式。
Dask 内部人员的可选奖金问题:
- 为什么将 prepare.sh 复制到
/usr/bin
(而不是 fx 到/tmp
)? - 创建目录的目的是什么
/opt/app
?
解决方案
这实际上取决于入口点脚本正在安装的文件的性质和用途。总的来说,我喜欢将其分为几类:
主机系统上经常更改的本地文件,将被滚动到最终映像中以进行生产发布。这适用于正在开发并需要在容器中测试的应用程序的源代码。您希望每次重建映像时将这些复制到运行时中。在 Dockerfile 中使用 COPY。
来自其他地方的频繁更改和/或特定于部署环境的文件。这就像来自 Hashicorp 保险库的秘密、网络设置、服务器配置等……可能会一直下载到容器中,即使它投入生产也是如此。入口点脚本应该下载这些文件,它应该根据主机注入的环境变量来决定从哪里获取哪些文件。
库、可执行程序(在
/bin
、/usr/local/bin
等...下)以及除计划升级期间外特别不应更改的内容。通常使用 安装的任何东西pip
,maven
或执行依赖管理的其他程序,以及使用apt-get
或等效安装的任何东西。这些文件不应从 Dockerfile或从入口点脚本。更好的是构建您的基础镜像,并安装所有依赖项,然后使用该镜像作为 FROM 源进行进一步开发。这有许多优点:它确保了一个稳定的、位于中心位置的起始平台,每个人都可以使用它进行开发和测试(它在重要的地方强制统一);它可以防止您对托管这些库的服务器进行攻击(不断地从 pypy.org 重新下载所有这些库是一种非常糟糕的形式……必须有人为该带宽付费);它使构建速度更快;如果您有单独的安全团队,这可能有助于减少他们需要扫描的文件数量。
您可能正在查看#3,但我将所有三个都包括在内,因为我认为这是对事物进行分类的有用方法。
推荐阅读
- automapper - AutoMapper 为大写和下划线映射错误的字段
- python - django rest框架中的Pytest断言错误
- sql - 有没有更有效的方法将多个 select 语句的第一行聚合成一个结果?
- vue.js - “TypeError:时刻不是函数”
- excel - 网页抓取:innertext
- laravel - Laravel ORM 关系,授权用户
- sql - 将触发器 NEW 设置为 UPDATE 的返回值
- python - 数值分析算法实现导致无限循环
- bots - 您如何公开 Discord Bot?
- c# - 我们可以在 C# 代码中调用 Visual Studio 的“查找所有引用”吗?如何?