容器化 AI 和机器学习:概述





5.00/5 (4投票s)
在本文——系列的第一篇文章——中,我们将回顾一些适用于机器学习应用程序的 Docker 基础知识。
引言
Docker 等容器技术极大地简化了软件的依赖管理和可移植性。在本系列文章中,我们将探讨 Docker 在机器学习 (ML) 场景中的用法。在本文——系列的第一篇文章——中,我们将回顾一些适用于机器学习应用程序的 Docker 基础知识。
本系列假设您熟悉机器学习、通用容器化以及 Docker。
安装 Docker
Docker 可以在多种平台运行,包括适用于 Intel/AMD 处理器的 Windows 和 macOS 的 Docker Desktop,以及适用于 Intel/AMD 和 ARM 处理器的各种 Linux 发行版的 Docker Server。您可以在 Docker 网站上找到适用于您平台的全面安装指南。
为什么选择 Docker?
Docker 是一种轻量级技术,用于在隔离的环境中打包和执行软件组件。这样的包称为“容器镜像”(或简称“镜像”),而镜像代码执行的环境称为“容器”。
Docker 技术可确保每个容器的 Python 和系统依赖项完全隔离,这比虚拟环境提供的功能更多。同时,这项技术允许在运行时环境之间实现最大的可移植性。在许多情况下,同一个容器可以在本地工作站或服务器上运行,无论是在本地还是在云端。
为了更好地理解我们在后续文章中将做出的某些设计选择,值得花一些时间了解 Docker 的基础知识。
图层
Docker 镜像由多个只读层组成。每一层只包含当前层与上一层之间的差异。当构建镜像时,只有发生更改的层及其后续层会被刷新。这就是为什么定义 Docker 层的方式至关重要,应该按照从最静态到最“动态”(最可能发生更改)的顺序排列。这可以大大缩短构建镜像所需的时间。
层数也会影响镜像大小(和构建时间),因此建议使用单个 RUN
语句执行多个 Linux 命令(单个 RUN = 单个层)。
Dockerfile
Dockerfile 定义了一个镜像。让我们看一个非常简单的例子
FROM python:3.7-slim
RUN apt-get update & apt-get install python3-numpy
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY app /app
WORKDIR app
ENTRYPOINT ["python", "app.py"]
CMD ["--input", "1234"]
上述语句的含义如下
FROM
以 <image_name>:<image_tag> 格式定义基础镜像。如果本地没有该镜像,Docker 将尝试从已知仓库(默认是 https://hub.docker.com)拉取。RUN
执行一个 Linux 命令。COPY
将本地文件从主机上下文复制到镜像中。WORKDIR
切换当前文件夹(如果需要,则创建它)。ENTRYPOINT
和CMD
定义了每次容器启动时执行的命令。如果同时使用这些语句,ENTRYPOINT
反映命令的常量部分,而CMD
反映其参数。
以下语句构建一个镜像
$ docker build -t <image_name>:<tag_name> .
请注意,末尾的 "."(点)表示当前文件夹是 Docker 上下文(简而言之,是复制到容器的文件和 Dockerfile 的根文件夹的位置)。
“Latest”并非最佳选择
默认情况下,如果未显式提供标签,Docker 会为基础镜像使用“latest”标签。与定义 Pip 或 Conda 的 Python 依赖项时指定包版本类似,您应该始终为基础镜像添加预定义的标签,而不是默认的“latest”。这可以为您节省很多麻烦,尤其是在生产环境中。虽然这不能保证每次构建的镜像都 100% 相同,但它大大降低了引入有害更改的风险。
不同平台上的进程隔离
Docker 根据主机操作系统的工作方式略有不同。在内部,Docker 依赖于四个核心 Linux 功能:联合文件系统、Linux 进程、命名空间和 cgroups。
联合文件系统(UnionFS)是一种用于处理镜像层的技术。对于 Linux 上的 Docker Server,所有容器与主机共享一个内核。
剩余的三项功能——进程、命名空间和 cgroups——可确保容器的正确隔离。对于 Windows 和 Mac 上的 Docker Desktop,会在主机上安装一个 Linux 虚拟机,所有正在运行的容器都共享该虚拟机的内核。
考虑到以上几点,很容易理解为什么在 Linux 服务器上使用默认的 root 用户运行容器是一个非常糟糕的主意。如果只有单个容器在单个专用机器上运行(这在云部署中很常见),则问题稍微不那么危险。
无论如何,您都不应该以 root 用户身份运行容器代码,即使在使用 Docker Desktop 时也是如此。
运行带数据的容器
闪电般快速的容器执行的秘密在于,当它启动时,不会复制任何数据。只会将一个(最初非常薄的)读写容器层添加到只读镜像层堆栈中。容器执行期间对文件的所有更改都以“增量”形式存储在这个新层中,使用联合文件系统。
当容器被移除时,这个读写层会随之被删除。这就是为什么您应该始终将容器数据视为临时的。如果您关心容器处理的数据,则需要一个卷。根据需求和主机环境,它可以由 Docker 实例持久化,也可以映射到本地或云文件夹。
架构很重要
Docker 并非魔法——它依赖于运行它的硬件。这意味着您仍然最有可能需要适用于 Intel/AMD 和 ARM 处理器的略有不同的镜像。
摘要
在本文中,我们回顾了一些 Docker 基础知识,重点关注在 ML 项目中常用的功能。在下一篇文章中,我们将把这些知识付诸实践。我们将创建一个简单的容器镜像,用于使用 Intel/AMD CPU 进行实验和训练。