使用Docker容器#

SkyPilot 可以将容器作为任务运行,或者作为集群的运行时环境。

  • 如果容器镜像可调用/具有入口点:将其作为任务运行。

  • 如果容器镜像要作为运行时环境使用(例如,ubuntu, nvcr.io/nvidia/pytorch:23.10-py3 等),并且如果你有额外的命令要在容器内运行:请将其作为运行时环境运行。

注意

在RunPod上运行docker容器是不支持的。要使用RunPod,可以使用你的docker镜像(用户名应为root作为运行时环境,或者使用setuprun来配置你的环境。更多信息请参见GitHub问题

将容器作为任务运行#

注意

在Kubernetes上,不建议在pod中运行Docker运行时。相反,使用您的容器作为运行时环境

SkyPilot 可以直接将容器化应用程序作为常规任务运行。SkyPilot 提供的默认虚拟机镜像已经预先配置了 Docker 运行时。

要启动一个容器化的应用程序,你可以直接在任务的run部分调用docker run

例如,要运行一个HuggingFace TGI服务容器:

resources:
  accelerators: A100:1

run: |
  docker run --gpus all --shm-size 1g -v ~/data:/data \
    ghcr.io/huggingface/text-generation-inference \
    --model-id lmsys/vicuna-13b-v1.5

  # NOTE: Uncommon to have any commands after the above.
  # `docker run` is blocking, so any commands after it
  # will NOT be run inside the container.

私有注册表#

使用此模式时,要访问托管在私有注册表上的Docker镜像,只需在任务的YAML文件中添加一个setup部分以进行注册表认证:

resources:
  accelerators: A100:1

setup: |
  # Authenticate with private registry
  docker login -u <username> -p <password> <registry>

run: |
  docker run <registry>/<image>:<tag>

远程构建容器#

如果您正在运行容器化应用程序,容器镜像也可以在任务的setup阶段在集群上远程构建。

echo_app 示例 提供了一个关于如何做到这一点的例子:

file_mounts:
  /inputs: ./echo_app  # Input to application
  /echo_app: ./echo_app  # Contains the Dockerfile and build context
  /outputs:  # Output to be written directly to S3 bucket
    name: # Set unique bucket name here
    store: s3
    mode: MOUNT

setup: |
  # Build docker image. If pushed to a registry, can also do docker pull here
  docker build -t echo:v0 /echo_app

run: |
  docker run --rm \
    --volume="/inputs:/inputs:ro" \
    --volume="/outputs:/outputs:rw" \
    echo:v0 \
    /inputs/README.md /outputs/output.txt

在这个例子中,Dockerfile 和构建上下文包含在 ./echo_app 中。 任务的 setup 阶段构建镜像,run 阶段运行容器。 应用程序的输入通过 file_mounts 复制到 SkyPilot,并使用 docker 卷挂载(--volume 标志)挂载到容器中。 应用程序在容器中的 /outputs 路径生成的输出也通过卷挂载到虚拟机上的 /outputs,并通过 bucket mounting 直接写入 S3 存储桶。

我们的GitHub仓库有更多示例,包括通过SkyPilot在Docker容器中运行Detectron2

使用容器作为运行时环境#

当容器被用作运行时环境时,所有操作都在容器内部进行:

  • SkyPilot 运行时会在容器内自动安装并启动;

  • setuprun 命令在容器中执行;

  • 任务创建的任何文件都将存储在容器内。

要使用Docker镜像作为您的运行时环境,请在任务YAML文件的resources部分中将image_id字段设置为docker:。目前仅支持基于Debian的镜像(例如,Ubuntu)。

例如,使用Docker Hub中的ubuntu:20.04镜像:

resources:
  image_id: docker:ubuntu:20.04

setup: |
  # Commands to run inside the container

run: |
  # Commands to run inside the container

再举一个例子,这里是如何使用 NVIDIA 的 PyTorch NGC 容器

resources:
  image_id: docker:nvcr.io/nvidia/pytorch:23.10-py3
  accelerators: T4

setup: |
  # Commands to run inside the container

run: |
  # Commands to run inside the container

  # Since SkyPilot tasks are run inside a fresh conda "(base)" environment,
  # deactivate first to access what the Docker image has already installed.
  source deactivate
  nvidia-smi
  python -c 'import torch; print(torch.__version__)'

分配给任务的任何GPU将自动映射到您的Docker容器中,集群中的所有后续任务也将在容器内运行。在多节点场景中,容器将在所有节点上启动,并且将分配相应节点的容器来执行任务。

提示

何时使用此功能?

如果您在Docker镜像中设置了预配置的开发环境,使用运行时环境模式可能会很方便。这对于启动在新虚拟机上配置具有挑战性的开发环境特别有用,例如依赖于特定版本的CUDA或cuDNN。

注意

由于我们在用户指定的容器镜像中pip install skypilot作为启动的一部分,用户应确保不会发生依赖冲突。

目前,必须满足以下要求:

  1. 容器镜像应基于Debian;

  2. 容器镜像必须授予sudo权限,而不需要用户进行密码认证。拥有root用户也是可以接受的。

注意

支持使用具有自定义入口点的容器作为运行时环境,容器的入口点将被/bin/bash覆盖。可以在任务YAML文件的setuprun部分执行特定命令。然而,由于RunPod API的限制,这种方法与RunPod不兼容,因此请确保选择一个具有默认入口点(即/bin/bash)的容器。

私有注册表#

注意

如果您使用SkyPilot在Kubernetes集群上启动,这些说明不适用。相反,请参阅在Kubernetes中使用私有仓库的镜像以获取更多信息。

使用此模式时,要访问托管在私有注册表上的Docker镜像,您可以使用任务环境变量提供注册表认证详细信息:

resources:
  image_id: docker:<user>/<your-docker-hub-repo>:<tag>

envs:
  # Values used in: docker login -u <user> -p <password> <registry server>
  SKYPILOT_DOCKER_USERNAME: <user>
  SKYPILOT_DOCKER_PASSWORD: <password>
  SKYPILOT_DOCKER_SERVER: docker.io
resources:
  image_id: docker:<your-ecr-repo>:<tag>

envs:
  # Values used in: docker login -u <user> -p <password> <registry server>
  SKYPILOT_DOCKER_USERNAME: AWS
  SKYPILOT_DOCKER_PASSWORD: <password>
  SKYPILOT_DOCKER_SERVER: <your-user-id>.dkr.ecr.<region>.amazonaws.com

我们建议通过CLI设置SKYPILOT_DOCKER_PASSWORD环境变量(参见传递秘密):

$ # Docker Hub password:
$ export SKYPILOT_DOCKER_PASSWORD=...
$ # Or cloud registry password:
$ export SKYPILOT_DOCKER_PASSWORD=$(aws ecr get-login-password --region us-east-1)
$ # Pass --env:
$ sky launch task.yaml --env SKYPILOT_DOCKER_PASSWORD