GPU共享服务器常用的docker命令
实验室GPU资源通过docker以及nvidia-docker构建了一个GPU的共享服务器,每次维护容器都会忘记一些命令,以此记录。
批量操作docker
- 暂停所有容器:docker stop $(docker ps -a -q)
- 删除所有容器:docker rm $(docker ps -a -q)
- 删除所有镜像:docker rmi $(docker images -q)
创建一个新的GPU容器
docker run -dit --gpus '"device=0,2,3"' --restart=always -v /home/gpu-server/docker-common-dir/:/home/common-dir -p3022:22 -p3888:8888 -p3889:8889 --name=gpu-server-vm-jiangnan --shm-size="100g" 容器镜像
- -dit:以后台终端方式运行一个容器
- –gpus:指定以gpu方式运行容器
- ‘“device=0,2,3”’:指定可以使用宿主机那些gpu卡
- –restart=always:指定docker服务启动,容器就启动
- -v /home/gpu-server/docker-common-dir/:/home/common-dir: 与宿主机的共享目录,前面是宿主机路径,后面是容器路径。
- -p:同理,只不过是端口映射
- –shm-size:这是linux特有的一个共享内存,docker创建默认为64m,若不指定,某些模型需要设置线程操作为1(num_workers=1),具体详情。
- 容器镜像
Dockerfile
通过Dockerfile可以先对目标镜像做一些预备环境的配置,同时将ssh服务配置上,这部分的Dockerfile,拉取的基础镜像,建议从nvidia使用的ubuntu系统,之前拉取官方的ubuntu,下载基础服务出现依赖报错,Dockerfile中出现报错很耗费时间,不过nvidia/cuda:11.4.0-cudnn8-runtime-ubuntu18.04
这个版本以及很好用。
FROM nvidia/cuda:11.4.0-cudnn8-runtime-ubuntu18.04
LABEL MAINTAINER="zyr<toumasi0411@gmail.com>"
ARG RELEASE_NAME=bionic
ARG ROOT_PASSWD=root
ENV SSH_PORT 22
ENV PATH /root/miniconda3/bin:$PATH
#
# UTF-8 encoding to support chs characters
#
RUN echo "export LANG=C.UTF-8" >>/etc/profile \
#
# apt sources backup
#
&& cp /etc/apt/sources.list /etc/apt/sources.list.bak \
#
# switch apt source to TUNA
#
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ release-name main restricted universe multiverse\n\
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ release-name-updates main restricted universe multiverse\n\
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ release-name-backports main restricted universe multiverse\n\
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ release-name-security main restricted universe multiverse" >/etc/apt/sources.list \
&& sed -i 's/release-name/'$RELEASE_NAME'/g' /etc/apt/sources.list \
#
# remove nvidia sources
#
# && rm /etc/apt/sources.list.d/cuda.list /etc/apt/sources.list.d/nvidia-ml.list \
#
# install necessary packages
#
&& apt-get update \
&& apt-get install -y --no-install-recommends \
apt-utils \
vim \
openssh-server \
net-tools \
iputils-ping \
wget \
curl \
git \
iptables \
bzip2 \
command-not-found \
#
# download & install miniconda
#
&& wget -q https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh \
&& bash Miniconda3-latest-Linux-x86_64.sh -b \
&& rm Miniconda3-latest-Linux-x86_64.sh \
&& ln -s /root/miniconda3/etc/profile.d/conda.sh /etc/profile.d/conda.sh \
#
# switch conda source to TUNA
#
&& echo "channels:\n\
- defaults\n\
show_channel_urls: true\n\
default_channels:\n\
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main\n\
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r\n\
custom_channels:\n\
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud\n\
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud\n\
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud\n\
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud\n\
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud" >/root/.condarc \
#
# create conda py37 environment
#
&& /root/miniconda3/bin/conda create -npy37 python=3.7 -y \
#
# switch pip source to TUNA & update pip
#
&& /root/miniconda3/envs/py37/bin/pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \
&& /root/miniconda3/envs/py37/bin/pip install pip -U \
#
# enable root access with ssh: replace line starts with '#PermitRootLogin' or 'PermitRootLogin'
#
&& sed -i '/^#*PermitRootLogin/cPermitRootLogin yes' /etc/ssh/sshd_config \
#
# set root password
#
&& echo "root:$ROOT_PASSWD" | chpasswd \
#
# change ssh port & start ssh service when docker container starts
#
&& echo "#!/bin/bash\n\
sed -i \"s/Port 22/Port \$SSH_PORT/g\" /etc/ssh/sshd_config\n\
service ssh start\n\
/bin/bash" >/home/startup.sh \
&& chmod 777 /home/startup.sh \
#
# add welcome tips
#
&& CONDA_VERSION=`/root/miniconda3/condabin/conda -V` \
&& CONDA_VERSION=${CONDA_VERSION#* } \
&& echo "\
printf '\\\n'\n\
printf '\\\033[0;34m'\n\
printf 'Welcome to GPU server\\\n'\n\
printf 'Please change the default root password in time\\\n'\n\
printf '\\\n'\n\
printf ' CUDA:\\\t\\\tv$CUDA_VERSION\\\n'\n\
printf ' CUDNN:\\\t\\\tv$CUDNN_VERSION\\\n'\n\
printf ' Conda:\\\t\\\tMiniconda v$CONDA_VERSION use \`conda activate py37\` to activate conda env\\\n'\n\
printf ' SSH port:\\\t$SSH_PORT for this container\\\n'\n\
printf '\\\033[0m'\n\
printf '\\\n'\n\
" >>/etc/update-motd.d/10-help-text \
#
# cleanup
#
&& rm -rf /var/lib/apt/lists/* /tmp/*
#
# set startup script
#
ENTRYPOINT /home/startup.sh
通过PID查找GPU占用率最高的容器
参考
服务器资源紧张,部分卡上创建了多个容器,有时候不知道那个容器正在使用显卡资源,通过以下方式可以找出那张卡正在使用显卡资源。
- nvidia-smi:找出占用显卡资源的pid
- cat /proc//cgroup 命令查询进程信息
- 上图每条信息都展示此进程处于那个docker容器的ID号,可以通过docker inspect命令查询出容器名称,
docker inspect --format '{{.Name}}' "容器ID" | sed 's/^\///'
查看某个容器挂载的GPU的ID号
容器一多,常常忘记某个容器挂载在那个GPU上,可以通过以下方式查询出
docker inspect 容器号
:可以查询出docker的所有详细信息,找出关于gpu设备的信息,一般在hostconfig标签下。此处内容太长,不能截到父标签hostconfig。
docker inspect -f "{{.HostConfig.DeviceRequests}}" 容器号
:用-f指定格式化输出,不用在一大堆信息中大海捞针可以看出是绑定的GPU是0,2,3这三张卡