深入了解Docker(3)|深入了解Docker(3) - Cli命令2

目录 深入了解Docker(1) 环境搭建
深入了解Docker(2) - Cli命令1
深入了解Docker(3) - Cli命令2
2.1.6 exec
exec是在容器内部执行命令的命令。在Docker使用过程中,很少出现启动容器时就直接创建pty,在pty中人工执行命令的情况,这种情况在生产系统中是不应该采用的。因此绝大多数情况,容器都采取-d后台运行模式。
exec能够在容器中执行脚本、命令或容器中合法的工具。查看官网文档

小技巧:进入容器有很多种姿势,比如说ssh,再比如说attach。根据不同的需要,可以采用不同的方式和容器交互,在容器中执行命令。但是,一般不建议在容器中使用ssh。感兴趣,可以阅读一下这个小短文《为什么不需要在 Docker 容器中运行 sshd》
Usage:docker exec [OPTIONS] CONTAINER COMMAND [ARG...] Run a command in a running containerOptions: -d, --detachDetached mode: run command in the background --detach-keys stringOverride the key sequence for detaching a container -e, --env listSet environment variables -i, --interactiveKeep STDIN open even if not attached --privilegedGive extended privileges to the command -t, --ttyAllocate a pseudo-TTY -u, --user stringUsername or UID (format: [:]) -w, --workdir stringWorking directory inside the container

如果仅仅是执行简单命令,那么不会用到什么选项。如果需要交互,例如vim /tmp/111.txt,那就需要使用-it选项,打开一个pty,保持stdin,以便容器通过pty接收控制字符,完成编辑器需要的交互。
# docker exec -it ubuntu vi /tmp/111.txt

COMMAND 应该是一个可执行体,如果执行一个调用链或者是引号包括的语句块则无法正常运行。例如:
docker exec -ti my_container "echo a && echo b" # 无法运行 docker exec -ti my_container sh -c "echo a && echo b" # 可以正常运行

--env , -e 选项,为新创建的session添加环境变量,这个环境变量只在这次会话中生效。例子:
$ docker exec -it -e VAR=1 ubuntu_bash bash

--detach , -d 选项在后台模式下执行(run command in the background)
--workdir , -w 选项,指定在容器内的工作路径。例子:
$ docker exec -it ubuntu_bash pwd# 默认路径 / $ docker exec -it -w /root ubuntu_bash pwd# 设置了工作路径后 /root

2.1.7 history
类似容器的diff命令,image(镜像)也可以使用history命令查看历史变更。history命令能够将image构建过程中所有执行过的命令显示出来。查看官网文档
Usage:docker history [OPTIONS] IMAGEOptions: --format stringPretty-print images using a Go template -H, --humanPrint sizes and dates in human readable format (default true) --no-truncDon't truncate output -q, --quietOnly show numeric IDs

下面演示-H选项的使用
# docker history ubuntu -H=false IMAGECREATED ATCREATED BYSIZECOMMENT 2020-04-24T09:07:48+08:00/bin/sh -c [ -z "$(apt-get indextargets)" ]1006705 2020-04-24T09:07:46+08:00/bin/sh -c #(nop) ADD file:a58c8b447951f9e30…72844599 [root@51yunwei ~]# docker history ubuntu -H IMAGECREATEDCREATED BYSIZECOMMENT 6 weeks ago/bin/sh -c [ -z "$(apt-get indextargets)" ]1.01MB 6 weeks ago/bin/sh -c #(nop) ADD file:a58c8b447951f9e30…72.8MB

--format 选项可以使用Go模版,输出更加人性化的信息,也可以转换成json等更容易处理的格式:
[root@51yunwei ~]# docker history --format "{{.ID}}: 操作时间:{{.CreatedSince}} 空间大小:{{.Size}}" ubuntu 1d622ef86b13: 操作时间:6 weeks ago 空间大小:0B : 操作时间:6 weeks ago 空间大小:7B : 操作时间:6 weeks ago 空间大小:811B : 操作时间:6 weeks ago 空间大小:1.01MB : 操作时间:6 weeks ago 空间大小:72.8MB

下面是模版变量:
占位符 描述
.ID Image ID
.CreatedSince Elapsed time since the image was created if --human=true, otherwise timestamp of when image was created
.CreatedAt Timestamp of when image was created
.CreatedBy Command that was used to create the image
.Size Image disk size
.Comment Comment for image
如果想知道详细的历史操作,可以使用--no-trunc=true参数:
[root@51yunwei ~]# docker history ubuntu --no-trunc=true ...... 6 weeks ago /bin/sh -c set -xe&& echo '#!/bin/sh' > /usr/sbin/policy-rc.d&& echo 'exit 101' >> /usr/sbin/policy-rc.d&& chmod +x /usr/sbin/policy-rc.d&& dpkg-divert --local --rename --add /sbin/initctl&& cp -a /usr/sbin/policy-rc.d /sbin/initctl&& sed -i 's/^exit.*/exit 0/' /sbin/initctl&& echo 'force-unsafe-io' > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup&& echo 'DPkg::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; ' > /etc/apt/apt.conf.d/docker-clean&& echo 'APT::Update::Post-Invoke { "rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true"; }; ' >> /etc/apt/apt.conf.d/docker-clean&& echo 'Dir::Cache::pkgcache ""; Dir::Cache::srcpkgcache ""; ' >> /etc/apt/apt.conf.d/docker-clean&& echo 'Acquire::Languages "none"; ' > /etc/apt/apt.conf.d/docker-no-languages&& echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz"; ' > /etc/apt/apt.conf.d/docker-gzip-indexes&& echo 'Apt::AutoRemove::SuggestsImportant "false"; ' > /etc/apt/apt.conf.d/docker-autoremove-suggests811B ......

2.1.8 info
info命令显示Docker的摘要信息。查看官网文档
【深入了解Docker(3)|深入了解Docker(3) - Cli命令2】info命令没有什么功能性选项,可以直接使用。
但是,info同样支持--format参数,这样就可以使用Go模版,或直接输出json格式,便于阅读或管理。
$ docker info --format '{{json .}}'{"ID":"I54V:OLXT:HVMM:TPKO:JPHQ:CQCD:JNLC:O3BZ:4ZVJ:43XJ:PFHZ:6N2S","Containers":14, ...}

[root@51yunwei ~]# docker info -f '容器数量:{{.Containers}}, 当前操作系统是{{.OSType}}.' 容器数量:3, 当前操作系统是linux.

2.1.9 inspect
inspect是探查之意。当在Docker中使用inspect命令,Docker Daemon能够将底层镜像和容器的底层信息(low-level information on Docker objects)都返回。查看官网文档
同info命令类似,很多Docker命令都开始支持JSON格式,或者提供Go模板进行信息格式的定义,这样就大大方便了运维脚本的编写和更有挑战性的应用。
Usage:docker inspect [OPTIONS] NAME|ID [NAME|ID...] Return low-level information on Docker objectsOptions: -f, --format stringFormat the output using the given Go template -s, --sizeDisplay total file sizes if the type is container --type stringReturn JSON for specified type

inspect主要返回以下几类信息:
  1. 基本信息类:名称、创建时间、当前状态(run、stop、pause)等;
  2. 运行参数类:包括网络信息、环境变量、主机名称等;
  3. 底层数据类:包括CPU设置、内存设置、虚拟化设置等。
[root@51yunwei ~]# docker inspect ubuntu -f 'IP地址:{{.NetworkSettings.IPAddress}}' IP地址:172.17.0.2[root@51yunwei ~]# docker inspect ubuntu -f 'IP地址:{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' IP地址:172.17.0.2

2.1.10 kill
正常情况下,容器的停止应该使用stop命令。当容器内进程出现死循环、容器资源耗尽已经无法按照正常流程关闭时,可以考虑使用kill命令。查看官网文档
和Unix/Linux操作系统类似,kill命令虽然多数用来杀死进程,但本质上是个发送信号 signal的作用。
小知识:为什么UNIX系统调用kill称为“ kill”?点击查看
  • 实际上,信号的最初目的是杀死目标进程。kill出现在Unix第三版,当时用于root用户强制终止进程(例如今天的SIGKILL)并进行coredump。
  • 在Unix第4版中,增加了signal编号参数,用于signal()系统调用,程序员可以使用自己的 handler 处理信号。但是,如果信号没有被目标处理程序调用,那么所有没处理的信号都能杀死目标进程。
  • 随着时间的流逝,越来越多的信号出现了。其中一些信号默认不会终止目标进程。但是kill这个名字仍然存在。
  • POSIX委员会曾经讨论重新命名kill,因为不是所有信号都旨在终止目标进程。但是,历史总是根深蒂固的,改变往往会带来更大的混乱,所以此事最终不了了之。
docker kill命令支持空格分隔的多个容器,默认发送SIGKILL信号给指定的容器。如果打算发送特定信号给容器,可以使用--signal , -s参数。字符串前缀SIG可以被省略,还可以直接使用数字。
$ docker kill --signal=SIGHUP my_container $ docker kill --signal=HUP my_container $ docker kill --signal=1 my_container

可以参考操作系统man手册页中signal(7),查看Linux标准的信号定义。
信号 动作 说明
SIGHUP 1 Term 在控制终端检测到挂起,或控制进程死亡
SIGINT 2 Term 键盘中断,INT
SIGQUIT 3 Core 键盘中断,QUIT
SIGILL 4 Core 非法指令
SIGABRT 6 Core abort(3)递送退出信号
SIGFPE 8 Core 浮点异常
SIGKILL 9 Term kill信号
SIGSEGV 11 Core 引用无效内存
SIGPIPE 13 Term 管道的另外一端已经关闭
2.1.11 logs
使用log命令可以获取到容器内部应用输出的日志。logs命令仅适用于那些使用json-file或journald日志驱动程序启动的容器。 。查看官网文档
Usage:docker logs [OPTIONS] CONTAINER Fetch the logs of a containerOptions: --detailsShow extra details provided to logs -f, --followFollow log output --since stringShow logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes) --tail stringNumber of lines to show from the end of the logs (default "all") -t, --timestampsShow timestamps --until stringShow logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)

--follow 选项,持续处理容器中被重定向到stdout或stderr输出的内容流。只要命令不退出,容器最新的日志就能始终输出出来。
2.1.12 ps
ps命令用来显示容器。查看官网文档
ps是Docker最常用的命令之一。通过ps命令,我们可以了解目前所有容器运行的状态信息,以便于管理员后续操作。
Usage:docker ps [OPTIONS] List containersOptions: -a, --allShow all containers (default shows just running) -f, --filter filterFilter output based on conditions provided --format stringPretty-print containers using a Go template -n, --last intShow n last created containers (includes all states) (default -1) -l, --latestShow the latest created container (includes all states) --no-truncDon't truncate output -q, --quietOnly display numeric IDs -s, --sizeDisplay total file sizes

过滤器选项(--filter)使用格式为key=value这样的kv对,如果有多个过滤器,则可以提供多个kv条件。当前支持的过滤器:
过滤器 描述
id 容器ID
name 容器名
label 表示键或键值对的任意字符串。表示为=
exited 表示容器的退出代码的整数。仅对--all有用
status 下列之一:created, restarting, running, removing, paused, exited, dead
ancestor 筛选从指定的image共同派生的容器,表示为[:], , 或者image@digest
before or since 按照给出的容器ID或名称,筛选出那些在指定时间之前或之后创建的容器
volume 筛选出挂载或绑定了指定卷的,正在运行的容器
network 筛选出连接到指定网络的,正在运行的容器
publish or expose 筛选出发布或公开给定网络端口的容器,表示为[/] 或者/[]
health 根据下列健康检查状态过滤容器,starting, healthy, unhealthy, none
isolation Windows守护状态专用,default / process / hyperv
is-task Filters containers that are a “task” for a service. Boolean option (true or false)
格式化选项(--format),能够使用Go模板进行输出,使用者可以根据自己的需要灵活设置输出格式。
占位符 描述
.ID 容器编号
.Image 镜像编号
.Command 引用命令
.CreatedAt 创建容器的时间
.RunningFor 自容器启动以来经过的时间
.Ports 暴露的端口
.Status 当前容器状态
.Size 容器占用的磁盘大小
.Names 容器名称
.Labels 分配给容器的所有标签
.Label 此容器的特定标签值。例如'{{.Label "com.docker.swarm.cpu"}}'
.Mounts 挂载到此容器中的卷的名称
.Networks 连接到此容器的网络的名称
格式化输出的例子(注意使用table关键字后,将输出列标题):
[root@51yunwei ~]# docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Size}}\t{{.Status}}" CONTAINER IDNAMESSIZESTATUS 03b22680693fubuntu1.22kB (virtual 73.9MB)Up 35 hours 19f4db6db14fmagical_almeida0B (virtual 13.3kB)Exited (0) 7 days ago 9cee21753a37amazing_galois0B (virtual 13.3kB)Exited (0) 7 days ago

2.1.13 rename
为容器改名。查看官网文档
# docker rename CONTAINER NEW_NAME

2.1.14 restart
重新启动一个或多个容器。查看官网文档
docker restart [OPTIONS] CONTAINER [CONTAINER...]

命令只有一个参数:
-t, --time intSeconds to wait for stop before killing the container (default 10)

当执行restart命令时,Docker会先stop容器,然后再start容器。如果在stop的时候,容器内部出现一些不正常的原因导致容器长时间无法正常停止,restart命令将会发送SIGKILL信号,要求容器立刻关闭。
选项(--time)就是这个等待正常关闭的时间,默认为10秒。

    推荐阅读