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 stop
(kill
)命令后,容器会变成停止状态。创建一个交互式容器,需要加入
-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+D
或exit
命令,之后容器会停止。要让容器继续运行可以使用快捷键Ctrl+PQ
来退出交互模式。 -
后台型容器
容器运行在后台,创建启动之后和终端无关。只有调用
docker stop
或docker 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 start
或 docker 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