自定义 Docker 镜像#

本节将帮助您

  • 使用您自己的依赖项扩展官方 Ray Docker 镜像

  • 将您的 Serve 应用程序打包到自定义 Docker 镜像中,而不是使用 runtime_env

  • 在 KubeRay 中使用自定义 Docker 镜像

要遵循本教程,请确保您已安装 Docker Desktop 并创建了一个 Dockerhub 账户,您可以在其中托管自定义 Docker 镜像。

工作示例#

创建一个名为 fake.py 的 Python 文件,并将以下 Serve 应用程序保存到其中

from faker import Faker

from ray import serve


@serve.deployment
def create_fake_email():
    return Faker().email()


app = create_fake_email.bind()

此应用程序创建并返回一个虚假电子邮件地址。它依赖于 Faker 包 来创建虚假电子邮件地址。请在本地安装 Faker 包来运行它

% pip install Faker==18.13.0

...

% serve run fake:app

...

# In another terminal window:
% curl localhost:8000
john24@example.org

本教程将介绍如何将此代码打包并部署到自定义 Docker 镜像中。

扩展 Ray Docker 镜像#

rayproject 组织维护着运行 Ray 所需依赖项的 Docker 镜像。事实上,rayproject/ray 仓库托管了本教程使用的 Docker 镜像。例如,此 RayService 配置 使用了 rayproject/ray 托管的 rayproject/ray:2.9.0 镜像。

您可以通过在 Dockerfile 中使用它们作为基础层来扩展这些镜像并添加您自己的依赖项。例如,工作示例应用程序使用了 Ray 2.9.0 和 Faker 18.13.0。您可以创建一个 Dockerfile,通过添加 Faker 包来扩展 rayproject/ray:2.9.0

# File name: Dockerfile
FROM rayproject/ray:2.9.0

RUN pip install Faker==18.13.0

总的来说,rayproject/ray 镜像只包含导入 Ray 和 Ray 库所需的依赖项。您可以从这两个仓库中的任何一个扩展镜像来构建您的自定义镜像。

然后,您可以构建此镜像并将其推送到您的 Dockerhub 账户,以便将来可以拉取。

% docker build . -t your_dockerhub_username/custom_image_name:latest

...

% docker image push your_dockerhub_username/custom_image_name:latest

...

请确保将 your_dockerhub_username 替换为您的 DockerHub 用户名,并将 custom_image_name 替换为您想要的镜像名称。 latest 是此镜像的版本。如果您在拉取镜像时未指定版本,Docker 将自动拉取该软件包的 latest 版本。您也可以选择用特定版本替换 latest

将您的 Serve 应用程序添加到 Docker 镜像#

在开发过程中,将您的 Serve 应用程序打包成 zip 文件并通过 runtime_envs 拉取到您的 Ray 集群中会很有用。在生产环境中,将 Serve 应用程序放入 Docker 镜像而不是 runtime_env 会更稳定,因为新的节点无需在运行前动态拉取和安装 Serve 应用程序代码。

使用 Dockerfile 中的 WORKDIRCOPY 命令将示例 Serve 应用程序代码安装到您的镜像中

# File name: Dockerfile
FROM rayproject/ray:2.9.0

RUN pip install Faker==18.13.0

# Set the working dir for the container to /serve_app
WORKDIR /serve_app

# Copies the local `fake.py` file into the WORKDIR
COPY fake.py /serve_app/fake.py

KubeRay 在 WORKDIR 目录内的 ray start 命令下启动 Ray。然后,所有 Ray Serve actor 都可以导入该目录中的任何依赖项。通过将 Serve 文件 COPYWORKDIR,Serve 部署就可以访问 Serve 代码,而无需 runtime_env

对于您的应用程序,您还可以将 Serve 应用所需的任何其他依赖项添加到 WORKDIR 目录中。

构建此镜像并将其推送到 Dockerhub。使用与之前相同的版本来覆盖存储在该版本下的镜像。

在 KubeRay 中使用自定义 Docker 镜像#

通过将自定义 Docker 镜像添加到 RayService 配置中,在 KubeRay 中运行它们。进行以下更改

  1. rayClusterConfig 中将 rayVersion 设置为您自定义 Docker 镜像中使用的 Ray 版本。

  2. ray-head 容器的 image 设置为您在 Dockerhub 上的自定义镜像名称。

  3. ray-worker 容器的 image 设置为您在 Dockerhub 上的自定义镜像名称。

  4. 更新 serveConfigV2 字段,以移除容器中存在的任何 runtime_env 依赖项。

此镜像的预构建版本可在 shrekrisanyscale/serve-fake-email-example 上找到。请尝试运行此 RayService 配置来使用它

apiVersion: ray.io/v1alpha1
kind: RayService
metadata:
  name: rayservice-fake-emails
spec:
  serviceUnhealthySecondThreshold: 300
  deploymentUnhealthySecondThreshold: 300
  serveConfigV2: |
    applications:
      - name: fake
        import_path: fake:app
        route_prefix: /
  rayClusterConfig:
    rayVersion: '2.5.0' # Should match Ray version in the containers
    headGroupSpec:
      rayStartParams:
        dashboard-host: '0.0.0.0'
      template:
        spec:
          containers:
            - name: ray-head
              image: shrekrisanyscale/serve-fake-email-example:example
              resources:
                limits:
                  cpu: 2
                  memory: 2Gi
                requests:
                  cpu: 2
                  memory: 2Gi
              ports:
                - containerPort: 6379
                  name: gcs-server
                - containerPort: 8265 # Ray dashboard
                  name: dashboard
                - containerPort: 10001
                  name: client
                - containerPort: 8000
                  name: serve
    workerGroupSpecs:
      - replicas: 1
        minReplicas: 1
        maxReplicas: 1
        groupName: small-group
        template:
          spec:
            containers:
              - name: ray-worker
                image: shrekrisanyscale/serve-fake-email-example:example
                lifecycle:
                  preStop:
                    exec:
                      command: ["/bin/sh","-c","ray stop"]
                resources:
                  limits:
                    cpu: "1"
                    memory: "2Gi"
                  requests:
                    cpu: "500m"
                    memory: "2Gi"