Docker常用指令详解

Docker 分为客户端和服务端两部分, docker 为客户端调用的命令, dockerd 为服务端调用的命令, 本文着重介绍客户端的用法。

特此声明,下面大部分内容来自于这位大佬,除此之外,还添加了一些自己的理解。

概览

主要用法:docker [ docker命令选项 ] [ 子命令 ] [ 子命令选项 ]

docker [ 子命令 ] —help 可查看每个子命令的详细用法。

Docker 命令选项列表

选项说明其他
—config [string]客户端本地配置文件路径默认为 ~/.docker
-D, —debug启用调试模式
—help打印用法
-H, —host list通过 socket 访问指定的 docker 守护进程 ( 服务端 )unix:// , fd:// , tcp://
-l, —log-level [string]设置日志级别 ( debuginfowarnerrorfatal )默认为 info
—tls启用 TLS 加密
—tlscacert [string]指定信任的 CA 根证书 路径默认为 ~/.docker/ca.pem
—tlscert [string]客户端证书路径默认为 ~/.docker/cert.pem
—tlskey [string]客户端证书私钥路径默认为 ~/.docker/key.pem
—tlsverify启用 TLS 加密并验证客户端证书
-v, —version打印 docker 客户端版本信息

镜像仓库相关

查找镜像

1
docker search [ 条件 ]

例如

1
2
# 查询三颗星及以上名字包含alpine的镜像
docker search -f=stars=3 alpine

获取镜像

1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。

  • 除了官方仓库外的第三方仓库要指定 url,格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
  • 标签 表示镜像的版本号,不指定时默认为 latest

比如:

1
2
3
4
5
6
7
8
9
10
$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
bf5d46315322: Pull complete
9f13e0ac480c: Pull complete
e8988b5b3097: Pull complete
40af181810e7: Pull complete
e6f7c7e5c03e: Pull complete
Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04

上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub 获取镜像。而镜像名称是 ubuntu:18.04,也就是用户名为默认的library,软件名为ubuntu,标签为18.04。因此将会获取官方镜像 library/ubuntu 仓库中标签为 18.04 的镜像。docker pull 命令的输出结果最后一行给出了镜像的完整名称,即: docker.io/library/ubuntu:18.04。注意这个链接前面是不需要加http://的。

推送镜像到仓库

1
docker push [ 镜像名 ]:[ tag ]

当然,需要先登录

1
2
3
4
5
6
ubuntu@VM-84-201-ubuntu:~$ docker push alpine
The push refers to a repository [docker.io/library/alpine]
3fb66f713c9f: Layer already exists
errors:
denied: requested access to the resource is denied(没有权限, 需要登录帐号)
unauthorized: authentication required

登录/退出第三方仓库

1
docker [ login/logout ] [ 仓库地址 ]

例如:

1
2
3
4
5
6
7
8
# 登录
ubuntu@VM-84-201-ubuntu:~$ docker login daocloud.io
Username (username): username
Password:
Login Succeeded
# 退出
ubuntu@VM-84-201-ubuntu:~$ docker logout daocloud.io
Removing login credentials for daocloud.io

本地镜像

查看本地镜像

1
docker images

例如:

1
2
3
4
ubuntu@VM-84-201-ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest a41a7446062d 14 hours ago 3.97MB
hello-world latest 48b5124b2768 4 months ago 1.84kB

删除本地镜像

1
2
docker rmi [ 镜像名 or 镜像 id ]
docker rmi $(docker images | grep "^<none>" | awk '{print $3}') # 想要删除untagged images,也就是那些id为的image的话可以用

如果用 镜像 id 作为参数,可以只输入前几位, 能唯一确定即可 ( 可以同时删除多个镜像, 空格隔开 )。此外, 如果已经使用该 镜像 启动了 容器 需要先删除 容器

1
2
3
4
5
ubuntu@VM-84-201-ubuntu:~$ docker rmi a41
Untagged: alpine:latest
Untagged: alpine@sha256:0b94d1d1b5eb130dd0253374552445b39470653fb1a1ec2d81490948876e462c
Deleted: sha256:a41a7446062d197dd4b21b38122dcc7b2399deb0750c4110925a7dd37c80f118
Deleted: sha256:3fb66f713c9fa9debcdaa58bb9858bd04c17350d9614b7a250ec0ee527319e59

若遇到错误Error response from daemon: conflict: unable to delete a9aad2420ea3 (must be forced) - image is being used by stopped container 4b42ead3973b,则先使用docker stop $(docker ps -a -q)停止所有的container,这样才能够删除其中的images。

若还是不行的话,先删除对应的docker。因为该image被对应的container引用,所以image删除失败。

1
2
3
4
[root@vm000949 redis]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mia/redis v2 a061cf8c12b8 48 minutes ago 210.7 MB
<none> <none> 037c233c605c 2 days ago 203.5 MB

主要希望删除这两个imgae,根据image的id到container中找

1
2
3
4
[root@vm000949 redis]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1be364973e1d a061cf8c12b8 "/bin/bash" 42 minutes ago Exited (137) 5 minutes ago thirsty_einstein
65e94723f0ed 037c233c605c "/bin/sh -c 'yum -y u" 2 days ago Exited (1) 2 days ago

然后删除它们

1
2
3
4
[root@vm000949 redis]# docker rm 65e94723f0ed
65e94723f0ed
[root@vm000949 redis]# docker rm 1be364973e1d
1be364973e1d

再删除镜像:

1
2
3
4
5
6
7
8
[root@vm000949 redis]# docker rmi a061cf8c12b8
Untagged: mia/redis:v2
Deleted: sha256:a061cf8c12b8a23ea9fe85ebcfc32615f8e9a38dd95961b0dd80ceae658cdc5a
Deleted: sha256:f80464ae70055852f02c7763858dd97121c0e3d77430cb4df2dc70aec1c19678
Deleted: sha256:cdcbccf2d746d094040b8383868120d6d73327827b6ee83a8989baab9bf5fa42
[root@vm000949 redis]# docker rmi 037c233c605c
Deleted: sha256:037c233c605c5b4266ef6cc208d6c1a07b01fab77e848ec0bbb3bb01bdb3fda1
Deleted: sha256:7e07f5920a8cef8dbc5a5a663b14dc37d1112b259d93629aa8ded32f0ea0a6ae

也可以根据提示来的,加-f强制删除镜像。

值得注意的是,若遇到错误Error response from daemon: conflict: unable to delete cc6f00f7df14 (cannot be forced) - image has dependent child images,则可以使用docker image inspect --format='{ {.RepoTags} } { {.Id} } { {.Parent} }' $(docker image ls -q --filter since=cc6f00f7df14)查看到有另外的 image FROM 了这个 image。可以通过删除子镜像来删除该镜像。

查看镜像详情

1
docker inspect [ 镜像名 or 镜像 id ]

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ubuntu@VM-84-201-ubuntu:~$ docker inspect a41
[
{
"Id": "sha256:a41a7446062d197dd4b21b38122dcc7b2399deb0750c4110925a7dd37c80f118",
"RepoTags": [
"alpine:latest"
],
"RepoDigests": [
"alpine@sha256:0b94d1d1b5eb130dd0253374552445b39470653fb1a1ec2d81490948876e462c"
],
"Parent": "",
"Comment": "",
"Created": "2017-05-25T23:33:22.029729271Z",
"Container": "19ee1cd90c07eb7b3c359aaec3706e269a871064cca47801122444cef51c5038",
......
}
}
]

查看容器映射路径,container_name 是容器的名字,也可以写容器的ID。

1
$ docker inspect container_name | grep Mounts -A 20

另外,还可以通过指令,查看该镜像的环境变量,如下所示:

1
2
3
4
5
6
7
8
9
"Env": [
"PATH=/opt/conda/lib/python3.8/site-packages/torch_tensorrt/bin:/opt/conda/bin:/usr/local/mpi/bin:/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/ucx/bin:/opt/tensorrt/bin",
"CUDA_VERSION=11.8.0.062",
"CUDA_DRIVER_VERSION=520.61.03",
"CUDA_CACHE_DISABLE=1",
"LD_LIBRARY_PATH=/opt/conda/lib/python3.8/site-packages/torch/lib:/opt/conda/lib/python3.8/site-packages/torch_tensorrt/lib:/usr/local/cuda/compat/lib:/usr/local/nvidia/lib:/usr/local/nvidia/lib64",
"NVIDIA_VISIBLE_DEVICES=all",
"NVIDIA_DRIVER_CAPABILITIES=compute,utility,video",
"NVIDIA_PRODUCT_NAME=PyTorch",

NVIDIA_VISIBLE_DEVICES=all则可能会导致在k8s集群中,实例可以看到该节点所有的显卡。解决方法是在dockerfile中取消该变量。

打包本地镜像, 使用压缩包来完成迁移

1
2
3
docker save [ 镜像名 ] > [ 文件路径 ]
或者
docker save -o [ 文件路径 ] [ 镜像名 ]

例如:

1
2
3
4
5
# 默认为文件流输出
docker save alpine > /usr/anyesu/docker/alpine.img

# 或者使用 '-o' 选项指定输出文件路径
docker save -o /usr/anyesu/docker/alpine.tar alpine

值得注意的是,若是跨系统打包docker,要使用-o的方式打包,用-i的方式解压。

导入镜像压缩包

1
2
3
4
5
# 当文件流输出的时候
docker load < [ 文件路径 ]

# 当 '-o' 选项指定输出文件路径
docker load -i [文件路径]

例如

1
2
3
4
5
6
7
8
9
10
# 默认从标准输入读取
ubuntu@VM-84-201-ubuntu:~$ docker load < /usr/anyesu/docker/alpine.img
3fb66f713c9f: Loading layer [==================================================>] 4.221MB/4.221MB
Loaded image: alpine:latest

# 用 '-i' 选项指定输入文件路径
ubuntu@VM-84-201-ubuntu:~$ docker load -i /usr/anyesu/docker/alpine.img
Loaded image: alpine:latest
Loaded image ID: sha256:665ffb03bfaea7d8b7472edc0a741b429267db249b1fcead457886e861eae25f
Loaded image ID: sha256:a41a7446062d197dd4b21b38122dcc7b2399deb0750c4110925a7dd37c80f118

修改镜像tag

1
docker tag [ 镜像名 or 镜像 id ] [ 新镜像名 ]:[ 新 tag ]

例如:

1
2
3
4
5
6
ubuntu@VM-84-201-ubuntu:~$ docker tag a41 anyesu/alpine:1.0
ubuntu@VM-84-201-ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
anyesu/alpine 1.0 a41a7446062d 15 hours ago 3.97MB
alpine latest a41a7446062d 15 hours ago 3.97MB
hello-world latest 48b5124b2768 4 months ago 1.84kB

容器相关

创建、启动容器并执行相应的命令

1
docker run [ 参数 ] [ 镜像名 or 镜像 id ] [ 命令 ]

如果没有指定命令时就执行 镜像 中默认的命令, 创建 镜像 的时候可设置默认命令。另外要注意的一点,启动 容器 后要执行一个前台进程 ( 就是能在控制台不断输出的或者一直等待的那种程序,如 tomcat 的 catalina.sh ) 才能使 容器 保持运行状态,否则,命令执行完 容器 就关闭了,像下面这个例子执行完就直接结束了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ubuntu@VM-84-201-ubuntu:~$ docker run hello-world

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.
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://cloud.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/engine/userguide/

run 命令常用选项

选项说明
-d后台运行容器, 并返回容器ID;不指定时, 启动后开始打印日志, Ctrl + C 退出命令同时会关闭容器
-i以交互模式运行容器, 通常与 -t 同时使用;
-t为容器重新分配一个伪输入终端, 通常与 -i 同时使用
—name “anyesu-container”为容器指定一个别名, 不指定时随机生成
-h docker-anyesu设置容器的主机名, 默认随机生成
—dns 8.8.8.8指定容器使用的 DNS 服务器, 默认和宿主机一致
-e docker_host=172.17.0.1设置环境变量
—cpuset=”0-2” or —cpuset=”0,1,2”绑定容器到指定 CPU 运行
-m 100M设置容器使用内存最大值
—net bridge指定容器的网络连接类型, 支持 bridge / host / none / container 四种类型
—ip 172.18.0.13为容器分配固定 ip ( 需要使用自定义网络 )
—expose 8081 —expose 8082开放一个端口或一组端口, 会覆盖镜像设置中开放的端口
-p [宿主机端口]:[容器内端口]宿主机到容器的端口映射, 可指定宿主机的要监听的 ip, 默认为 0.0.0.0
-P注意是大写的, 宿主机随机指定一组可用的端口映射容器 expose 的所有端口
-v [宿主机目录路径]:[容器内目录路径]挂载宿主机的指定目录 ( 或文件 ) 到容器内的指定目录 ( 或文件 )
—add-host [主机名]:[ip]为容器 hosts 文件追加 host , 默认会在 hosts 文件最后追加内容:[主机名]:[容器ip]
—volumes-from [其他容器名]将其他容器的数据卷添加到此容器
—link [其他容器名]:[在该容器中的别名]添加链接到另一个容器, 在本容器 hosts 文件中加入关联容器的记录, 效果类似于 —add-host

一个较完整的例子:

1
2
3
4
5
6
7
8
9
# 创建一个名为anyesu_net、网段为172.18.0.0的网桥(docker默认创建的网段为172.17.0.0)
docker network create --subnet=172.18.0.0/16 anyesu_net

# 创建并启动一个配置复杂的容器
ubuntu@VM-84-201-ubuntu:~$ docker run -d --name anyesu-container -h docker-anyesu --dns 8.8.8.8 -e docker_host=172.18.0.1 -e docker_host2=172.18.0.2 --net anyesu_net --ip 172.18.0.13 --expose 8081 --expose 8082 -P -p 8000:8000 -p 8001:8001 -v /usr/anyesu:/usr/anyesu --add-host anyesu_host:172.18.0.1 tomcat:7
912e6632161de0783a057aa02380e676753f66cfb367ef1686d4d09cdc931659
ubuntu@VM-84-201-ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
912e6632161d tomcat:7 "catalina.sh run" 6 seconds ago Up 5 seconds 0.0.0.0:8000-8001->8000-8001/tcp, 0.0.0.0:32783->8080/tcp, 0.0.0.0:32782->8081/tcp, 0.0.0.0:32781->8082/tcp anyesu-container

单字符选项可以合并, 如 -i -t 可以合并为 -it

另一个完整的例子:

使用docker images查看当前的docker镜像如下。

image-20200417101555383

则启动docker镜像的命令可以是:

1
2
3
4
5
6
7
8
9
# 将/data6/zhaodali映射到/workspace文件夹
docker run --gpus all -v /data6/zhaodali:/workspace -ti ubuntu-opencv-torch:latest /bin/bash

# 开启之后运行ls指令,看到将/data6/zhaodali映射到/workspace文件夹
root@16aa6953dfb3:/workspace# ls
AilabFaceSecuritySDK-v1.0.0 backup faceDataset faceDataset_detect faceDataset_extract fddb_images testAilabFaceSecuritySDK-v1.0.0 zhaodali_replay.zip

# 若想将/data4/zhaodali映射到/workspace文件夹,则使用下面指令
docker run --gpus all -v /data4/zhaodali:/workspace -ti ubuntu-opencv-torch:latest /bin/bash

想要退出的话,直接按下ctrl + D指令。

若想在docker内连接内网源安装软件和Python包,则需要运行下面指令,然后更改镜像内的apt软件源和pip源为内网源。

1
docker run --gpus all -v /dev/dri:/dev/dri --ipc=host -it --add-host mirrors.tencent.com:100.115.83.221 --add-host mirrors.cloud.tencent.com:100.115.83.221 -v /data6/zhaodali:/workspace -ti ubuntu-opencv-torch:latest /bin/bash

若进入docker后还是连不上内网,则将--ipc=host改为--network=host

若出现错误ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm),则在开启docker的时候加上--ipc=host指令,让docker容器共享主机内存。

查看运行中的容器

1
2
3
4
# 查看运行中的容器
docker ps
# 查看所有的容器
docker ps -a

开启/停止/重启容器

1
2
3
4
5
6
7
8
# 关闭容器(发送SIGTERM信号,做一些'退出前工作',再发送SIGKILL信号)
docker stop anyesu-container
# 强制关闭容器(默认发送SIGKILL信号, 加-s参数可以发送其他信号)
docker kill anyesu-container
# 启动容器
docker start anyesu-container
# 重启容器
docker restart anyesu-container

删除容器

1
docker rm [ 容器名 or 容器 id ]

可以指定多个容器一起删除, 加 -f 选项可强制删除正在运行的 容器

1
2
3
4
5
6
7
ubuntu@VM-84-201-ubuntu:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd7a6c1ba0f0 tomcat "catalina.sh run" 20 seconds ago Up 18 seconds 0.0.0.0:32798->8080/tcp, 0.0.0.0:32797->8081/tcp, 0.0.0.0:32796->8082/tcp musing_newton
61941bea1c87 tomcat "catalina.sh run" About a minute ago Up About a minute 0.0.0.0:8000-8001->8000-8001/tcp, 0.0.0.0:32795->8080/tcp, 0.0.0.0:32794->8081/tcp, 0.0.0.0:32793->8082/tcp anyesu-container
ubuntu@VM-84-201-ubuntu:~$ docker rm musing_newton anyesu-container -f
musing_newton
anyesu-container

查看容器详情

1
docker inspect [ 容器名 or 容器 id ]

比如

1
docker inspect anyesu-container

查看容器中正在运行的进程

1
docker top [ 容器名 or 容器 id ]

比如:

1
2
3
ubuntu@VM-84-201-ubuntu:~$ docker top anyesu-container
UID PID PPID C STIME TTY TIME CMD
root 31769 31752 1 00:26 ? 00:00:03 /docker-java-home/jre/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start

保存容器

1
docker commit [ 容器名 or 容器 id ] [ 镜像名 ]:[ tag ]

比如:

1
2
3
4
5
6
7
8
ubuntu@VM-84-201-ubuntu:~$ docker commit anyesu-container anyesu/tomcat:1.0
sha256:582fcffd3209a2478e2179c9381a1ef67e0df9ba95aba713875c0857f5dae4e5
ubuntu@VM-84-201-ubuntu:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
anyesu/tomcat 1.0 582fcffd3209 2 seconds ago 334MB
alpine latest a41a7446062d 17 hours ago 3.97MB
tomcat latest 3695a0fe8320 2 days ago 334MB
hello-world latest 48b5124b2768 4 months ago 1.84kB

再比如:

1
2
3
4
5
6
7
(base) [zhaodali@TENCENT64 /data6/zhaodali]$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c433608fdb59 cwaffles/openpose:latest "/bin/bash" 3 hours ago Up 3 hours eager_mclean

# 容器id可以只写几位
(base) [zhaodali@TENCENT64 /data6/zhaodali]$ docker commit c4336 cwaffles/openpose:1.0
sha256:8208e6744b38479b2728e83a30adbfdc7e0baa15cc0f431d2d2bf53e14a9577f

重命名容器

1
2
3
4
5
6
# 当得知容器名时
docker rename container_name new_name

# 若想直接通过image,比如说,centos7-python3.10-cu11.8-cudnn8.9.0-pytorch2.0.0更改为centos7-python3.10-cu11.8-cudnn8.9.0-pytorch2.0.0-runtime,他的image id为12bd3254d657
docker image tag 12bd3254d657 mirrors.tencent.com/sec-gpus/centos7-python3.10-cu11.8-cudnn8.9.0-pytorch2.0.0-runtime
docker rmi centos7-python3.10-cu11.8-cudnn8.9.0-pytorch2.0.0

开启新终端进入同一个docker

可以先通过docker ps获取container id,然后通过docker exec -it ${container_id} /bin/bash 进入,如果不是/bin/bash环境,可以使用/bin/sh进入。

使用 Dockerfile 构建镜像

1
docker build -t [ 镜像名 ]:[ tag ] -f [ DockerFile 名 ] [ DockerFile 所在目录 ]

数据是实时更新的,点击 查看详细用法。

若在构建镜像时,出现了无法连接网络安装依赖时,可以在上面指令后面添加--network=host

映射jupyter-notebook

启动Docker:

1
NV_GPU=0 nvidia-docker run -it -p 7777:8888 -ti --ipc=host a9aad2420ea3

使用docker ps查看刚启动的container实例:

1
2
3
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc56fc116249 78c6f941bef3 "/bin/bash" 10 hours ago Up 10 hours 6006/tcp, 0.0.0.0:7777->8888/tcp pedantic_gagarin

可以看到,这里container实例开放了6006和8888两个端口,其中8888端口映射到了主机的7777端口。此时进入Docker,在需要执行jupyter notebook的文件夹内打开终端运行如下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(solaris) root@cc56fc116249:/opt/conda/pkgs# jupyter notebook --ip 0.0.0.0 --no-browser --allow-root &
[1] 14781
(solaris) root@cc56fc116249:/opt/conda/pkgs# [I 11:27:03.688 NotebookApp] JupyterLab extension loaded from /opt/conda/envs/solaris/lib/python3.7/site-packages/jupyterlab
[I 11:27:03.688 NotebookApp] JupyterLab application directory is /opt/conda/envs/solaris/share/jupyter/lab
[I 11:27:03.690 NotebookApp] Serving notebooks from local directory: /opt/conda/pkgs
[I 11:27:03.690 NotebookApp] Jupyter Notebook 6.1.4 is running at:
[I 11:27:03.690 NotebookApp] http://cc56fc116249:8888/?token=dcb8fd9afd7f4182fa3f2c4ecf39df2a1090bd62599e20f1
[I 11:27:03.690 NotebookApp] or http://127.0.0.1:8888/?token=dcb8fd9afd7f4182fa3f2c4ecf39df2a1090bd62599e20f1
[I 11:27:03.690 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 11:27:03.693 NotebookApp]

To access the notebook, open this file in a browser:
file:///root/.local/share/jupyter/runtime/nbserver-14781-open.html
Or copy and paste one of these URLs:
http://cc56fc116249:8888/?token=dcb8fd9afd7f4182fa3f2c4ecf39df2a1090bd62599e20f1
or http://127.0.0.1:8888/?token=dcb8fd9afd7f4182fa3f2c4ecf39df2a1090bd62599e20f1

回到主机,在浏览器中打开http://127.0.0.1:7777/?token=dcb8fd9afd7f4182fa3f2c4ecf39df2a1090bd62599e20f1(注意需要将上面链接中的8888端口替换为7777端口)。如果需要输入token,则输入后面的dcb8fd9afd7f4182fa3f2c4ecf39df2a1090bd62599e20f1即可。

硬件资源相关

显示容器硬件资源使用情况

1
docker stats [ 选项 ] [ 0个或多个正在运行容器 ]

比如:

1
2
3
4
# 不指定容器时显示所有正在运行的容器
ubuntu@VM-84-201-ubuntu:~$ docker stats
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
9bb9d6bed6e6 0.00% 20.57MiB / 864.5MiB 2.38% 104kB / 1.99MB 4.9MB / 4.1kB 11

更新容器的硬件资源限制

1
docker update [ 选项 ]

这个操作可能会输出下面的错误内容:

1
Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap

解决办法

1
2
3
4
5
6
7
8
9
10
11
# /etc/default/grub
sudo vi /etc/default/grub

# 添加内核启动参数
GRUB_CMDLINE_LINUX="... cgroup_enable=memory swapaccount=1"

# 更新 grub
sudo update-grub

# 重启
sudo reboot

注意是在 GRUB_CMDLINE_LINUX追加 上述参数内容, 我试过简单粗暴的在文件末尾添加下面内容, 这么做会覆盖原有的启动参数, 导致网络连接失败。网络坏了, ssh 都连不上了, 幸好可以在 腾讯云 的网页控制台登录, 修改内容重启就好了。所以呢, 这一步操作一定要慎重。

使用压力测试工具 stress 验证效果

使用已有的 stress 镜像 progrium/stress, 开两个终端, 在其中一个终端中执行下面的命令

1
docker run -m 100m --rm -it progrium/stress --cpu 2 --io 1 --vm 10 --vm-bytes 9M

在另一个终端执行 docker stats 进行监控

1
2
CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9eb0 88.42% 92.22MiB / 100MiB 92.22% 0B / 0B 1.65MB / 2.88MB 14

再开一个终端执行

1
2
# 9eb0为容器id开头, 请根据实际情况替换。内存限制只能调大不能调小
docker update -m 200m 9eb0

基础子命令列表

选项说明
attach进入运行中的容器, 显示该容器的控制台界面。注意, 从该指令退出会导致容器关闭
build根据 Dockerfile 文件构建镜像
commit提交容器所做的改为为一个新的镜像
cp在容器和宿主机之间复制文件
create根据镜像生成一个新的容器
diff展示容器相对于构建它的镜像内容所做的改变
events实时打印服务端执行的事件
exec在已运行的容器中执行命令
export导出容器到本地快照文件
history显示镜像每层的变更内容
images列出本地所有镜像
import导入本地容器快照文件为镜像
info显示 Docker 详细的系统信息
inspect查看容器或镜像的配置信息, 默认为 json 数据
kill-s 选项向容器发送信号, 默认为 SIGKILL 信号 ( 强制关闭 )
load导入镜像压缩包
login登录第三方仓库
logout退出第三方仓库
logs打印容器的控制台输出内容, -f 选项可以持续输出
pause暂停容器
port容器端口映射列表
ps列出正在运行的容器, -a 选项显示所有容器
pull从镜像仓库拉取镜像
push将镜像推送到镜像仓库
rename重命名容器名
restart重启容器
rm删除已停止的容器, -f 选项可强制删除正在运行的容器
rmi删除镜像 ( 必须先删除该镜像构建的所有容器 )
run根据镜像生成并进入一个新的容器
save打包本地镜像, 使用压缩包来完成迁移
search查找镜像
start启动关闭的容器
stats显示容器对资源的使用情况 ( 内存、CPU、磁盘等 )
stop关闭正在运行的容器
tag修改镜像 tag
top显示容器中正在运行的进程 ( 相当于容器内执行 ps -ef 命令 )
unpause恢复暂停的容器
update更新容器的硬件资源限制 ( 内存、CPU 等 )
version显示 Docker 客户端和服务端版本信息
wait阻塞当前命令直到对应的容器被关闭, 容器关闭后打印结束代码
daemon这个子命令已 过期, 将在 Docker 17.12 之后的版本中移出, 直接使用 dockerd

用于管理的子命令列表

选项说明
container管理容器
image管理镜像
network管理容器网络 ( 默认为 bridgehostnone 三个网络配置)
plugin管理插件
system管理系统资源。其中, docker system prune 命令用于清理没有使用的镜像、容器、数据卷以及网络
volume管理数据卷
swarm管理 Swarm 模式
service管理 Swarm 模式下的服务
node管理 Swarm 模式下的 Docker 集群中的节点
secret管理 Swarm 模式下的敏感数据
stackSwarm 模式下利用 compose-file 管理服务

说明:

其中 containerimagesystem 一般用前面的简化指令即可。Swarm 模式用来管理 Docker 集群, 它将一群 Docker 宿主机变成一个单一的虚拟的主机, 实现对多台物理机的集群管理。

Docker空间扩容

docker默认是把数据(images、containers等)保存在/var/lib/docker中,有的人根目录空间很有限,想给docker扩容,怎么办呢?

可以使用docker info指令查看存储的位置,例如Docker Root Dir: /var/lib/docker

一种办法是先停止docker daemon,然后把上述目录移动到/opt/data或者其他的有空间的目录下,最后在/var/lib下做个同名的docker软连接,指向/opt/data/docker:

1
2
3
4
5
6
service docker stop(或者/etc/init.d/docker stop)

mv /var/lib/docker /opt/data
ln -s /opt/data/docker /var/lib/docker

service docker start

若遇到/var/lib/docker无法删除时,可以参考https://github.com/moby/moby/issues/6077。

1
2
cat /proc/mounts |grep docker
sudo umount /path

参考

Docker 常用指令详解
获取镜像
Can’t install pip packages inside a docker container with Ubuntu
删除镜像
如何解决 image has dependent child images 错误
怎么在 docker 中开启多个终端
在 docker 中运行 Jupyter notebook
Docker load and save: “archive/tar: invalid tar header”
ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm). #283
Cannot remove /var/lib/docker after changing docker runtime root to /home/docker after a fresh install with no containers / images #6077
给docker扩容、删除/var/lib/docker
Docker 查看容器映射路径
Docker how to change repository name or rename image?

------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道