65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2021 年 4 月 23 日

CPOL

5分钟阅读

viewsIcon

7483

在本文——系列的第一篇文章——中,我们将回顾一些适用于机器学习应用程序的 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 切换当前文件夹(如果需要,则创建它)。
  • ENTRYPOINTCMD 定义了每次容器启动时执行的命令。如果同时使用这些语句,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 进行实验和训练。

容器化人工智能与机器学习:概述 - CodeProject - 代码之家
© . All rights reserved.