如何基于现有镜像创建新的 docker 镜像,但包含更多 Python 包?

Posted

技术标签:

【中文标题】如何基于现有镜像创建新的 docker 镜像,但包含更多 Python 包?【英文标题】:How to create a new docker image based on an existing image, but including more Python packages? 【发布时间】:2021-10-27 00:20:01 【问题描述】:

假设我已经像这样提取了 NVIDIA NGC PyTorch docker 映像: docker pull nvcr.io/nvidia/pytorch:21.07-py3

那我要添加这些python包:omegaconf wandb pycocotools?

如何使用原始 Docker 映像和其他 Python 包创建新的 Docker 映像?

另外,我如何在整个组织中分发新图像?

【问题讨论】:

只需编写一个 Dockerfile,从 NVIDIA 映像开始并安装附加包。 @MarcelloRomani 好的,怎么样? 抱歉,这是家庭作业 :-) 一旦你知道如何编写一个基本的 Dockerfile 并安装几个 python 包,它就很简单了。 对一个问题投反对票的原因之一是:“这个问题没有显示出任何研究成果”。 @MarcelloRomani “没有表现出任何研究努力”的批评不再有意义,因为我现在已经回答了我自己的问题。这证明我做了足够的研究,不是吗? 【参考方案1】:

创建一个名为Dockerfile 的文件。添加下面解释的行。

添加FROM 行来指定基础镜像:

FROM nvcr.io/nvidia/pytorch:21.07-py3

将 Pip 升级到最新版本:

RUN python -m pip install --upgrade pip

安装您需要的其他 Python 包:

RUN python -m pip install omegaconf wandb pycocotools

总的来说,Dockerfile 看起来像这样:

FROM nvcr.io/nvidia/pytorch:21.07-py3
RUN python -m pip install --upgrade pip
RUN python -m pip install omegaconf wandb pycocotools

在与Dockerfile 相同的目录中,运行此命令以构建新映像,将my-new-image 替换为您选择的名称:

docker build -t my-new-image .

这对我有用,但 Pip 会生成有关以 root 用户身份安装软件包的警告。我发现最好忽略这个警告。请参阅此答案末尾的注释以了解原因。

新的 docker 镜像现在应该出现在您的系统上:

$ docker images
REPOSITORY                         TAG                            IMAGE ID       CREATED              SIZE
my-new-image                       latest                         082f76972805   13 seconds ago   15.1GB
nvcr.io/nvidia/pytorch             21.07-py3                      7beec3ff8d35   5 weeks ago          15GB
[...]

您现在可以运行新映像 ..

$ docker run --gpus all -it --rm --ipc=host my-new-image

.. 并验证它是否具有额外的 Python 包:

# python -m pip list | grep 'omegaconf\|wandb\|pycocotools'
omegaconf                     2.1.1
pycocotools                   2.0+nv0.5.1
wandb                         0.12.1

The Docker Hub Repositories documentation 详细说明了以下必要步骤:

    创建存储库(可能是私有的) 推送图片 添加协作者 从存储库中拉取图像

注意:非 root 用户的问题: 尽管不以 Docker 根用户身份运行 Docker 容器被认为是“最佳实践”,但实际上非 root 用户可能会增加一些复杂性.

你可以在你的 docker 文件中创建一个非 root 用户,如下所示:

RUN useradd -ms /bin/bash myuser
USER myuser
ENV PATH "$PATH:/home/myuser/.local/bin"

但是,如果您使用 -v 标志运行具有已安装卷的容器,则将根据其用户 ID 或组 ID 是否与主机系统中的用户或组匹配,授予 myuser 对这些卷的访问权限。您可以修改 useradd 命令行以指定所需的用户 ID 或组 ID,但生成的图像当然不能移植到具有不同 ID 的系统。

此外,似乎存在阻止非 root 用户访问指向 fscrypt 加密文件夹的已安装卷的限制。但是,这对我使用 root docker 用户来说很好。

由于这些原因,我发现让容器以 root 身份运行是最简单的。

【讨论】:

我从未见过使用python -m pip 添加 Python 包的示例 Dcokerfile,但我在这里使用它是因为我知道这是调用 Pip 的正确方法。当直接使用pip 命令时,有可能pippython 实际指向不同版本的Python。如果我们改用python -m pip,就可以避免这种可能性。 出于好奇,我正在研究的一件事是,是否可以使用基本映像的包管理器安装这些 Python 包。这应该消除“不要将 pip 用作 root”警告。 这个最近的答案在 Dockerfile 中添加了一个新用户并在运行 Pip 之前切换到该用户。也建议先升级Pip:***.com/questions/68673221/… 显然 docker 最佳实践是不要在 docker 容器中使用 root 帐户。 docs.docker.com/develop/develop-images/…sysdig.com/blog/dockerfile-best-practices 非 root docker 用户根据与主机系统用户 ID 或组 ID 匹配的用户 ID 或组 ID 被授予对已挂载卷的文件访问权限。但是,如果 docker 映像假定主机系统具有具有特定 ID 的用户或组,则它们是不可移植的。此外,这似乎根本不适用于fscrypt 文件系统。只有 root docker 用户似乎能够访问未锁定的 fscrypt 文件系统中的文件。

以上是关于如何基于现有镜像创建新的 docker 镜像,但包含更多 Python 包?的主要内容,如果未能解决你的问题,请参考以下文章

Docker 数据管理容器互联 与 镜像的创建编译(DockerFile)

docker 镜像分层原理

如何用Dockerfile创建镜像

Docker镜像的创建

从头基于空镜像scratch创建一个新的Docker镜像

Docker------Docker数据管理与Dockerfile镜像创建