文章目录
- 1 安装Docker及前期配置
- 1.1 安装docker
- 卸载旧版本
- 使用脚本自动安装
- 1.2 启动Docker
- 1.3 建立Docker用户组
- 1.4 测试 Docker 是否安装正确
- 2 镜像获取
- 2.1 从`docker hub`从下载镜像
- 2.2 物理机文件镜像制作
- 配置`Dockerfile`文件
- 创建镜像
- 3.3 已保存容器制作
- 3 创建容器
- 3.1 使用`docker hub`中的镜像。
- 3.2 使用物理机镜像
- 3.3 可使用jupyterlab
- 4 启动并进入容器
- 5 容器备份与迁移
- 5.1 用容器构建镜像
- 5.2 导入和导出容器
- 导出容器
- 导入容器快照
- 6 开启`ssh`服务
- 6.1 前期准备
- 6.2 远程连接
- 6.3 补充
- 7 补充
- 7.1 为Docker配置GPU
- 7.2 删除或停止容器
- 7.3 Docker常用命令
- 7.4 清理容器存储目录
- 7.5 下载`Linux`必备软件
- 7.6 修改docker镜像的存储路径
- 8 实例
1 安装Docker及前期配置
1.1 安装docker
卸载旧版本
sudo apt-get remove docker \
docker-engine \
docker.io
使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装,另外可以通过 --mirror
选项使用国内源进行安装:
curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun
执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。
1.2 启动Docker
# 启动docker
sudo systemctl enable docker
sudo systemctl start docker
# 设置docker开机自启动
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
1.3 建立Docker用户组
默认情况下,docker
命令会使用Unix socket
与Docker
引擎通讯。而只有root
用户和 docker
组的用户才可以访问 Docker
引擎的 Unix socket
。出于安全考虑,一般 Linux 系统上不会直接使用 root
用户。因此,更好地做法是将需要使用 docker
的用户加入 docker
用户组。
- 建立
docker
组:
sudo groupadd docker
- 将当前用户加入
docker
组:
sudo usermod -aG docker $USER
退出当前终端并重新登录,进行如下测试。
1.4 测试 Docker 是否安装正确
docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
若能正常输出以上信息,则说明安装成功。
2 镜像获取
2.1 从docker hub
从下载镜像
使用docker pull
命令,下面给出几个例子
# 下载最新的配置了pytorch的镜像
sudo docker pull pytorch/pytorch:latest
2.2 物理机文件镜像制作
配置Dockerfile
文件
先用touch Dockerfile
在当前目录创建一个Dockerfile
文件,然后用sudo vim Dockerfile
编辑Dockerfile
文件:
# FROM ubuntu:2.04
# FROM python:3.8
FROM continuumio/anaconda3
WORKDIR /home
COPY . .
# pip配置清华镜像
RUN pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip3 install -r requirements.txt
RUN apt-get update && apt-get install sudo -y
# 配置阿里云镜像
RUN sudo cp -a /etc/apt/sources.list /etc/apt/sources.list.bak
RUN sudo sed -i "s@http://.*archive.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list
RUN sudo sed -i "s@http://.*security.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list
# 下载GPU工具用的
RUN 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
RUN apt-get update && apt-get install -y \
passwd \
openssl \
openssh-server \
openssh-client \
wget \
nano \
net-tools \
vim-gtk \
iputils-ping \
nvidia-container-toolkit
# CMD ["bash", "sample2.sh"]
# CMD ["python3", "run.py"]
# ENTRYPOINT service ssh start && bash
注释:
FROM
:指定一个基础镜像 (base image);WORKDIR
:指定这个命令之后的所有Docker命令 (比如RUN
,COPY
等等)的工作路径 (working directory),如果指定的路径在镜像中不存在则会自动创建;COPY
:复制文件,格式为COPY <物理机路径> <镜像中的目标路径>
,这里使用.
表示指定WORKDIR
下的所有文件;RUN
:在创建镜像时运行shell
命令;CMD
:指定当Docker容器运行起来之后要执行的命令
创建镜像
sudo docker build --no-cache -t image-name .
注释:
-t
:tag
,指的是要给镜像起的标签名,这里为image-name
,名字必须要是小写;.
:表示在当前路径下搜索Dockerfile
文件;
3.3 已保存容器制作
具体参见5.2的容器导入部分。
3 创建容器
使用docker run
命令便可创建容器。
3.1 使用docker hub
中的镜像。
此时需要额外设置工作路径等。
sudo docker run -itd --gpus all -w /home -p 18080:22 \
--name container_name pytorch/pytorch:latest /bin/bash
解释:这会创建一个名为container_name
的容器,并将它存储在物理机的 path_to_project
目录下。此外,该容器会将主机的 18080
端口映射到容器的 22
端口上。其中
--gpus all
表示开启 GPU;-v
(volume
,数据卷) 表示挂载一个主机目录 。-v /path_to_project:/home
(慎用)。这里将物理机的/path_to_project
路径映射为容器中的/home
路径。可以把它当做是一个在物理机和不同容器中共享的文件夹,比如在一个容器中修改了volume
的数据,会同时反应在其它容器上。也可以使用docker volume create path_to_volume
创建数据卷,这里因为我已经直接指定了-v
参数,是会默认创建volume
的,因此无需再create
一个;-w
表示指定容器工作目录 (与Dockerfile
中的WORKDIR
一样),-p
表示映射主机端口到容器端口(port
);--name
表示指定容器名称;-itd
中的-d
表示detached
即后台运行,-i
(--interactive
) 表示保留交互界面,-t
表示分配一个虚拟的终端 (allocate a pseudo-TTY),经常与-i
一起出现,合起来就是“以交互的方式打开终端”;pytorch/pytorch:latest
为前面用docker pull
拉取的镜像名字。/bin/bash
:指bash
文件的编译地址。
3.2 使用物理机镜像
此时无需设置工作路径以及挂载路径等。
sudo docker run -itd --gpus all -p 18080:22 --name container_name \
image_name /bin/bash
其中-v /path_to_project:/home
慎加,可能会导致容器中没有文件; -w /home
可以不用加了。
示例:
sudo docker run -itd --gpus all -p 18080:22 --name ffjord_v1 ffjord /bin/bash
sudo docker run -itd -v /home/cw/scire_solver --gpus all -p 18080:22 --name scire_solver_1 scire_solver /bin/bash
3.3 可使用jupyterlab
参考自How to run JupyterLab on Docker - DEV Community
sudo docker run -itd -v /home/cw/scire_solver --gpus all --shm-size 50G --privileged -p 8899:8899 -e JUPYTER_ENABLE=yes -e JUPYTER_TOKEN=docker --name scire_solver_2 scire_solver_jupyter /bin/bash
其中:
-e
指的是设定容器的环境变量,其中JUPYTER_ENABLE=yes
是让容器可使用jupyter_lab
,JUPYTER_TOKEN=docker
是设定jupyter_lab
的token
,在后面登录的时候要用,-v
指的是设定容器保存在物理机上的地址,8899:8899
指的是将容器的8899端口(:
后面的,这个是要在jupyter_lab_config.py
文件中设定的)映射到物理机的8899端口(:
前面的)。--shm-size
设定的是交换区内容大小,这个会影响data_loader
等的性能(调整容器shm大小)。--privileged
是获取容器的root
权限,此时可以用root
权限操控容器。
设定好之后,就可以用http://localhost:8899?token=docker
远程连接了,注意,这里面的localhost
换成容器所挂载的物理机的ip
地址。8899
也是物理机的端口号,但因为我们将物理机的8899
端口映射到容器的8899
端口了,而容器的8899
端口被用于jupyter_lab
的远程连接服务,因此意味着连物理机的8899
等价于连接容器的jupyter_lab
。token=docker
是前面设置的JUPYTER_TOKEN=docker
决定的。
4 启动并进入容器
- 先启动容器:
sudo docker start container_name
# 示例:sudo docker start scire_solver_2
- 接着进入容器:
sudo docker exec -it container_name /bin/bash
# 示例:sudo docker exec -it scire_solver_2 /bin/bash
其中/bin/bash
为bash
文件的编译地址,与前面一致。
5 容器备份与迁移
5.1 用容器构建镜像
本节内容主要参考自利用 commit 理解镜像构成。
当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 docker commit
命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。
docker commit
的语法格式为:
docker commit [options] <container_ID或container_name> [<new_image_name>[:<label>]]
我们可以用下面的命令将容器保存为镜像:
docker commit \
--author "XX" \
--message "XX" \
container_name \
new_image_name:label
其中 --author
是指定修改的作者,而 --message
则是记录本次修改的内容。这点和 git
版本控制相似,不过这里这些信息可以省略留空。
我们可以在 docker image ls
中看到这个新定制的镜像。我们还可以用 docker history image_name[:label]
具体查看镜像内的历史记录。
5.2 导入和导出容器
导出容器
如果要导出物理机某个容器,可以使用 docker export
命令。
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7691a814370e ubuntu:18.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test
$ docker export 7691a814370e > ubuntu.tar
这样将导出容器快照到物理机文件。
导入容器快照
注:下面用到的
ubuntu.tar
根据自己情况修改成其他名字
可以使用 docker import
从容器快照文件中再导入为镜像,例如
$ cat ubuntu.tar | docker import - test/ubuntu:v1.0
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
这里的cat
命令是ubuntu中用来显示文件内容用的,这里必须要用。或者也可以用
docker import ubuntu.tar test/ubuntu:v1.0
docker import
之后可以用docker image ls
查看镜像,但查看容器是看不到的
此外,也可以通过指定 URL 或者某个目录来导入,例如
$ docker import http://example.com/exampleimage.tgz example/imagerepo
注:用户既可以使用 *docker load*
来导入镜像存储文件到物理机镜像库,也可以使用 *docker import*
来导入一个容器快照到物理机镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
6 开启ssh
服务
在此之前需要先安装好Linux
必备软件。
6.1 前期准备
# add root passward* 记住自己设置的密码,后面ssh连接要用
sudo passwd root
# New passwrd: # 输入root新密码
# Retype new password: # 再次输入root密码
# passwd: password updated successfully # 密码更新成功
apt update
apt install passwd openssl openssh-server openssh-client -y
# 检查ssh服务是否启动成功
sudo ps -e | grep ssh
# 如果有sshd则说明ssh服务已启动,如果没有启动,输入下边命令启动ssh服务
sudo service ssh start
# 配置ssh文件
vi /etc/ssh/sshd_config
# PasswordAuthentication no # 设置为no才可以使用sftp传文件
# port 22
# PermitRootLogin yes
# 重启ssh
service ssh restart 或 /etc/init.d/ssh restart
# 查看ssh状态
service ssh status
# 设置开机自启动
systemctl enable ssh
# 取消开机自启
systemctl disable ssh
实际服务器环境下机器是很少重启的,所以最好再手动配置一个启动脚本。
# 设置打开shell自启动
sudo nano ssh_auto.sh
添加以下内容:
#!/bin/bash
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$LOGTIME] startup run..." >>/root/run.log
service ssh start >>/root/run.log
赋予权限:
chmod +x ssh_auto.sh
添加到.bashrc
文件中去:
# 编辑.bashrc文件
sudo vim /root/.bashrc
# 添加以下内容
. /root/ssh_auto.sh
# 让.bashrc生效
source .bashrc
6.2 远程连接
ssh root@ip -p 18080-o ServerAliveInterval=20
远程连接ip
是重点,这里ip
不是容器内部的ip
而是物理机的ip
。此外,root
指的是容器中用户的名字,而非物理机中用户的名字,千万不要搞混了。
-o ServerAliveInterval=20
表示每隔20秒发送一次信息告诉服务器我还在线。-p
是端口号,指的是在使用docker run
的时候物理机映射到容器中的ip
,比如18080:22
的话ip=18080
,可以用
docker port container_name 22
在物理机看容器端口映射。
在输入密码的时候,填的是容器的密码,而不是物理机的密码,一定要注意!
6.3 补充
- 使用
sudo systemctl status ssh
仍然会报错,无需理会
$ sudo systemctl status ssh
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
7 补充
7.1 为Docker配置GPU
本节内容参考自nvidia-container-toolkit,可解决docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]].
。注意,下面的命令都是在物理机上执行的,而非在容器里。
- 1、设置软件包存储库和
▁GPG▁
密钥 (直接复制粘贴过去即可):
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
- 2、 在更新软件包列表后安装
Nvidia-container-Toolkit
软件包(和依赖项):
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
- 3、配置
Docker daemon
以识别NVIDIA Container Runtime
:
sudo nvidia-ctk runtime configure --runtime=docker
- 4、在设置默认运行时后重新启动
Docker daemon
以完成安装:
sudo systemctl restart docker
之后便可继续运行docker run
了。
7.2 删除或停止容器
- 获取容器ID:一般使用
docker ps
命令查看Docker
进程。但是,由于这个进程没有正常启动,所以,此时没有显示出来。因此,改用docker ps -l
命令,其中-l
表示显示最新创建的容器 (latest
)。 - 删除对应容器:拿到了容器ID,现在只需要执行
docker rm container_ID
指令删除容器即可。 - 停止对应容器:同理,只需执行
docker stop container_ID
或者docker stop container_name
便可关闭容器。
7.3 Docker常用命令
查看所有镜像:docker images
查看运行中的容器:docker ps
查看所有容器:docker ps -a
启动容器:docker start 容器ID
重启容器:docker restart 容器ID
停止容器:docker stop 容器ID
进入容器:docker exec -it 容器ID /bin/bash
退出容器:exit
构建镜像:docker build -f Dockerfile -t 镜像名:V1 .
创建并运行容器:docker run -d -p 端口 镜像名:V1
删除容器:docker rm 容器ID
删除镜像:docker image rm 镜像ID
复制jar到容器中:docker cp XXX.jar 容器ID:/opt
7.4 清理容器存储目录
可以用sudo du -sh /var/lib/docker
指令查看物理机中存储docker
相关文件的文件夹的大小。接着运行以下指令便可清除不必要的文件:
docker system prune --all --force
docker system prune --all --force --volumes
7.5 下载Linux
必备软件
- 下载
wget, vim
等必备基础软件
apt-get update
apt-get install sudo
# 配置阿里云镜像
sudo cp -a /etc/apt/sources.list /etc/apt/sources.list.bak
sudo sed -i "s@http://.*archive.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list
sudo sed -i "s@http://.*security.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list
apt-get update
# 下载必备软件
sudo apt-get install wget
sudo apt-get install nano
sudo apt install net-tools
sudo apt-get install vim-gtk
apt install iputils-ping
- 下载并配置
anaconda3
# 下载anaconda
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2023.03-1-Linux-x86_64.sh
# 安装anaconda,默认安装在/root/anaconda3
bash Anaconda3-2023.03-1-Linux-x86_64.sh
# 普通用户登陆后,需要执行以下指令使conda的路径等系统环境变量信息写入当前用户的 ~/bashrc 文件中:
/root/anaconda3/bin/conda init bash
# 刷新环境变量
source .bashrc
# pip配置清华镜像源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
7.6 修改docker镜像的存储路径
- 首先查看当前docker镜像默认的存储位置,如下命令
docker info|grep "Docker Root Dir"
一般情况下,在没有特意设置的情况下,默认的保存路径为 /var/lib/docker
。
- 关闭所有运行的docker容器
docker ps | awk '{print $1}' |xargs docker stop
- 停止docker服务
systemctl stop docker
- 在新新增的磁盘挂载点上新建目录,并将原有的docker容器和镜像全部拷贝过来,比如这里新增磁盘的挂载点为
/data/
(这个看自己需求,可自行设置,比如我的为/home/cw/
),则参照如下命令操作
mkdir -p /data/var/lib/docker/
cd /data/var/lib/docker/
cp -r /var/lib/docker/* /data/var/lib/docker/
- 设置docker的配置文件,并指定存储路径,如果文件不存在则直接创建一个
vi /etc/docker/daemon.json
添加如下内容
{
"data-root": "/data/var/lib/docker",
// 可有可无,如果不需要记得把`data-root`后面的`,`删掉
"registry-mirrors": ["https://ooe7wn09.mirror.aliyuncs.com"]
}
- 然后重启docker服务
systemctl daemon-reload
systemctl start docker
至此就完成了docker容器和镜像默认路径的修改。
8 实例
这是我拉取pytorch
,然后创建容器的命令,创建完后可以配置vscode
直接远程该镜像,端口为18080
sudo docker pull pytorch/pytorch:latest
sudo docker run -itd --gpus all -v /data/chumei:/home -w /home -p 18080:22 --name chumei pytorch/pytorch:latest /bin/bash
sudo docker start chumei
sudo docker exec -it chumei /bin/bash
/etc/init.d/ssh start
你的容器打包好后,在新系统创建你的容器,需要
- 改变拉取镜像名:
pytorch/pytorch:latest
- 改变容器存储在系统上的文件夹:
/data/chumei
- 改变你想开通的端口号:
18080
具体解释:
1、首先使用以下命令拉取 PyTorch
镜像:
sudo docker pull pytorch/pytorch:latest
这将会从 Docker Hub
上下载最新版本的 PyTorch
镜像,并在物理机存储。
2、接下来,使用以下命令创建容器:
sudo docker run -itd --gpus all -v /data/chumei:/home -w /home -p 18080:22 --name chumei pytorch/pytorch:latest /bin/bash
这会创建一个名为 chumei
的容器,并将它存储在 /data/chumei
目录下。此外,该容器会将主机的 18080
端口映射到容器的 22
端口上。其中 --gpus all
表示开启 GPU,-v
表示挂载一个主机目录,-w
表示指定容器工作目录,-p
表示映射主机端口到容器端口,--name
表示指定容器名称。
3、启动容器:
sudo docker start chumei
这会启动名为 chumei
的容器。
4、进入容器:
sudo docker exec -it chumei /bin/bash
这会打开一个新的终端,进入正在运行的容器 chumei
中。
5、启动 SSH
服务:
/etc/init.d/ssh start
这会启动容器内的 SSH
服务。
完成以上步骤后,就可以使用 VS Code
等工具通过远程连接访问容器,开发和运行代码了。注意,在使用 VS Code
配置远程连接时,需要指定容器的 IP
地址和端口号。