Docker 容器操作

创建容器

创建容器可以使用 docker create 命令或 docker run 命令。

创建静止容器

使用 docker create 命令可以创建一个处于停止状态的容器:

[root@server4 ~]$ docker create alpine
53b658ada694f5d5a5a5ba8e1bf656db4de8bacd79d4ae49857fe1ce27f60292

创建容器后,Docker 会立即返回容器的 ID。每个容器的 ID 都是唯一的。

在大多数镜像中已经设定了基于这个镜像的容器,在启动时要运行的程序,也可以在创建容器时重新指定容器所绑定的应用程序。例如,指定运行 tail -f /var/log/messages 命令:

[root@server4 ~]$ docker create ubuntu:18.04 tail -f /var/log/messages
a7420c78df7388b3317364e0089491928ff0e2d184261d49b8315bc4fce8ed0d

创建运行容器

使用 docker run 命令可以创建两种类型的容器:

  • 交互型容器

    容器运行默认在前台,通常会指定有交互的控制台,可以给容器输入,得到容器输出。如果创建容器的终端被关闭,容器内部使用 exit 命令退出,或调用 docker stopkill)命令后,容器会变成停止状态。

    创建一个交互式容器,需要加入 -t 选项让 Docker 为容器创建一个伪终端并绑定到容器标准输入上。加入 -i 选项让容器的标准输入保持打开。例如,创建启动一个名为 myshell 的 Ubuntu 容器:

    [root@server4 ~]$ docker run -i -t --name=myshell ubuntu:18.04 /bin/bash
    root@fffa37ac6638:/# 

    容器启动以后进入 bash shell,由提示符可得用户名为 root,主机名也就是容器短 ID 为 fffa37ac6638。

    要退出容器可以使用快捷键 Ctrl+Dexit 命令,之后容器会停止。要让容器继续运行可以使用快捷键 Ctrl+PQ 来退出交互模式。

  • 后台型容器

    容器运行在后台,创建启动之后和终端无关。只有调用 docker stopdocker kill 命令才能使容器变成停止状态。

    在实际应用中,大多数容器都是后台运行式容器,在创建时使用 -d 参数。例如,创建后台运行的 Ubuntu 容器,并指定一个不会终止的命令:

    [root@server4 ~]$ docker run --restart=always --name dshell -d ubuntu:18.04 /bin/sh -c "while true; do echo sleeping; sleep 1; done"
    bb018e9f0619a23f0e4cdc23cee2b738ecc3dc34dc8c7d3eaa4b93c9ddcd2b7e

容器启动参数

使用 docker run 命令启动容器时可以指定一些启动参数。

常用参数

常用启动参数如下:

  • -d:设置容器在后台运行。
  • -i:保持标准输入打开。
  • -t:分配一个伪终端。
  • --name='':设定容器名称,如果不指定系统会随机分配一个名称。最大用途是用在两个容器之间建立 link 通信。
  • --restart="":重启策略,可以设置为以下几种策略。
    • No:默认选项,没有任何重启操作。
    • Always:无论容器处于什么状态都执行重启。同时容器会在 Docker 服务端启动时自启动。
    • On-failure:当容器的命令返回非 0 值时重启。
    • Unless-stopped:和 Always 类似,但不会自启动。
  • --rm:容器退出后,自动删除容器。不能和 -d--rm 同时使用。
  • --privileged:特权模式。容器可以访问除 AppArmor 和 SELinux 之外的主机所有进程。
  • --env=[]:指定容器内环境变量。

网络参数

与网络相关的启动参数如下:

  • --net="": 设置容器采用的网络方式,默认为 bridge。有以下几种模式:
    • none: 不使用网络。容器不能访问外部网络,但内部存在回环地址。
    • bridge: 桥接模式。容器通常连接到 docker0 网桥的 veth 口,网桥再连接到宿主机网络端口上。
    • host: 主机模式。直接使用宿主机网络,共享端口。容器所有暴露的端口和容器连接将失效。
    • container: 容器模式。将容器的网络栈合并在一起,容器可以不需要 IP 来进行通信。
    • 自定义网络: 对于 Overlay 和用户定义的多主机模式,Docker 可以采用此选项。
  • -p: 设置容器映射到主机的端口,设置格式为 -p 主机端口:容器端口
  • --link="": 链接到其他容器。更推荐使用 --net 参数为需要连接的容器分配一个专有网络。
  • --expose=[]: 设置容器暴露的端口或端口范围。
  • -P: 通过 NAT 将容器设置的暴露端口自动映射到本机临时端口,默认选取端口号范围为 49153~65535。
  • --dns=[]: 设置容器使用的 DNS 服务器。
  • --add-host="": 在容器内的 /etc/hosts 文件中添加自定义主机名解析。
  • --ip="": 设置容器的 IP 地址。
  • --hostname="": 设置容器的主机名。

文件参数

与文件系统挂载相关的参数如下:

  • -v: 将主机上的文件挂载到容器中,格式为 -v 主机路径:容器路径
  • --tmpfs=[]: 将临时文件系统挂载到容器中。
  • --device="": 将宿主机设备挂载到容器内,默认可读写,可以自定义权限。
  • --volumes-from=[]: 从其他容器挂载卷。
  • --workdir="": 设置容器内的默认工作目录。

其他参数

其他一些不常用的启动参数:

  • --pid="" 控制容器中进程使用的 PID。容器中执行的程序 PID 从 1 开始计算。常用 --pid=host 来与宿主机共享 PID。
  • -ust="": 设置容器中使用的主机名和域名模式。
  • --ipc="": 设置进程间通信模式。
  • --log-driver: 设置容器的日志等级,可以设置为以下等级:
    • none: 不显示日志。
    • json-file: 默认输出格式。
    • syslog: 将日志输出到系统日志 /var/log/message 中。
    • journald: 将日志写入 journald。
  • --isolation="": 设置容器使用的隔离机制。
  • -h: 设置容器的主机名。

管理容器

除了创建容器之外的管理容器命令.

启动容器

想要启动一个停止状态的容器,使用 docker start 命令:

[root@server4 ~]$ docker start fffa37ac663
fffa37ac663

针对一个运行中的容器,可以使用 docker restart 命令来重启:

[root@server4 ~]$ docker restart myshell
myshell

此外,使用 docker unpause 命令来恢复一个暂停的容器运行。

停止容器

使用 docker stop 命令可以给容器中的进程发送 SIGTERM 信号,默认等待 10 秒后,会发送 SIGKILL 信号来终止容器:

[root@server4 ~]$ docker stop 74b23cb72
74b23cb72

要发送 SIGKILL 信号来立即强行停止容器,使用 docker kill 命令:

[root@server4 ~]$ docker kill fffa37a
fffa37a

此外还可以使用 docker pause 命令来暂停容器。

删除容器

当容器不再需要时,可以使用 docker rm 命令删除停止状态的容器:

[root@server4 ~]$ docker rm 74b23cb722 myshell
74b23cb722
myshell

当然,也支持使用 -f 参数来强行删除运行中的容器。

重命名容器

可以使用 docker rename 命令来对容器进行重命名:

[root@server4 .docker]$ docker rename 86e7325c7729 cent

清理容器

使用 docker container prune 命令会清除所有处于停止状态的容器:

[root@server4 ~]$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
525899c2d8701ca12d44ac21d28beca50356c92cefe7d2c7159904c15dc41344

Total reclaimed space: 0B

导出容器

导出容器使用 docker export 命令。正在运行中的容器也可以导出,并且不用担心容器依赖的镜像问题:

[root@server4 ~]$ docker export 53b658ada > a.tar

与导出镜像类似,可以同时导出多个容器到一个文件。

导入容器

可以使用 docker import 命令导入通过 docker export 命令导出的容器作为镜像:

[root@server4 ~]$ docker import a.tar user1:0.1
sha256:7549e3270b729e1e908cde70ba3e0f2f9bf1b5abff2482fefa13775c2c62de2e
[root@server4 ~]$ docker images
REPOSITORY                TAG       IMAGE ID       CREATED         SIZE
user1                     0.1       7549e3270b72   7 seconds ago   5.6MB

与导入镜像的功能相比,容器快照文件会丢弃所有的历史记录和元数据信息。

另外,docker import 命令还可以用来导入模板创建镜像。

查询容器

查询容器信息的常用操作如下。

查询容器列表

查看正在运行中的容器使用 docker ps 命令:

[root@server4 ~]$ docker ps
CONTAINER ID IMAGE        COMMAND                CREATED        STATUS    PORTS    NAMES
74b23cb722cb ubuntu:18.04 "/bin/sh -c 'while t…" 22 seconds ago Up 21 seconds      dshell

其结果显示标头含义如下:

  • CONTAINER ID: 容器 ID,全长为 64 位的十六进制。可以使用容器 ID 的前几位来操作容器。
  • IMAGE: 创建容器时使用的镜像。
  • COMMAND: 容器最后运行的命令。
  • CREATED: 创建容器的时间。
  • STATUS: 容器的状态,其 UP 后的时间表示容器已经运行的时长。如果是 Exited(0) 的形式,括号内的数字表示容器退出时的状态码,常见的有:0(执行完正常退出)、125(docker 命令参数错误)、126(权限限制命令无法执行)、127(容器内的命令无法找到)。
  • PORTS: 对外开放的端口。
  • NAMES: 容器名,和容器 ID 一样标识容器,所以不能重名。

要查看所有容器,使用 -a 参数:

[root@server4 ~]$ docker ps -a
CONTAINER ID IMAGE         COMMAND           CREATED        STATUS  PORTS  NAMES
74b23cb722cb ubuntu:18.04  "/bin/sh -c 'wh"  9 minutes ago  Up 9 minutes   dshell
fffa37ac6638 ubuntu:18.04  "/bin/bash"       25 minutes ago Exited (130)   myshell
53b658ada694 alpine        "/bin/sh"         36 minutes ago Created        charming_jones

要查看最近创建的 2 个容器,使用 -n=x 参数:

[root@server4 ~]$ docker ps -n=2
CONTAINER ID IMAGE         COMMAND           CREATED        STATUS  PORTS  NAMES
74b23cb722cb ubuntu:18.04  "/bin/sh -c 'wh"  9 minutes ago  Up 9 minutes   dshell
fffa37ac6638 ubuntu:18.04  "/bin/bash"       25 minutes ago Exited (130)   myshell

此外还有 -f 过滤参数,在容器较多时可以快速过滤。可以使用以下方法进行过滤:

  • id: 容器 ID。
  • label: 容器的标记,可以来源于创建容器的镜像,或者在创建容器时通过 --label 参数设置。
  • name: 容器的名称。
  • exited: 容器停止时主进程的返回码。注意要与 -a 参数配合使用。
  • status: 容器的状态,可以是以下状态中一种:created、restarting、running、paused、exited、dead。
  • ancestor: 创建容器的镜像,可以指定镜像名或镜像 ID。
  • before: 给出一个容器名或容器 ID,返回给定容器之前创建的容器。
  • since: 给出一个容器名或容器 ID,返回给定容器之后创建的容器。
  • isolation: 隔离性,可以是 default、process、hyperv 等机制,只对 Windows 有用。
  • volume: 显示使用指定数据卷或挂载点的容器。
  • network: 显示使用指定网络 ID 或网络名称的容器。

查询容器进程

使用 docker top 命令,可以查看容器中正在运行的进程:

[root@server4 ~]$ docker top dshell 
UID  PID   PPID  C  STIME  TTY TIME      CMD
root 6625  6605  0  22:29  ?   00:00:00  /bin/sh -c while true; do echo sp; sleep 1; done
root 7736  6625  0  22:38  ?   00:00:00  sleep 1

docker top 命令显示结果类似于 ps 命令,它还可以套用 ps 命令的参数。

查询统计信息

使用 docker stats 命令来实时查询容器内进程对系统资源的使用情况:

[root@server4 ~]$ docker stats
CONTAINER ID NAME             CPU %  MEM USAGE / LIMIT MEM %  NET I/O     BLOCK I/O  PIDS
69e11c2ea066 reverent_vaughan 0.00%  408KiB / 3.682GiB 0.01%  656B / 0B   0B / 0B       1
c2382935fd0b dshell           0.16%  600KiB / 3.682GiB 0.02%  656B / 0B   2.26MB / 0B   2
099bc0337b97 myshell          0.00%  404KiB / 3.682GiB 0.01%  656B / 0B   0B / 0B       1

查询容器详情

同样可以使用 docker inspect 来查看容器的配置信息:

[root@server4 ~]$ docker inspect dshell
[
    {
        "Id": "c2382935fd0b1ea40949266e0818da70c0518c0ed340558c68fd97987be5fc2f",
        "Created": "2021-10-21T14:29:54.535612575Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true; do echo sleeping; sleep 1; done"
        ],
        "State": {
            "Status": "running",

查询容器日志

对于后台型容器,可以使用 docker logs 命令来查看容器的日志。它将输出到标准输出的数据作为日志输出到运行 docker logs 命令的终端上。

默认情况下,logs 输出的是从容器启动到调用执行 logs 命令时的所有输出。使用 -f 参数可以持续打印输出日志:

[root@server4 ~]$ docker logs -f dshell
sleeping
sleeping

也可以使用 --tail 参数来查看日志末尾输出行:

[root@server4 ~]$ docker logs --tail=5 dshell 
sleeping
sleeping

加入 -t 参数能显示日志输出时间:

[root@server4 ~]$ docker logs --tail=5 -t dshell 
2021-10-21T14:36:55.905640558Z sleeping
2021-10-21T14:36:56.907301372Z sleeping
2021-10-21T14:36:57.908906032Z sleeping

操作容器

一些常用的操作容器方式.

依附容器

在使用 docker startdocker restart 启动的交互型容器中,并没有具体的终端可以依附,这时需要通过 docker attach 命令将终端依附到容器上,相当于将容器切换到前台交互模式:

[root@server4 ~]$ docker start 099bc03
099bc03
[root@server4 ~]$ docker attach 099bc03
root@099bc0337b97:/# 

可以使用快捷键 Ctrl+P+Q 来退出容器,这样容器会保持运行。

后台型容器(只有 -d 没有 -it 参数)无法依附终端,因为它本身就不接受用户交互式输入。

容器内执行命令

可以使用 docker exec 命令在容器中运行新的任务。任务可以指定在后台运行或为交互型任务。

例如,在后台执行创建文件时,使用 -d 参数:

[root@server4 ~]$ docker exec -d dshell touch /root/data.conf

创建一个交互型任务时,使用 -it 参数:

[root@server4 ~]$ docker exec -it dshell /bin/bash
root@c2382935fd0b:/# 

复制文件

可以使用 docker cp 命令在容器与主机之间进行文件复制。命令格式如下:docker cp <源地址> <目标地址>

例如,将本地文件 /root/ftp.sh 复制到容器 myshell/home/ 目录下:

[root@server4 ~]$ docker cp /root/ftp.sh myshell:/home/
[root@server4 ~]$ docker exec myshell ls /home
ftp.sh

将容器 myshell 下的文件 /home/ftp.sh 复制到本地 /root/bin/ 目录下:

[root@server4 ~]$ docker cp myshell:/home/ftp.sh /root/bin/
[root@server4 ~]$ ll /root/bin
total 4
-rw-r--r--. 1 root root 52 Sep 23 19:18 ftp.sh

资源限制

Docker 通过 cgroup 来限制容器可使用的资源。

内存限额

默认情况下,对容器的资源使用没有限制。可以在创建容器时使用 -m 参数限制容器最大可使用的内存,并使用 --memory-swap 参数限制最大虚拟内存(默认为内存的两倍):

[root@server4 ~]$ docker run -m 20M --memory-swap=30M alpine

CPU 限额

Docker 通过设置 CPU 使用权重来分配容器可使用的 CPU 资源。通常只有在 CPU 资源紧张的情况下,才会实际限制。可以使用 -c 参数来设置 CPU 使用权重,默认值为 1024:

[root@server4 ~]$ docker run -it -c 128 alpine
[root@server4 ~]$ cat /sys/fs/cgroup/cpu/docker/1ffdbd1af1c64/cpu.shares 
128

读写限制

Docker 可以通过 Block IO 来限制容器对磁盘的读写带宽。有以下三种设置方式:

  • 设置权重

    默认情况下,容器可以平等地读写磁盘,可以通过设置 --blkio-weight 参数来改变读写优先级,默认值为 500:

    [root@server4 ~]$ docker run --blkio-weight 300 alpine
  • 限制读写速度(bps)

    bps(byte per second)表示每秒读写的字节数。可以使用 --device-read-bps--device-write-bps 参数来限制对特定设备的读写速度。

    例如,限制容器对 /dev/sda 的写入速度为 10 MB/s:

    [root@server4 ~]$ docker run -it --device-write-bps /dev/sda:10MB alpine
  • 限制 IOPS 次数

    IOPS(io per second) 表示每秒的输入输出次数。可以使用 --device-read-iops--device-write-iops 参数来限制对特定设备的每秒 IO 次数。

    例如,限制容器对 /dev/sda 每秒的 IO 次数为 100:

    root@server4 ~]$ docker run -it --device-write-iops /dev/sda:100 alpine