深入了解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 container

Options:
  -d, --detach               Detached mode: run command in the background
      --detach-keys string   Override the key sequence for detaching a container
  -e, --env list             Set environment variables
  -i, --interactive          Keep STDIN open even if not attached
      --privileged           Give extended privileges to the command
  -t, --tty                  Allocate a pseudo-TTY
  -u, --user string          Username or UID (format: <name|uid>[:<group|gid>])
  -w, --workdir string       Working 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] IMAGE

Options:
      --format string   Pretty-print images using a Go template
  -H, --human           Print sizes and dates in human readable format (default true)
      --no-trunc        Don't truncate output
  -q, --quiet           Only show numeric IDs

下面演示-H选项的使用

# docker history ubuntu -H=false
IMAGE               CREATED AT                  CREATED BY                                      SIZE                COMMENT
<missing>           2020-04-24T09:07:48+08:00   /bin/sh -c [ -z "$(apt-get indextargets)" ]     1006705
<missing>           2020-04-24T09:07:46+08:00   /bin/sh -c #(nop) ADD file:a58c8b447951f9e30…   72844599
[root@51yunwei ~]# docker history ubuntu -H
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
<missing>           6 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     1.01MB
<missing>           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
<missing>: 操作时间:6 weeks ago 空间大小:7B
<missing>: 操作时间:6 weeks ago 空间大小:811B
<missing>: 操作时间:6 weeks ago 空间大小:1.01MB
<missing>: 操作时间: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
......
<missing> 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-suggests   811B
......

2.1.8 info

info命令显示Docker的摘要信息。查看官网文档

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 objects

Options:
  -f, --format string   Format the output using the given Go template
  -s, --size            Display total file sizes if the type is container
      --type string     Return 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 container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
      --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show 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 containers

Options:
  -a, --all             Show all containers (default shows just running)
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print containers using a Go template
  -n, --last int        Show n last created containers (includes all states) (default -1)
  -l, --latest          Show the latest created container (includes all states)
      --no-trunc        Don't truncate output
  -q, --quiet           Only display numeric IDs
  -s, --size            Display total file sizes

过滤器选项(--filter)使用格式为key=value这样的kv对,如果有多个过滤器,则可以提供多个kv条件。当前支持的过滤器:

过滤器 描述
id 容器ID
name 容器名
label 表示键或键值对的任意字符串。表示为<key>或<key>=<value>
exited 表示容器的退出代码的整数。仅对--all有用
status 下列之一:created, restarting, running, removing, paused, exited, dead
ancestor 筛选从指定的image共同派生的容器,表示为<image-name>[:<tag>], <image id>, 或者image@digest
before or since 按照给出的容器ID或名称,筛选出那些在指定时间之前或之后创建的容器
volume 筛选出挂载或绑定了指定卷的,正在运行的容器
network 筛选出连接到指定网络的,正在运行的容器
publish or expose 筛选出发布或公开给定网络端口的容器,表示为<port>[/<proto>] 或者<startport-endport>/[<proto>]
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 ID        NAMES               SIZE                      STATUS
03b22680693f        ubuntu              1.22kB (virtual 73.9MB)   Up 35 hours
19f4db6db14f        magical_almeida     0B (virtual 13.3kB)       Exited (0) 7 days ago
9cee21753a37        amazing_galois      0B (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 int   Seconds to wait for stop before killing the container (default 10)

当执行restart命令时,Docker会先stop容器,然后再start容器。如果在stop的时候,容器内部出现一些不正常的原因导致容器长时间无法正常停止,restart命令将会发送SIGKILL信号,要求容器立刻关闭。

选项(--time)就是这个等待正常关闭的时间,默认为10秒。

推荐阅读更多精彩内容