随着机器学习应用日益复杂,将模型从开发推向生产不再只是写好代码那么简单。关键在于确保应用能在不同环境中一致运行。这正是容器化大显身手的地方。但究竟什么是容器化?为什么它能为机器学习工作流带来颠覆性改变?
容器化是一种轻量、可移植的方式,它将应用及其所有依赖、库与配置打包到称为“容器”的单一单元中。与传统虚拟机(VM)不同,容器共享主机系统的操作系统,从而更快、更高效,也更易扩展。
对数据科学家和机器学习工程师而言,这意味着您可以在本地机器上构建模型,并将其部署到任意位置——无论是云平台、服务器,还是同事的笔记本电脑——而无需担心兼容性问题。
在本教程中,我们将使用 Docker 和 Kubernetes 将一个机器学习应用容器化。完成后,您将掌握:
为您的 ML 应用构建 Docker 容器。
使用 Kubernetes 部署并管理容器化应用。
在生产环境中扩展并监控 ML 应用。
如果您是 Docker 新手,请查看我们的指南: 从零开始学习 Docker 。您也可以学习我们的课程: 使用 Docker 和 Kubernetes 的容器化与虚拟化 。
先决条件
在开始之前,您应具备 Python、机器学习工作流以及命令行的基础知识。建议熟悉 Docker 概念 (如镜像、容器、基础命令),而 Kubernetes 的基础知识 可选,但对部署与扩展很有帮助。
什么是容器化应用?
容器化应用是将软件应用与其所有依赖、库和配置一起打包到一个轻量的单元(容器)中。对于机器学习应用,这意味着将从已训练的模型到所需的 Python 库全部打包,确保您的应用在任何地方都以相同方式运行。
传统应用 vs 容器化应用
为什么容器化对机器学习应用很重要
在开发机器学习应用时,您很可能遇到过“只在我机器上能跑”的问题。也许您的模型在笔记本上运行完美,但部署到云端就失败;或者同事因安装了不同版本的 scikit-learn 或 TensorFlow 而无法复现您的结果。
容器化通过为您的应用创建一致且隔离的环境来解决这些问题。以下是容器化应用在机器学习中的优势:
一致性 :从开发到测试再到生产,应用在不同环境中的行为保持一致。
隔离性 :每个容器在其独立环境中运行,避免不同应用或依赖之间的冲突。
可移植性 :容器可在任何支持容器化的平台上运行,无论是本地机器、云服务还是本地服务器。
可扩展性 :需要处理更多请求?通过运行多个实例,容器可轻松实现水平扩展。
容器 vs 虚拟机
容器和虚拟机(VM)都用于隔离应用,但在运行方式与适用场景上有显著差异。以下是关键区别与优势概览:
方面
容器
虚拟机(VM)
架构
共享主机 OS 内核;轻量且相互隔离。
包含完整 OS;运行在虚拟机监控器之上。
性能
轻量、启动快、资源开销低。
更重、启动慢,因完整 OS 带来更高资源占用。
可移植性
高度可移植;跨环境表现一致。
受 OS 依赖影响,移植性较差,可能遇到兼容性问题。
可扩展性
可借助 Kubernetes 等编排工具轻松扩展。
可扩展,但需要更多资源与管理投入。
安全性
依赖主机 OS 安全性;隔离度低于 VM。
因独立 OS 带来更强隔离;更适合敏感应用。
对于机器学习应用,这些差异尤为重要。当您需要扩展模型以处理更多预测请求,或想部署多个版本进行 A/B 测试时,容器能提供所需的敏捷性与资源效率。
想进一步了解容器化与虚拟化,请查看该学习路径: 使用 Docker 和 Kubernetes 的容器化与虚拟化 。
如何将机器学习应用容器化
在下文中,我们将按步骤介绍如何将应用容器化:
1. 环境准备
在开始将机器学习应用容器化之前,需要安装必要工具并准备环境。本节将指导您安装 Docker,并准备一个简单的机器学习应用以进行容器化。
所需工具
要将机器学习应用容器化,您需要以下工具:
Docker :用于构建、分发和运行容器的平台。
Kubernetes (可选):用于大规模管理容器的编排工具。(我们将在后文介绍。)
先从安装 Docker 开始。
步骤 1:安装 Docker
Docker 可用于 Windows、macOS 和 Linux。以下是在您的系统上安装 Docker 的步骤。
Windows/macOS:
前往 Docker 官网 。
下载并安装 Docker Desktop。
按照安装向导的提示完成安装。
Linux(Ubuntu/Debian):
打开终端并运行以下命令安装 Docker:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$( dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $( lsb_release -cs ) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
sudo docker --version 技术支持
该安装过程会将 Docker 软件源添加到系统,使用 GPG 密钥验证其真实性,并安装 Docker 引擎及其命令行工具。
步骤 2:验证 Docker 安装
安装完成后,在命令行中运行以下命令验证是否正常工作:
docker --version
docker run hello-world技术支持
这将拉取一个轻量级测试镜像并以容器形式运行。如果成功,您会看到一条欢迎信息,确认安装正常,如下所示:
Hello from Docker! 技术支持
2. 准备您的机器学习应用
现在已安装 Docker,接下来准备一个简单的机器学习应用进行容器化。本文将使用一个基础的 Python 脚本,它加载一个预训练模型并通过 Flask API 提供预测服务。
步骤 1:创建一个简单的 ML 应用
为您的项目创建一个新目录,并添加以下文件:
app.py :通过 Flask API 提供预测的 Python 脚本。
requirements.txt :列出 Python 依赖的文件。
以下是 app.py 的代码:
from sklearn. datasets import load_iris
from sklearn. ensemble import RandomForestClassifier
from sklearn. model_selection import train_test_split
from flask import Flask, request, jsonify
import numpy as np
app = Flask( __name__)
iris = load_iris( )
X, y = iris. data, iris. target
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size= 0.2 , random_state= 42 )
model = RandomForestClassifier( random_state= 42 )
model. fit( X_train, y_train)
@app. route ( '/predict' , methods= [ 'POST' ] )
def predict ( ) :
features = request. json[ 'features' ]
prediction = model. predict( [ features] )
return jsonify( { 'prediction' : int ( prediction[ 0 ] ) ,
'class_name' : iris. target_names[ prediction[ 0 ] ] } )
if __name__ == '__main__' :
app. run( host= '0.0.0.0' , port= 5000 ) 技术支持
该代码加载 Iris 数据集,训练 随机森林分类器 ,并设置一个 Flask API 端点来接收特征值并返回预测。我们将其构建为 Web 服务,以便更适合容器化。
步骤 2:创建 requirements.txt
requirements.txt 文件列出脚本运行所需的 Python 库。与 app.py 位于同一目录下创建该文件:
scikit-learn== 1.3 .0
numpy == 1.24 .3
flask == 2.0 .1技术支持
这指定了我们的应用所需的 Python 包的确切版本。固定版本可确保容器化应用的一致性与可复现性。
现在环境已就绪,ML 应用也准备完毕,我们可以开始构建第一个 Docker 容器。下一节将编写 Dockerfile ,并为基于 Flask 的 ML 应用构建 Docker 镜像。
3. 构建您的第一个 Docker 容器
现在机器学习应用已就绪,下一步是使用 Docker 将其容器化。这需要创建一个 Dockerfile,它是一份包含构建 Docker 镜像指令的脚本。镜像构建完成后,我们即可将其作为容器运行。
Dockerfile 示例:编写 Dockerfile
Dockerfile 是一份文本文件,包含组装镜像所需的全部命令。以下是为我们的 Flask 型 ML 应用创建 Dockerfile 的方法。
在与 app.py 和 requirements.txt 同一目录下,创建名为 Dockerfile 的新文件(无扩展名)。
将以下内容添加到 Dockerfile 中:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD [ "python" , "app.py" ] 技术支持
说明:
FROM python:3.9-slim :使用官方 Python 3.9 slim 镜像作为基础镜像。slim 版本轻量,适合容器化应用。
WORKDIR /app :将容器内的工作目录设为 /app 。后续命令均在该目录下运行。
COPY requirements.txt . :将本地的 requirements.txt 复制到容器中。
RUN pip install --no-cache-dir -r requirements.txt :安装 requirements.txt 中列出的 Python 依赖。使用 --no-cache-dir 可避免缓存从而减小镜像体积。
COPY . . :将本地当前目录的所有文件复制到容器的 /app 目录。
EXPOSE 5000 :暴露 Flask 应用监听的 5000 端口。
CMD ["python", "app.py"] :定义容器启动时运行 Flask 应用的命令。
构建并测试 Docker 镜像
编写好 Dockerfile 后,我们就可以构建镜像并以容器形式运行。
步骤 1:构建 Docker 镜像
在终端运行以下命令构建 Docker 镜像:
docker build -t ml-flask-app . 技术支持
该命令会基于当前目录下的 Dockerfile 构建镜像。标志 -t ml-flask-app 为镜像打上 ml-flask-app 的标签,便于后续引用。
步骤 2:运行 Docker 容器
镜像构建完成后,使用以下命令将其作为容器运行:
docker run -p 5000 :5000 ml-flask-app技术支持
该命令基于 ml-flask-app 镜像启动一个容器。标志 -p 5000:5000 将本机 5000 端口映射到容器内 5000 端口,便于通过浏览器或 curl 等工具访问 Flask 应用。
步骤 3:测试容器化应用
打开新的终端窗口,向容器内运行的 Flask 应用发送测试请求:
curl -X POST -H "Content-Type: application/json" -d '{"input": [5.1, 3.5, 1.4, 0.2]}' http://localhost:5000/predict技术支持
您将看到类似如下的响应:
{
"prediction" : 0
} 技术支持
这意味着容器化的 Flask 应用已成功运行,可对外提供预测服务。
调试常见问题
如果在构建或运行容器时遇到问题,以下建议可帮助您排查:
查看 Docker 日志: 使用以下命令查看运行中容器的日志:
docker logs < container_id> 技术支持
验证 Dockerfile 语法: 仔细检查 Dockerfile 是否有拼写或语法错误。
检查端口冲突: 确保本机 5000 端口未被占用。如已占用,可将容器映射到其他端口,例如:
docker run -p 5001 :5000 ml-flask-app技术支持
重新构建镜像:
如修改了 Dockerfile 或应用代码,请使用以下命令重新构建:
docker build -t ml-flask-app . 技术支持
在成功构建并测试 Docker 容器后,下一步是学习如何管理和扩展容器化应用。接下来我们将探索如何使用 Kubernetes 部署并扩展 ML 应用。
想获取更多 Docker 项目,请查看我们的指南: 10 个 Docker 项目灵感:从入门到进阶 。
运行您的容器化应用
既然我们已构建好 Docker 容器,接下来看看如何有效管理它。本节将带您了解启动、停止和检查容器的常用 Docker 命令,以及如何处理日志和端口。
使用 Docker 管理容器
Docker 提供了一组强大的命令来管理容器。让我们了解最常用的命令。
启动容器
要从镜像启动一个容器,使用 docker run 命令。例如:
docker run -p 5000 :5000 ml-flask-app技术支持
该命令基于 ml-flask-app 镜像启动容器,并将本机 5000 端口映射到容器 5000 端口。
如果希望在后台运行容器(分离模式),请添加 -d 标志:
docker run -d -p 5000 :5000 ml-flask-app技术支持
这样容器会在后台运行,释放您的终端。
停止容器
要停止一个运行中的容器,先使用以下命令获取容器 ID:
docker ps 技术支持
该命令会列出所有运行中的容器及其 ID、名称和其他信息。获得容器 ID 后,使用如下命令停止容器:
docker stop < container_id> 技术支持
例如:
docker stop a1b2c3d4e5f6技术支持
检查容器
要查看容器的详细信息,使用 docker inspect 命令:
docker inspect < container_id> 技术支持
它将输出 JSON 格式的详情,如容器的网络设置、挂载卷和环境变量等。
列出容器
要查看所有容器(包括运行中与已停止),使用:
docker ps -a 技术支持
这有助于检查容器状态并查找容器 ID。
处理日志和端口
日志与端口对调试和访问容器化应用至关重要。让我们看看如何使用它们。
查看容器日志
要查看运行中容器的日志,使用:
docker logs < container_id> 技术支持
例如:
docker logs a1b2c3d4e5f6技术支持
该命令会显示应用的输出,包括任何错误或控制台信息。若希望实时跟随日志(类似于 tail -f ),可添加 -f 标志:
docker logs -f < container_id> 技术支持
端口映射
运行容器时,可以使用 -p 标志将容器端口映射至本机。例如:
docker run -p 5000 :5000 ml-flask-app技术支持
该命令将容器内的 5000 端口映射到本机 5000 端口。如果 5000 端口已被占用,可映射到其他端口,例如:
docker run -p 5001 :5000 ml-flask-app技术支持
现在,您的 Flask 应用可通过 http://localhost:5001 访问。
检查端口绑定
要查看运行中容器的端口映射,使用:
docker port < container_id> 技术支持
该命令会列出容器的端口映射,有助于排查连通性问题。下一节我们将介绍如何在 Kubernetes 上部署容器化的 ML 应用并实现规模化管理。
借助 Kubernetes 扩展
应用容器化后,我们可以使用 Kubernetes 进行部署。Kubernetes 能自动化容器化应用的部署、扩展与管理,使处理大规模工作负载更轻松。本节我们将在 Kubernetes 集群上部署我们的 ML 应用。
在 Kubernetes 上部署容器
Kubernetes 使用 YAML 文件来定义应用的期望状态。这些文件描述容器应如何部署、扩展与管理。先为基于 Flask 的 ML 应用创建一个 Kubernetes 部署。
步骤 1:编写 Kubernetes 部署 YAML 文件
创建名为 ml-flask-app-deployment.yaml 的文件,并填入以下内容:
apiVersion : apps/v1
kind : Deployment
metadata :
name : ml- flask- app
spec :
replicas : 3
selector :
matchLabels :
app : ml- flask- app
template :
metadata :
labels :
app : ml- flask- app
spec :
containers :
- name : ml- flask- app
image : ml- flask- app
ports :
- containerPort : 5000 技术支持
该 YAML 文件定义了:
一个名为 ml-flask-app 的 Deployment。
三个副本,确保高可用性。
使用我们之前构建的 ml-flask-app 镜像的容器。
容器端口 5000,即 Flask 应用监听的端口。
步骤 2:部署应用
在 Kubernetes 上部署应用,使用 kubectl apply 命令:
kubectl apply -f ml-flask-app-deployment.yaml技术支持
该命令会指示 Kubernetes 创建 YAML 文件中定义的资源。您可以使用以下命令查看部署状态:
kubectl get deployments技术支持
该命令会显示部署状态,包括正在运行的副本数。
步骤 3:暴露应用
要使应用可从 Kubernetes 集群外部访问,需要创建 Service。创建名为 ml-flask-app-service.yaml 的文件,并填入以下内容:
apiVersion : v1
kind : Service
metadata :
name : ml- flask- app- service
spec :
type : LoadBalancer
ports :
- port : 80
targetPort : 5000
selector :
app : ml- flask- app技术支持
该 YAML 文件定义了:
名为 ml-flask-app-service 的 Service。
LoadBalancer 类型,用于将应用暴露到互联网。
将外部 80 端口映射到内部 5000 端口。
使用以下命令应用 Service:
kubectl apply -f ml-flask-app-service.yaml技术支持
您可以用以下命令查看 Service 状态:
kubectl get services技术支持
该命令会显示应用可访问的外部 IP 地址。
扩展与监控
Kubernetes 让应用扩展和性能监控变得轻松。让我们来看具体做法。
扩展应用
要扩展应用,可更新部署中的副本数量。例如将副本数扩展到 5,运行:
kubectl scale deployment ml-flask-app --replicas = 5 技术支持
您也可以在 YAML 文件中更新 replicas 字段并重新应用:
spec :
replicas : 5 技术支持
然后运行:
kubectl apply -f ml-flask-app-deployment.yaml技术支持
监控应用
Kubernetes 提供多种工具监控我们的应用。下面看看常用工具。
使用 kubectl logs 查看特定 Pod 的日志:
kubectl logs < pod_name>
技术支持
使用 kubectl get pods 检查 Pod 状态:
kubectl get pods技术支持
使用 kubectl top 查看 CPU 与内存使用:
kubectl top pods技术支持
自动扩缩容
Kubernetes 还支持 Horizontal Pod Autoscaler(HPA),可基于 CPU 或内存使用率自动调整 Pod 数量。启用自动扩缩容:
kubectl autoscale deployment ml-flask-app --cpu-percent= 50 --min = 3 --max = 10 技术支持
这将确保部署根据 CPU 使用率在 3 到 10 个副本间自动伸缩。
Kubernetes 部署最佳实践
在 Kubernetes 上部署应用时,建议遵循以下最佳实践。
使用资源限额
为容器定义 CPU 和内存限制,防止资源耗尽:
resources :
limits :
cpu : "1"
memory : "512Mi" 技术支持
使用存活与就绪探针
添加健康检查,确保应用正确运行:
livenessProbe :
httpGet :
path : /health
port : 5000
initialDelaySeconds : 5
periodSeconds : 10
readinessProbe :
httpGet :
path : /ready
port : 5000
initialDelaySeconds : 5
periodSeconds : 10
技术支持
使用命名空间
使用命名空间组织资源,避免冲突:
kubectl create namespace ml-app
kubectl apply -f ml-flask-app-deployment.yaml -n ml-app技术支持
下一节我们将介绍优化 Dockerfile、管理依赖以及确保安全性的技巧。
容器化 ML 应用的最佳实践
对机器学习应用进行容器化会面临一些挑战,比如大型依赖的管理、可复现性的保证以及安全维护。以下最佳实践可帮助您应对这些挑战,构建健壮的容器化 ML 应用。
优化 Dockerfile
优化良好的 Dockerfile 能显著缩短构建时间并减小镜像体积。以下是一些优化技巧:
使用多阶段构建
多阶段构建允许我们在单个 Dockerfile 中使用多个 FROM 语句。它通过丢弃中间阶段中不必要的文件和依赖来减小最终镜像体积。例如:
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt
COPY . .
FROM python:3.9-slim
WORKDIR /app
COPY --from = builder /root/.local /root/.local
COPY --from = builder /app .
ENV PATH = /root/.local/bin:$PATH
EXPOSE 5000
CMD [ "python" , "app.py" ] 技术支持
该 Dockerfile:
使用 builder 阶段安装依赖并构建应用。
仅将必要文件(如已安装依赖和应用代码)复制到最终镜像,从而减小体积。
减少层数
Dockerfile 中的每条指令都会创建一个新层。要减少层数并减小镜像体积:
将多个 RUN 命令用 && 合并为一个命令。
优先使用 COPY 而非 ADD ,除非确实需要 ADD 的额外功能。
例如:
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential && \
rm -rf /var/lib/apt/lists/*技术支持
使用轻量级基础镜像
选择轻量级基础镜像,如 python:3.9-slim ,而非更大的 python:3.9 。slim 镜像仅包含必要包,可有效减小体积。
管理依赖与可复现性
可复现性对机器学习工作流至关重要。以下是管理依赖并确保可复现性的方法。
使用 requirements.txt 或 pipen
将所有 Python 依赖列在 requirements.txt 文件中,或使用 pipenv 进行管理。例如:
scikit-learn== 1.3 .0
numpy == 1.24 .3
Flask == 2.3 .2技术支持
在 Dockerfile 中安装依赖:
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt技术支持
固定依赖版本
始终固定依赖版本以避免意外变动。例如:
scikit-learn== 1.3 .0
numpy == 1.24 .3
Flask == 2.3 .2技术支持
使用环境变量进行配置
用环境变量进行应用配置,而非硬编码。这样能让容器在不同环境中更灵活、更易配置。例如:
ENV MODEL_PATH = /app/models/model.pkl技术支持
然后在应用中访问该环境变量:
import os
model_path = os. getenv( 'MODEL_PATH' ) 技术支持
安全性考量
安全是容器化应用的关键。以下是保护 ML 应用的最佳实践:
避免以 root 身份运行
以 root 用户运行容器会带来安全风险。应创建非 root 用户,并以该用户运行容器。例如:
RUN useradd -m myuser
USER myuser
WORKDIR /home/myuser/app
COPY --chown = myuser:myuser . .
CMD [ "python" , "app.py" ] 技术支持
扫描镜像漏洞
使用 Trivy 或 Clair 等工具扫描 Docker 镜像中的漏洞。例如使用 Trivy 扫描镜像:
trivy image ml-flask-app技术支持
安全地管理机密
切勿在 Dockerfile 或应用代码中硬编码敏感信息(如 API 密钥或数据库凭据)。应使用 Kubernetes Secrets 或 Docker Secrets 管理敏感数据。例如,在 Kubernetes 中:
apiVersion : v1
kind : Secret
metadata :
name : my- secret
type : Opaque
data :
api_key : <base64- encoded- api- key> 技术支持
然后在部署中将该机密作为环境变量挂载:
env :
- name : API_KEY
valueFrom :
secretKeyRef :
name : my- secret
key : api_key技术支持
测试与调试
测试与调试对确保容器化应用按预期运行至关重要。以下是一些建议:
本地测试
在部署到 Kubernetes 之前,使用 Docker 在本地测试容器。例如:
docker run -p 5000 :5000 ml-flask-app技术支持
使用日志进行调试
使用 docker logs 或 kubectl logs 调试容器化应用中的问题。例如:
docker logs < container_id>
kubectl logs < pod_name> 技术支持
自动化测试
使用 CI/CD 流水线自动化容器化应用的测试与部署。GitHub Actions、GitLab CI 或 Jenkins 等工具可帮助我们搭建自动化工作流。
遵循这些最佳实践,我们可以构建高效、可复现且安全的容器化机器学习应用。从优化 Dockerfile 到管理依赖与确保安全,这些策略将帮助我们简化 ML 工作流,并自信地部署模型。
结语
使用 Docker 和 Kubernetes 对机器学习应用进行容器化,可简化部署、确保可复现性并增强可扩展性。通过遵循优化 Dockerfile、管理依赖与重视安全等最佳实践,我们能够构建健壮、高效且安全的 ML 工作流。
若想继续学习容器化并强化您的机器学习工作流,请查看以下课程:
随着机器学习应用日益复杂,将模型从开发推向生产不再只是写好代码那么简单。关键在于确保应用能在不同环境中一致运行。这正是容器化大显身手的地方。但究竟什么是容器化?为什么它能为机器学习工作流带来颠覆性改变?
容器化是一种轻量、可移植的方式,它将应用及其所有依赖、库与配置打包到称为“容器”的单一单元中。与传统虚拟机(VM)不同,容器共享主机系统的操作系统,从而更快、更高效,也更易扩展。
对数据科学家和机器学习工程师而言,这意味着您可以在本地机器上构建模型,并将其部署到任意位置——无论是云平台、服务器,还是同事的笔记本电脑——而无需担心兼容性问题。
在本教程中,我们将使用 Docker 和 Kubernetes 将一个机器学习应用容器化。完成后,您将掌握:
如果您是 Docker 新手,请查看我们的指南:从零开始学习 Docker。您也可以学习我们的课程:使用 Docker 和 Kubernetes 的容器化与虚拟化。
先决条件
在开始之前,您应具备 Python、机器学习工作流以及命令行的基础知识。建议熟悉Docker 概念(如镜像、容器、基础命令),而Kubernetes 的基础知识可选,但对部署与扩展很有帮助。
什么是容器化应用?
容器化应用是将软件应用与其所有依赖、库和配置一起打包到一个轻量的单元(容器)中。对于机器学习应用,这意味着将从已训练的模型到所需的 Python 库全部打包,确保您的应用在任何地方都以相同方式运行。
传统应用 vs 容器化应用
为什么容器化对机器学习应用很重要
在开发机器学习应用时,您很可能遇到过“只在我机器上能跑”的问题。也许您的模型在笔记本上运行完美,但部署到云端就失败;或者同事因安装了不同版本的 scikit-learn 或 TensorFlow 而无法复现您的结果。
容器化通过为您的应用创建一致且隔离的环境来解决这些问题。以下是容器化应用在机器学习中的优势:
容器 vs 虚拟机
容器和虚拟机(VM)都用于隔离应用,但在运行方式与适用场景上有显著差异。以下是关键区别与优势概览:
方面
容器
虚拟机(VM)
架构
共享主机 OS 内核;轻量且相互隔离。
包含完整 OS;运行在虚拟机监控器之上。
性能
轻量、启动快、资源开销低。
更重、启动慢,因完整 OS 带来更高资源占用。
可移植性
高度可移植;跨环境表现一致。
受 OS 依赖影响,移植性较差,可能遇到兼容性问题。
可扩展性
可借助 Kubernetes 等编排工具轻松扩展。
可扩展,但需要更多资源与管理投入。
安全性
依赖主机 OS 安全性;隔离度低于 VM。
因独立 OS 带来更强隔离;更适合敏感应用。
对于机器学习应用,这些差异尤为重要。当您需要扩展模型以处理更多预测请求,或想部署多个版本进行 A/B 测试时,容器能提供所需的敏捷性与资源效率。
想进一步了解容器化与虚拟化,请查看该学习路径:使用 Docker 和 Kubernetes 的容器化与虚拟化。
如何将机器学习应用容器化
在下文中,我们将按步骤介绍如何将应用容器化:
1. 环境准备
在开始将机器学习应用容器化之前,需要安装必要工具并准备环境。本节将指导您安装 Docker,并准备一个简单的机器学习应用以进行容器化。
所需工具
要将机器学习应用容器化,您需要以下工具:
先从安装 Docker 开始。
步骤 1:安装 Docker
Docker 可用于 Windows、macOS 和 Linux。以下是在您的系统上安装 Docker 的步骤。
Windows/macOS:
Linux(Ubuntu/Debian):
打开终端并运行以下命令安装 Docker:
该安装过程会将 Docker 软件源添加到系统,使用 GPG 密钥验证其真实性,并安装 Docker 引擎及其命令行工具。
步骤 2:验证 Docker 安装
安装完成后,在命令行中运行以下命令验证是否正常工作:
这将拉取一个轻量级测试镜像并以容器形式运行。如果成功,您会看到一条欢迎信息,确认安装正常,如下所示:
2. 准备您的机器学习应用
现在已安装 Docker,接下来准备一个简单的机器学习应用进行容器化。本文将使用一个基础的 Python 脚本,它加载一个预训练模型并通过 Flask API 提供预测服务。
步骤 1:创建一个简单的 ML 应用
为您的项目创建一个新目录,并添加以下文件:
以下是 app.py 的代码:
该代码加载 Iris 数据集,训练随机森林分类器,并设置一个 Flask API 端点来接收特征值并返回预测。我们将其构建为 Web 服务,以便更适合容器化。
步骤 2:创建
requirements.txtrequirements.txt文件列出脚本运行所需的 Python 库。与 app.py 位于同一目录下创建该文件:这指定了我们的应用所需的 Python 包的确切版本。固定版本可确保容器化应用的一致性与可复现性。
现在环境已就绪,ML 应用也准备完毕,我们可以开始构建第一个 Docker 容器。下一节将编写
Dockerfile,并为基于 Flask 的 ML 应用构建 Docker 镜像。3. 构建您的第一个 Docker 容器
现在机器学习应用已就绪,下一步是使用 Docker 将其容器化。这需要创建一个
Dockerfile,它是一份包含构建 Docker 镜像指令的脚本。镜像构建完成后,我们即可将其作为容器运行。Dockerfile 示例:编写 Dockerfile
Dockerfile是一份文本文件,包含组装镜像所需的全部命令。以下是为我们的 Flask 型 ML 应用创建 Dockerfile 的方法。app.py和requirements.txt同一目录下,创建名为Dockerfile的新文件(无扩展名)。Dockerfile中:说明:
FROM python:3.9-slim:使用官方 Python 3.9 slim 镜像作为基础镜像。slim 版本轻量,适合容器化应用。WORKDIR /app:将容器内的工作目录设为/app。后续命令均在该目录下运行。COPY requirements.txt .:将本地的 requirements.txt 复制到容器中。RUN pip install --no-cache-dir -r requirements.txt:安装 requirements.txt 中列出的 Python 依赖。使用 --no-cache-dir 可避免缓存从而减小镜像体积。COPY . .:将本地当前目录的所有文件复制到容器的 /app 目录。EXPOSE 5000:暴露 Flask 应用监听的 5000 端口。CMD ["python", "app.py"]:定义容器启动时运行 Flask 应用的命令。构建并测试 Docker 镜像
编写好 Dockerfile 后,我们就可以构建镜像并以容器形式运行。
步骤 1:构建 Docker 镜像
在终端运行以下命令构建 Docker 镜像:
该命令会基于当前目录下的 Dockerfile 构建镜像。标志
-t ml-flask-app为镜像打上ml-flask-app的标签,便于后续引用。步骤 2:运行 Docker 容器
镜像构建完成后,使用以下命令将其作为容器运行:
该命令基于
ml-flask-app镜像启动一个容器。标志-p 5000:5000将本机 5000 端口映射到容器内 5000 端口,便于通过浏览器或curl等工具访问 Flask 应用。步骤 3:测试容器化应用
打开新的终端窗口,向容器内运行的 Flask 应用发送测试请求:
您将看到类似如下的响应:
这意味着容器化的 Flask 应用已成功运行,可对外提供预测服务。
调试常见问题
如果在构建或运行容器时遇到问题,以下建议可帮助您排查:
查看 Docker 日志:使用以下命令查看运行中容器的日志:
验证 Dockerfile 语法:仔细检查 Dockerfile 是否有拼写或语法错误。
检查端口冲突:确保本机 5000 端口未被占用。如已占用,可将容器映射到其他端口,例如:
重新构建镜像:
如修改了 Dockerfile 或应用代码,请使用以下命令重新构建:
在成功构建并测试 Docker 容器后,下一步是学习如何管理和扩展容器化应用。接下来我们将探索如何使用 Kubernetes 部署并扩展 ML 应用。
想获取更多 Docker 项目,请查看我们的指南:10 个 Docker 项目灵感:从入门到进阶。
运行您的容器化应用
既然我们已构建好 Docker 容器,接下来看看如何有效管理它。本节将带您了解启动、停止和检查容器的常用 Docker 命令,以及如何处理日志和端口。
使用 Docker 管理容器
Docker 提供了一组强大的命令来管理容器。让我们了解最常用的命令。
启动容器
要从镜像启动一个容器,使用
docker run命令。例如:该命令基于
ml-flask-app镜像启动容器,并将本机 5000 端口映射到容器 5000 端口。如果希望在后台运行容器(分离模式),请添加
-d标志:这样容器会在后台运行,释放您的终端。
停止容器
要停止一个运行中的容器,先使用以下命令获取容器 ID:
该命令会列出所有运行中的容器及其 ID、名称和其他信息。获得容器 ID 后,使用如下命令停止容器:
例如:
检查容器
要查看容器的详细信息,使用
docker inspect命令:它将输出 JSON 格式的详情,如容器的网络设置、挂载卷和环境变量等。
列出容器
要查看所有容器(包括运行中与已停止),使用:
这有助于检查容器状态并查找容器 ID。
处理日志和端口
日志与端口对调试和访问容器化应用至关重要。让我们看看如何使用它们。
查看容器日志
要查看运行中容器的日志,使用:
例如:
该命令会显示应用的输出,包括任何错误或控制台信息。若希望实时跟随日志(类似于
tail -f),可添加-f标志:端口映射
运行容器时,可以使用 -p 标志将容器端口映射至本机。例如:
该命令将容器内的 5000 端口映射到本机 5000 端口。如果 5000 端口已被占用,可映射到其他端口,例如:
现在,您的 Flask 应用可通过
http://localhost:5001访问。检查端口绑定
要查看运行中容器的端口映射,使用:
该命令会列出容器的端口映射,有助于排查连通性问题。下一节我们将介绍如何在 Kubernetes 上部署容器化的 ML 应用并实现规模化管理。
借助 Kubernetes 扩展
应用容器化后,我们可以使用Kubernetes 进行部署。Kubernetes 能自动化容器化应用的部署、扩展与管理,使处理大规模工作负载更轻松。本节我们将在 Kubernetes 集群上部署我们的 ML 应用。
在 Kubernetes 上部署容器
Kubernetes 使用 YAML 文件来定义应用的期望状态。这些文件描述容器应如何部署、扩展与管理。先为基于 Flask 的 ML 应用创建一个 Kubernetes 部署。
步骤 1:编写 Kubernetes 部署 YAML 文件
创建名为
ml-flask-app-deployment.yaml的文件,并填入以下内容:该 YAML 文件定义了:
ml-flask-app的 Deployment。ml-flask-app镜像的容器。步骤 2:部署应用
在 Kubernetes 上部署应用,使用
kubectl apply命令:该命令会指示 Kubernetes 创建 YAML 文件中定义的资源。您可以使用以下命令查看部署状态:
该命令会显示部署状态,包括正在运行的副本数。
步骤 3:暴露应用
要使应用可从 Kubernetes 集群外部访问,需要创建 Service。创建名为
ml-flask-app-service.yaml的文件,并填入以下内容:该 YAML 文件定义了:
ml-flask-app-service的 Service。使用以下命令应用 Service:
您可以用以下命令查看 Service 状态:
该命令会显示应用可访问的外部 IP 地址。
扩展与监控
Kubernetes 让应用扩展和性能监控变得轻松。让我们来看具体做法。
扩展应用
要扩展应用,可更新部署中的副本数量。例如将副本数扩展到 5,运行:
您也可以在 YAML 文件中更新
replicas字段并重新应用:然后运行:
监控应用
Kubernetes 提供多种工具监控我们的应用。下面看看常用工具。
使用
kubectl logs查看特定 Pod 的日志:使用
kubectl get pods检查 Pod 状态:使用
kubectl top查看 CPU 与内存使用:自动扩缩容
Kubernetes 还支持 Horizontal Pod Autoscaler(HPA),可基于 CPU 或内存使用率自动调整 Pod 数量。启用自动扩缩容:
这将确保部署根据 CPU 使用率在 3 到 10 个副本间自动伸缩。
Kubernetes 部署最佳实践
在 Kubernetes 上部署应用时,建议遵循以下最佳实践。
使用资源限额
为容器定义 CPU 和内存限制,防止资源耗尽:
使用存活与就绪探针
添加健康检查,确保应用正确运行:
使用命名空间
使用命名空间组织资源,避免冲突:
下一节我们将介绍优化 Dockerfile、管理依赖以及确保安全性的技巧。
容器化 ML 应用的最佳实践
对机器学习应用进行容器化会面临一些挑战,比如大型依赖的管理、可复现性的保证以及安全维护。以下最佳实践可帮助您应对这些挑战,构建健壮的容器化 ML 应用。
优化 Dockerfile
优化良好的 Dockerfile 能显著缩短构建时间并减小镜像体积。以下是一些优化技巧:
使用多阶段构建
多阶段构建允许我们在单个 Dockerfile 中使用多个
FROM语句。它通过丢弃中间阶段中不必要的文件和依赖来减小最终镜像体积。例如:该 Dockerfile:
builder阶段安装依赖并构建应用。减少层数
Dockerfile 中的每条指令都会创建一个新层。要减少层数并减小镜像体积:
RUN命令用&&合并为一个命令。COPY而非ADD,除非确实需要ADD的额外功能。例如:
使用轻量级基础镜像
选择轻量级基础镜像,如
python:3.9-slim,而非更大的python:3.9。slim 镜像仅包含必要包,可有效减小体积。管理依赖与可复现性
可复现性对机器学习工作流至关重要。以下是管理依赖并确保可复现性的方法。
使用 requirements.txt 或 pipen
将所有 Python 依赖列在
requirements.txt文件中,或使用pipenv进行管理。例如:在 Dockerfile 中安装依赖:
固定依赖版本
始终固定依赖版本以避免意外变动。例如:
使用环境变量进行配置
用环境变量进行应用配置,而非硬编码。这样能让容器在不同环境中更灵活、更易配置。例如:
然后在应用中访问该环境变量:
安全性考量
安全是容器化应用的关键。以下是保护 ML 应用的最佳实践:
避免以 root 身份运行
以
root用户运行容器会带来安全风险。应创建非 root 用户,并以该用户运行容器。例如:扫描镜像漏洞
使用 Trivy 或 Clair 等工具扫描 Docker 镜像中的漏洞。例如使用 Trivy 扫描镜像:
安全地管理机密
切勿在 Dockerfile 或应用代码中硬编码敏感信息(如 API 密钥或数据库凭据)。应使用 Kubernetes Secrets 或 Docker Secrets 管理敏感数据。例如,在 Kubernetes 中:
然后在部署中将该机密作为环境变量挂载:
测试与调试
测试与调试对确保容器化应用按预期运行至关重要。以下是一些建议:
本地测试
在部署到 Kubernetes 之前,使用 Docker 在本地测试容器。例如:
使用日志进行调试
使用
docker logs或kubectl logs调试容器化应用中的问题。例如:自动化测试
使用 CI/CD 流水线自动化容器化应用的测试与部署。GitHub Actions、GitLab CI 或 Jenkins 等工具可帮助我们搭建自动化工作流。
遵循这些最佳实践,我们可以构建高效、可复现且安全的容器化机器学习应用。从优化 Dockerfile 到管理依赖与确保安全,这些策略将帮助我们简化 ML 工作流,并自信地部署模型。
结语
使用 Docker 和 Kubernetes 对机器学习应用进行容器化,可简化部署、确保可复现性并增强可扩展性。通过遵循优化 Dockerfile、管理依赖与重视安全等最佳实践,我们能够构建健壮、高效且安全的 ML 工作流。
若想继续学习容器化并强化您的机器学习工作流,请查看以下课程: