本文最后更新于:2023年9月26日 下午
怎么实验室只有👴一个运维
0x00. 一切开始之前
因为笔者目前所在的实验室好像只有笔者一个人会一点点运维技术,大家都喜欢在根目录和各种乱七八糟的目录到处乱拉(错乱),为了保证服务器环境不会哪天用着用着给整个挂掉了,笔者写了一份《服务器安全使用指北》,并顺便拷贝过来水一篇博客(笑)
What is docker?
抄自 Wikipedia:
Docker 是一个开源的开放平台软件,用于开发应用、交付(shipping)应用和运行应用。Docker 允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。
按照笔者的理解,Docker 可以简单理解为用于创建共享操作系统内核虚拟机隔离环境(称为容器)的工具包:
Why use docker?
为了解决服务器环境污染问题(例如配环境把服务器主环境搞崩了,这将同时影响到使用服务器的多个用户),在服务器多人共享的情况下,对于不涉及内核驱动更改的工作,推荐使用 docker 创建一个新的隔离环境来完成。
How to install docker?
推荐参照官网的安装教程来完成,这里笔者也是使用的官网教程进行安装
笔者实验室服务器安装了 Ubuntu,其他发行版请参见官网教程进行安装
Docker Engine(推荐)
首先通过如下命令卸载可能存在的旧版 docker:
1
| $ for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
|
接下来添加 docker 仓库的 GPG key 并进行配置:
1 2 3 4 5 6 7 8 9 10
| $ sudo apt-get update $ sudo apt-get install ca-certificates curl gnupg $ sudo install -m 0755 -d /etc/apt/keyrings $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg $ sudo chmod a+r /etc/apt/keyrings/docker.gpg $ echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt-get update
|
正式安装 docker:
1
| $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
完成之后可以通过如下命令验证是否安装成功:
1
| $ sudo docker run hello-world
|
将当前用户添加到 docker 用户组:
1 2 3
| $ sudo groupadd docker $ sudo usermod -aG docker $USER $ sudo systemctl restart docker
|
Docker Desktop(不推荐)
Docker Desktop 额外提供了一个 GUI,以及不同用户间的隔离机制,不过 笔者用着感觉不是很 ok ,所以还是推荐传统的纯 Docker Engine
对于非 Gnome 桌面环境而言,需要安装 gnome-terminal
:
1
| $ sudo apt install gnome-terminal
|
卸载可能安装过的 docker:
1 2 3 4
| $ sudo apt remove docker-desktop $ rm -r $HOME/.docker/desktop $ sudo rm /usr/local/bin/com.docker.cli $ sudo apt purge docker-desktop
|
设置 docker 仓库:
1 2 3 4 5 6 7 8 9 10
| $ sudo apt-get update $ sudo apt-get install ca-certificates curl gnupg $ sudo install -m 0755 -d /etc/apt/keyrings $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg $ sudo chmod a+r /etc/apt/keyrings/docker.gpg $ echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt-get update
|
下载 docker 安装包:
1
| $ wget https://desktop.docker.com/linux/main/amd64/docker-desktop-4.22.1-amd64.deb
|
安装 docker:
1 2
| $ sudo apt-get update $ sudo apt-get install ./docker-desktop-4.22.1-amd64.deb
|
启动 docker:
1
| $ systemctl --user start docker-desktop
|
将当前用户添加到 docker 用户组:
1 2 3
| $ sudo groupadd docker $ sudo usermod -aG docker $USER $ systemctl --user restart docker-desktop
|
0x01. 使用 docker 搭建基本的容器环境
若用户未加入 docker 用户组则所有命令开头都需要添加 sudo 获得 root 权限
创建 Docker 镜像
首先在一个空白的文件夹中创建一个名为 Dockerfile
的文件,写入如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get -y update && \ apt-get install -y lib32z1 apt-transport-https python3 git \ libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev \ vim netcat openssh-server unzip make wget bison flex build-essential curl
RUN rm -f /etc/service/sshd/down RUN sed -ri 's/^#?PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config &&\ sed -ri 's/#UseDNS\ no/UseDNS\ no/g' /etc/ssh/sshd_config && \ sed -ri "s/StrictModes yes/StrictModes no/g" /etc/ssh/sshd_config && \ sed -ri "s/UsePAM yes/UsePAM no/g" /etc/ssh/sshd_config
RUN echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config
RUN groupadd arttnba3 && \ useradd -g arttnba3 arttnba3 -m && \ echo "arttnba3:lTaa4cqucW4zxvJswU5KH0HIRM9VmjO7" | chpasswd && \ echo "root:rqUHmfGUtjItWapDuv3NEqwQ9bm6GBrs" | chpasswd
RUN mkdir /home/arttnba3/.ssh && \ echo "这里写你的ssh公钥" > /home/arttnba3/.ssh/authorized_keys
RUN echo "#!/bin/sh\nservice ssh restart\nsleep infinity" > /root/start.sh RUN chmod +x /root/start.sh
CMD ["/root/start.sh"]
EXPOSE 22
|
接下来运行以下命令创建镜像:
1
| $ docker build -t "自定义镜像名" .
|
创建并启动 docker 容器
完成 docker 镜像创建之后接下来我们就可以开始使用该镜像启动一个新的容器,使用如下命令:
1
| $ docker run -d --privileged -p "外部端口:22" -h "容器主机名" --name="容器名" 自定义镜像名
|
这里添加了一个服务器端口到容器内部 22
端口的映射,从而使得可以从外部直接通过 ssh 连接到容器内部
如果你的容器不需要主机相关的一些权限,也可以去掉 --privileged
参数
进入 docker 容器
进入容器环境有两种办法,一种是通过 container id(可以通过 docker ps
查看,在创建容器时也会打印出容器id),另一种是通过自定义的容器名,这里进入容器后默认是 root 用户:
1
| $ docker exec -it 容器名或容器ID /bin/bash
|
如果想要以容器内部的指定用户身份进入容器,使用如下命令:
1
| $ docker exec -u 用户名 -it 容器名或容器ID /bin/bash
|
从外部连接 docker 容器
在启动容器时我们已经指定了一个外部端口映射,可以直接通过该端口进行 ssh 连接,操作和正常登录服务器基本一致,不过要手动指定该外部端口:
1
| $ ssh 容器内用户名@服务器主机名或IP -p 自定义的外部端口
|
删除 docker 容器
如果 docker 内环境配崩了不想要了,可以简单通过如下命令将该容器进行删除:
1 2
| $ docker stop 容器ID或容器名 $ docker rm 容器ID或容器名
|
重新创建新的容器环境可以直接回到第二步继续进行
删除 docker 镜像
如果 docker 镜像构建感觉不够好,可以通过如下命令删除对应镜像(需确保没有容器在使用该镜像):
后续使用则需要回到第一步从头开始
0x02. 创建可以使用显卡的 docker 环境
有的时候会存在需要在显卡上跑一些任务的需求,本节讲述如何创建一个挂载了显卡的 docker 容器
NVIDIA Container Toolkit 是由英伟达开发的一套对 docker 进行包装的工具,从而使得 docker 容器可以使用服务器主机上的显卡
有两种方法:
方法 ①
需要在服务器主机上完成,首先使用如下命令安装基本组件:
1 2
| $ sudo apt-get update \ && sudo apt-get install -y nvidia-container-toolkit-base
|
使用如下命令检查是否安装成功:
接下来使用如下命令生成 CDI (Container Device Interface)规范文件:
1
| $ sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
|
添加 NVIDIA 仓库与 GPG 密钥:
1 2 3 4 5
| $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \ && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \ && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \ sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \ sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
|
安装 toolkit:
1 2
| $ sudo apt-get update $ sudo apt-get install -y nvidia-container-toolkit
|
配置 docker daemon 进程以识别 NVIDIA COntainer Runtime:
1 2
| $ sudo nvidia-ctk runtime configure --runtime=docker $ sudo systemctl restart docker
|
测试是否安装成功:
1
| $ sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
|
最后成功输出和 nvidia-smi
命令一样的结果就说明安装成功了:
方法 ②
参见 Github 上的这个 issue
若方法 ① 没法成功进行,可以使用如下命令进行安装:
1 2 3 4 5
| $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list $ sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit $ sudo systemctl restart docker
|
添加 NVIDIA Rumtime
NVIDIA Container Runtime 的添加一共有三种方法
方法 ①
首先创建配置文件夹:
1
| $ sudo mkdir -p /etc/systemd/system/docker.service.d
|
然后创建配置文件,注意这条命令一共有五行,全部复制后粘贴进去:
1 2 3 4 5
| $ sudo tee /etc/systemd/system/docker.service.d/override.conf <<EOF [Service] ExecStart= ExecStart=/usr/bin/dockerd --host=fd:// --add-runtime=nvidia=/usr/bin/nvidia-container-runtime EOF
|
重启 docker:
1
| $ sudo systemctl daemon-reload && sudo systemctl restart docker
|
方法 ②
Nvidia toolkit 安装成功之后也可以辅助我们完成这一步,通过如下两条命令其中之一完成:
1 2
| $ sudo nvidia-ctk runtime configure --runtime=docker $ sudo nvidia-ctk runtime configure --runtime=docker --set-as-default
|
重启 docker:
1
| $ sudo systemctl restart docker
|
方法 ③
也可以使用 docker 直接添加 NVIDIA Runtime:
1
| $ sudo dockerd --add-runtime=nvidia=/usr/bin/nvidia-container-runtime [...]
|
配置带 CUDA 的 docker 镜像
创建并启动带显卡的 Docker 容器
与 0x01
中的创建 docker 容器的步骤基本相同,不过需要添加额外的参数
更多用法参见 https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/user-guide.html,本文仅展示基本用法
使用 Nvidia Runtime
通过额外添加 --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all
参数完成:
1
| $ docker run -d --privileged -p "外部端口:22" -h "容器主机名" --name="容器名" --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all 自定义镜像名
|
通过额外添加 --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=显卡标号
参数完成,其中显卡标号为 nvidia-smi -L
命令中所展示的序号,挂载多张显卡需要用 ,
进行隔离(显卡标号间不要加空格 ),这里以挂载第一、二张显卡为例:
1
| $ docker run -d --privileged -p "外部端口:22" -h "容器主机名" --name="容器名" --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=0,1 自定义镜像名
|
传统用法
额外添加 --gpus all
参数即可:
1
| $ docker run -d --privileged -p "外部端口:22" -h "容器主机名" --name="容器名" --gpus all 自定义镜像名
|
通过额外添加 --gpus='"device=显卡标号"'
参数完成,其中显卡标号为 nvidia-smi -L
命令中所展示的序号,以下命令以第一张显卡为例:
1
| $ docker run -d --privileged -p "外部端口:22" -h "容器主机名" --name="容器名" --gpus='"device=0"' 自定义镜像名
|