docker使用

1. 简单的Demo

docker run ubuntu:15.10 /bin/echo "Hello World"

Docker以ubuntu15.10镜像创建一个新容器,然后再容器里执行/bin/echo "Hello world,然后输出结果,一共分为两种情况,如果此镜像已经存在,那么会直接运行该镜像然后输出;如果镜像不存在,就会从docker hub上拉取公共镜像进行输出

  • docker: Docker的二进制执行文件
  • run: 与docker组合来运行一个容器
  • ubuntu:15.10: 指定要运行的镜像,Docker首先从本地主机上查找镜像是否存在,如果不存在,Docker就会从镜像仓库Docker Hub下载公共镜像
  • /bin/echo “Hello world”: 在启动的容器里执行的命令

2. Docker客户端

docker

直接使用docker命令即可查看Docker客户端的所有命令选项

docker <command> --help

使用此命令查看某个命令的详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
wangyh@Ti-Sev:~$ docker

Usage: docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

......................................

Run 'docker COMMAND --help' for more information on a command.

To get more help with docker, check out our guides at https://docs.docker.com/go/guides/
wangyh@Ti-Sev:~$ docker kill --help

Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]

Kill one or more running containers

Options:
-s, --signal string Signal to send to the container (default "KILL")

wangyh@Ti-Sev:~$

2. 镜像命令

2.1 获取镜像

docker pull命令直接从DockerHub上拉取一个镜像,例如从nvidia/cuda这里拉取一个镜像,其中nvidia/cuda表示拉去的目标仓库,12.3.1-devel-ubi8表示拉取的版本

docker pull nvidia/cuda:12.3.1-devel-ubi8

2.2 查找镜像

docker search pytorch

查找合适的pytorch镜像

  • NAME: 镜像仓库源的名称
  • DESCRIPTION: 镜像的描述
  • OFFICIAL: 是否docker官方发布
  • stars: 类似GitHub里面的star, 表示点赞、喜欢的意思
  • AUTOMATED: 自动构建
1
2
3
4
5
6
7
wangyh@Ti-Sev:~$ docker search pytorch
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
pytorch/pytorch PyTorch is a deep learning framework that pu… 388
floydhub/pytorch pytorch 47 [OK]
anibali/pytorch Docker images for the PyTorch deep learning … 33 [OK]
pytorchlightning/pytorch_lightning PyTorch Lightning image 12
pytorch/torchserve 10

2.3 列出本地镜像列表

docker images

列出镜像列表

  • REPOSITORY: 表示镜像的仓库源
  • TAG: 镜像的标签
  • IMAGE ID: 镜像ID
  • CREATED: 镜像创建时间
  • SIZE: 镜像大小
1
2
3
wangyh@Ti-Sev:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wangyh pytorch 304d4ce9d74a 17 minutes ago 3.46GB

2.4 删除镜像

docker rmi <id>

有时候镜像删除不了,报如下错误Error response from daemon: conflict: unable to delete 0f4d93a5f95d (must be forced) - image is being used by stopped container 83835b8839d2,有两种方法解决(一般来说第二种方法更有效)

  1. 换为docker rmi <name:tag>命令
  2. docker rmi -f <id>命令强制删除
1
2
3
4
wangyh@Ti-Sev:~$ docker rmi 304d4ce9d74a
Untagged: wangyh:pytorch
Deleted: sha256:304d4ce9d74a51e37edec454b1ad99a24ae58652789d91420976787fdae2454c
Deleted: sha256:d5e0ea3b89b8a270b008e02d1932b5f941ee4c2fec6ece70ed947a3daf92a8d0

3. 容器命令

下面的演示均以pytorch/pytorch镜像为准

3.1 启动容器

docker run -i -t pytorch/pytorch /bin/bash

  • -t: 在新容器内制定一个伪终端或终端
  • -i: 允许你对容器内的标准输入(STDIN)进行交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
wangyh@Ti-Sev:~$ docker run -i -t pytorch/pytorch /bin/bash

root@1315aa2d41a2:/workspace# ls

root@1315aa2d41a2:/workspace# cat /proc/version
Linux version 4.15.0-151-generic (buildd@lgw01-amd64-042) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #157-Ubuntu SMP Fri Jul 9 23:07:57 UTC 2021

root@1315aa2d41a2:/workspace# cd ..

root@1315aa2d41a2:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var workspace

root@1315aa2d41a2:/# exit
exit

wangyh@Ti-Sev:~$

其中第二行root@1315aa2d41a2:/workspace#表示我们已经进入到pytorch/pytorch的容器中,可以查看版本信息并进行一些相应的操作,最后用exit命令退出容器,返回主机。运行docker ps查看不到此容器,表示容器已经被停止

3.2 启动容器(后台模式)

docker run -d pytorch/pytorch /bin/sh -c "while true; do echo hello world; sleep 1; done"

此命令会输出一段长字符:c4bec97b9c398c470f2ccfae77e9d1fc35e1c22127b7d9209267a5bee79b18a8

这个长字符为容器ID,对每个容器来说唯一,只要容器在运行就可以查看,运行docker ps

  • CONTAINER ID: 容器ID
  • IMAGE: 使用的镜像
  • COMMAND: 启动镜像时使用的命令
  • STATUS: 容器的状态
    • created:已创建
    • restarting:重启中
    • running or up:运行中
    • removing:迁移中
    • paused: 暂停
    • exited: 停止
    • dead: 死亡
  • PORTS: 容器的端口信息和使用的连接类型(tcp/udp)
  • NAMES: 自动分配的容器名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
wangyh@Ti-Sev:~$ docker run -d pytorch/pytorch /bin/sh -c "while true; do echo hello world; sleep 1; done"
c4bec97b9c398c470f2ccfae77e9d1fc35e1c22127b7d9209267a5bee79b18a8

wangyh@Ti-Sev:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4bec97b9c39 pytorch/pytorch "/bin/sh -c 'while t…" 10 seconds ago Up 9 seconds laughing_hellman

wangyh@Ti-Sev:~$ docker logs c4bec97b9c39
hello world

wangyh@Ti-Sev:~$ docker logs laughing_hellman
hello world
hello world
hello world
hello world

3.3 停止容器

docker stop <id>/<name>

使用docker stop命令来停止容器,后面跟容器id或者容器name

1
2
3
4
5
6
7
8
9
wangyh@Ti-Sev:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4bec97b9c39 pytorch/pytorch "/bin/sh -c 'while t…" 10 seconds ago Up 9 seconds laughing_hellman

wangyh@Ti-Sev:~$ docker stop laughing_hellman
laughing_hellman

wangyh@Ti-Sev:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

3.4 启动已经停止的容器

docker ps -a: 查看所有容器(包括已经停止的容器)

docker start <id>/<name>: 启动已经停止的容器

docker stop <id>/<name>: 停止容器

docker restart <id>/<name>: 重启容器

3.5 进入容器

docker attach <id>/<name>

进入到指定容器,如果从容器退出,会导致容器的终止

docker exec -it <id>/<name> /bin/bash

进入到指定容器,如果从容器退出,不会导致容器的终止

3.6 删除容器

docker rm -f <id>

删除正在运行的容器

docker container prune

清理掉所有处于终止状态的容器

3.7 导入和导出容器

docker export <id>/<name> > path/pytorch.tar

导出容器到指定文件

cat docker/ubuntu.tar | docker import - test/ubuntu:v1

导出容器

1
2
3
4
5
6
7
8
9
10
11
12
13
wangyh@Ti-Sev:~$ docker export af2e2f698dfd > /data4/wangyh/pytorch.tar
wangyh@Ti-Sev:~$ ll /data4/wangyh
total 3413612
-rw-rw-r-- 1 wangyh wangyh 3495418880 Dec 30 21:08 pytorch.tar

wangyh@Ti-Sev:~$ cat /data4/wangyh/pytorch.tar | docker import - wangyh:pytorch
sha256:304d4ce9d74a51e37edec454b1ad99a24ae58652789d91420976787fdae2454c

wangyh@Ti-Sev:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wangyh pytorch 304d4ce9d74a 5 minutes ago 3.46GB

wangyh@Ti-Sev:~$

4. 制作docker镜像

当运行容器时,如果使用的镜像在本地不存在,docker就会自动从Docker Hub公共镜像源下载,当docker镜像仓库中的镜像不能满足需求时,可以有以下两种方式对镜像进行修改

  • 从已经创建的容器中更新镜像,并提交修改后的镜像
  • 使用Dockerfile指令来创建一个新的镜像

这里我们以创建一个深度学习的Docker镜像为例子,需要的版本是:cuda10.1-cudnn7-devel-ubuntu18.04,python3.8,pytorch1.8

4.1 使用现有镜像

此方法是利用现有的镜像建立一个容器,然后在容器内进行你想要的操作,比如建立了一个python环境,然后退出容器,将容器进行保存为镜像压缩文件,然后重新将压缩文件转化为镜像即可,下面直接给出命令行的建立过程

首先我们这里已经建立了一个容器,如下

1
2
3
wangyh@Ti-Sev:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
506a5c87aaa3 pytorch/pytorch:latest "/bin/bash" 5 minutes ago Exited (0) 4 minutes ago recursing_chatterjee

然后我们使用export命令将其保存到/data4/wangyh文件夹下,进入到文件夹,ls查看发现现在多了一个pytorch.tar文件

1
2
3
4
5
6
wangyh@Ti-Sev:~$ docker export 506a5c87aaa3 > /data4/wangyh/pytorch.tar

wangyh@Ti-Sev:~$ cd /data4/wangyh

wangyh@Ti-Sev:/data4/wangyh$ ls
pytorch.tar

接下来我们用import命令将其转化为镜像,此时用docker images发现镜像已经存在啦

1
2
3
4
5
6
7
wangyh@Ti-Sev:/data4/wangyh$ cat pytorch.tar | docker import - test/pytorch:vv2
sha256:464d3d9480156995273961ee9f3429a970127c2b6cacbf2a7a4aa9fd4e78d460

wangyh@Ti-Sev:/data4/wangyh$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/pytorch vv2 464d3d948015 About a minute ago 3.5GB
wangyh@Ti-Sev:/data4/wangyh$

4.2 Dockerfile

Dockerfile的制作很简单,首先建立一个文件命名为Dockerfile,然后将下面的内容复制进去,运行命令

docker build -t <image name> .

例如建立名称为nvidia/cuda:v2的镜像名称

docker build -t nvidia/cuda:v2 .

然后等待镜像建立完成即可,对下面的命令进行解释

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
#!/bin/bash

FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04
MAINTAINER wangyh "1061771439@qq.com"

RUN apt-get update \
&& apt-get install -y sudo \
&& apt-get install -y wget \
&& apt-get install -y vim

RUN cd /home \
&& wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh \
&& bash Miniconda3-latest-Linux-x86_64.sh -b \
&& rm -f Miniconda3-latest-Linux-x86_64.sh

ENV PATH=/root/miniconda3/bin:$PATH

RUN conda --version \
&& echo "channels:" > ~/.condarc \
&& echo " - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/" >> ~/.condarc \
&& echo " - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge" >> ~/.condarc \
&& echo " - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/" >> ~/.condarc \
&& echo " - defaults" >> ~/.condarc \
&& echo "set show_channel_urls: yes" >> ~/.condarc \
&& conda env list

ADD requirements.txt /home

SHELL ["/bin/bash", "-c"]
RUN conda create -n torch -y python=3.8
# 用于激活环境,conda activate命令无效
# 参考https://saigezixun.com/article/91/
SHELL ["conda", "run", "-n", "torch", "/bin/bash", "-c"]

Run conda list
RUN pip install torch==1.8.1+cu101 torchvision==0.9.1+cu101 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
  • 首先刚创建的环境很多命令不能用,我们用apt-get update命令更新一下,然后就可以用apt-get install xxx安装了
  • 随后我们安装miniconda3,wget安装包,bash安装,安装完后rm删除即可
  • ENV用来给miniconda3添加环境变量,然后RUN命令修改conda源
  • 将宿主机的requirements.txt文件上传到容器中的/home中,方便我们后续进行pip install -r requirements.txt
  • 创建conda环境,然后SHELL进入到环境中
  • 在PyTorch官网安装相应的包即可,至此镜像创建完成

4.3 Dockerfile命令

  • (一)FROM命令

指定基础镜像。新的镜像在基础镜像上进行修改,例如我们要创建一个cuda环境,可以直接从Docker Hub上进行查找,本文中采用了nvidia/cuda:10.1的版本,所以写为FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04

  • (二)MAINTAINER

指定作者。指定dockerfile的作者名称和邮箱,例如MAINTAINER wangyh 1061771439@qq.com

  • (三)RUN

在镜像内部执行的命令,和在terminal中执行的一样,有两种执行格式

1
2
shell格式:RUN mkdir abc
exec格式: RUN ["mkdir", "abc"]

如果要执行多个命令,需要在每个命令之后加入&&\

1
2
3
4
RUN apt-get update && \
apt-get install -y sudo && \
apt-get install -y wget && \
apt-get install -y vim

此外,有一些经常使用的文件操作命令

1. 向某个文件中写内容

1
2
3
4
5
echo "aaa" > b.txt  # 清空b.txt中的内容,并将"aaa"写到b.txt中
echo "aaa" >> b.txt # 将"aaa"写到b.txt末尾,并加入换行符自动换行

cat a.txt > b.txt # 清空b.txt中的内容,并将a.txt中的内容写入b.txt
cat a.txt >> b.txt # 将a.txt中的内容写入b.txt末尾,不会加入换行符

2. 修改替换某个文件中的内容

1
2
sed 's/要被取代的字串/新的字串/g'  # 语法格式,s和g
sed -i 's/oo/kk/g' testfile # 选项i表示直接修改testfile文件内容
  • (四)ADD/COPY

这两个命令都是将宿主机的文件复制到镜像内,如果目标位置不存在,会自动创建。例如将home文件夹下的a.txt文件复制到容器中root目录下,执行ADD /home/a.txt /root/a.txt

  • (五)SHELL

shell指令可以覆盖默认的命令shell,例如linux的默认shell是[“\bin\bash”, “-c”], windows是[“cmd”, “\S”, “\C”]

  • (六)ENV

设置容器的环境变量

1
2
3
4
5
ENV PATH=/root/miniconda3/bin:$PATH  # 设置miniconda的环境变量

# 设置代理
ENV http_proxy http://192.168.161.204:7890
ENV https_proxy http://192.168.161.204:7890