操作容器
本文将具体介绍如何使用开发机的「Docker 容器」功能管理一个容器,包括创建、启动和停止等。
NOTE
请确保该开发机已打开「Docker 容器」开关。您可以前往开发机详情页检查「Docker 容器」开关状态,通过「改配」按钮开启该功能。
启动容器
作为测试,您可以从智算云平台镜像中心的公共仓库(cr.infini-ai.com/infini-ai
)中拉取预置镜像,并启动一个容器。
例如,下面的命令启动并进入容器:
# 例1 登入开发机后,执行以下命令启动容器输出一个 “Hello World”,之后终止容器。
docker run --rm --name ubuntu cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 /bin/echo 'Hello world'
# 例2 登入开发机后,启动容器并进入容器
docker run -it --name ubuntu cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 bash
您可以从镜像中心获取预置镜像地址。
启动并挂载主容器本地目录
开发机主容器系统盘提供 50GB 持久化存储,可使用 -v
选项将主容器本地目录挂载至容器内。
例如,-v ~:/home/host
将主容器的 HOME 目录挂载到容器内的 /home/host
挂载点。
docker run -it -v ~:/home/host --name ubuntu cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 bash
启动并挂载高性能存储
如开发机已挂载共享高性能存储,则可使用 -v
选项将主容器的高性能存储(默认 /mnt
)挂载至容器内。
例如,-v /mnt/public:/mnt
将主容器的 /mnt
目录挂载到容器内的 /mnt
挂载点。
docker run -it -v /mnt/public:/mnt --name ubuntu cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 bash
启动并挂载云盘
如果是使用弹性资源创建的开发机,且可使用云盘,则可使用 -v
选项将主容器的云盘目录(默认 /datadisk
)挂载至容器内。
挂载前,请先在开发机内修改云盘目录权限,否则无法写入数据:
mkdir /datadisk/host-shared
chmod -R 777 /datadisk/host-shared
例如,-v /datadisk/host-shared:/host-shared
将主容器的 /datadisk/host-shared
目录挂载到容器内的 /host-shared
挂载点。
docker run -it -v /datadisk/host-shared:/host-shared --name ubuntu cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 bash
启动并挂载 GPU
例如,使用 CUDA 镜像,启动一个带有 GPU 的 Docker 容器。
docker run -it --gpus=all cr.infini-ai.com/infini-ai/cuda:12.2.2-cudnn8-devel-ubuntu20.04
TIP
- 使用
--gpus=all
挂载开发机所有的 GPU 设备。 - 旧版开发机启用 Docker 功能时,开发机内部容器会独占全部 GPU。如遇到开发机(主容器)无法与内部容器共享 GPU 的情况,建议将开发机关机再开机,以完成版本更新。
修改默认共享内存大小
如果对共享内存(/dev/shm
) 的大小有要求,可以使用 --shm-size
指定共享内存大小。共享内存默认值为 64MB
,最大值可调整至为开发机内存 90% 的一半。
docker run -it --shm-size=403g --gpus=all -v /mnt/public:/mnt cr.infini-ai.com/infini-ai/cuda:12.2.2-cudnn8-devel-ubuntu20.04
从容器内访问开发机上的服务
假设在开发机上直接启动了一个运行在 8003 端口的 HTTP 服务:
python3 -m http.server 8003 --bind 0.0.0.0
如何在开发机内部运行的容器内访问主机(开发机)上的服务呢?
首先,AIStudio 基于 K8S 技术,不能直接在容器中使用 host.docker.internal
访问运行主机(即开发机)上的服务。
其次,在开发机内部运行 Docker 容器时,容器内的 localhost 或 127.0.0.1 运行时,通常指的是容器自身的回环地址,而不是开发机。
为了让容器内的服务能够访问主机上的服务,可以采用以下方法:
--network host (主机网络模式)
容器与主机共享网络命名空间。容器直接使用主机的网络接口、IP 地址和端口。容器内部的进程就像直接运行在主机上一样。
在 docker run
中添加 --network host
即可,或在 docker compose 文件中配置主机网络模式。以下是验证示例:
# 查看当前开发机的 hostname 和 ip
root@is-daokhy2zrg3qrz6i-devmachine-0:~# hostname
is-daokhy2zrg3qrz6i-devmachine-0
root@is-daokhy2zrg3qrz6i-devmachine-0:~# hostname -i
10.212.126.170
# 不采用 --network host (主机网络模式),运行容器
root@is-daokhy2zrg3qrz6i-devmachine-0:~# docker run -it cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 /bin/bash
# 在容器内部检查当前容器的 hostname 和 ip
root@cf2b84f3139c:/# hostname
cf2b84f3139c
root@cf2b84f3139c:/# hostname -i
172.17.0.2
root@cf2b84f3139c:/# exit
exit
# 采用 --network host (主机网络模式),运行容器
root@is-daokhy2zrg3qrz6i-devmachine-0:~# docker run -it --network host cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 /bin/bash
# 在容器内部检查当前容器的 hostname 和 ip,发现与开发机相同
root@is-daokhy2zrg3qrz6i-devmachine-0:/# hostname
is-daokhy2zrg3qrz6i-devmachine-0
root@is-daokhy2zrg3qrz6i-devmachine-0:/# hostname -i
10.212.126.170
root@is-daokhy2zrg3qrz6i-devmachine-0:/# exit
exit
--add-host hostname:ip (添加主机映射)
在容器的 /etc/hosts
文件中添加一条记录,将指定的主机名映射到指定的 IP 地址。容器可以通过该主机名访问主机上的服务。
在 docker run
中添加 --add-host <hostname:ip>
即可,或在 docker compose 文件中配置主机网络模式。以下是验证示例:
# 查看当前开发机的 hostname 和 ip
root@is-daokhy2zrg3qrz6i-devmachine-0:~# hostname
is-daokhy2zrg3qrz6i-devmachine-0
root@is-daokhy2zrg3qrz6i-devmachine-0:~# hostname -i
10.212.126.170
# 使用 --add-host 增加当前开发机的 hostname 和 ip 记录
root@is-daokhy2zrg3qrz6i-devmachine-0:~# docker run -it --add-host is-daokhy2zrg3qrz6i-devmachine-0:10.212.126.170 cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 /bin/bash
# 在容器内部,可以使用主机(即开发机)的 hostname 访问 8003 端口上的服务。
root@76b460edc125:/# curl is-daokhy2zrg3qrz6i-devmachine-0:8003
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".bashrc">.bashrc</a></li>
<li><a href=".conda/">.conda/</a></li>
<li><a href=".profile">.profile</a></li>
<li><a href=".ssh/">.ssh/</a></li>
<li><a href=".wget-hsts">.wget-hsts</a></li>
</ul>
<hr>
</body>
</html>
root@76b460edc125:/#
也可以动态地获取当前机器的主机名和 IP 地址:
docker run -it --add-host $(hostname):$(hostname -i) cr.infini-ai.com/infini-ai/ubuntu:22.04-20240429 /bin/bash
对比
特性 | --network host | --add-host hostname:ip |
---|---|---|
性能 | 最高 | 较高 |
安全性 | 最差 | 较好 |
隔离性 | 最差 | 较好 |
配置 | 最简单 | 相对复杂,可脚本化 |
适用场景 | 极端性能需求,不考虑安全/隔离性 | 大部分情况 |