Docker 命令 之 容器(Container)

摘要

容器的生命周期

  • 容器可能处于以下几种状态:

    • 初建(created)
    • 运行(running)
    • 暂停(paused)
    • 停止(stopped)
    • 删除(deleted)
  • 各生命周期之间的转换关系如图所示:

命令/情况 说明 容器状态变更
docker create 创建容器后,不立即启动运行,容器进入初建状态 初建状态
docker run 创建容器,并立即启动运行,进入运行状态 初建 → 运行
docker start 启动已创建的容器,容器转为运行状态 停止 → 运行
docker stop 停止正在运行的容器,容器转入停止状态 运行 → 停止
docker kill 强制终止容器,相当于“断电”,容易丢失数据,不建议轻易使用 运行 → 停止(非正常)
docker restart 重启容器,容器重新进入运行状态 运行 → 停止 → 运行
docker pause 暂停容器内所有进程,容器进入暂停状态 运行 → 暂停
docker unpause 取消暂停状态,容器恢复运行 暂停 → 运行
docker rm 删除容器,容器转入删除状态 任意 → 删除
Killed by out-of-memory (OOM) 宿主机内存耗尽,容器被系统终止,此为非计划终止;建议杀死内存占用最高的容器 运行 → 停止(异常)
Container process exited 容器进程异常终止后,进入“是否重启”判断流程:是则执行 start 进入运行;否则保持停止状态 异常 → 停止或运行

docker container : 容器管理

  • docker container --help

命令 说明 别名
attach 将本地的标准输入、输出和错误流附加到一个正在运行的容器上 docker attach
commit 根据容器的更改创建一个新的镜像 docker commit
cp 在容器和本地文件系统之间复制文件/文件夹 docker cp
create 创建一个新的容器 docker create
diff 检查容器文件系统上的文件或目录的更改 docker diff
exec 在正在运行的容器中执行命令 docker exec
export 将容器的文件系统导出为 tar 归档文件 docker export
inspect 显示一个或多个容器的详细信息 可以使用 docker inspect
kill 终止一个或多个正在运行的容器 docker kill
logs 获取容器的日志 docker logs
ls 列出容器 docker ps
pause 暂停一个或多个容器内的所有进程 docker pause
port 列出容器的端口映射或特定的端口映射 docker port
prune 删除所有已停止的容器
rename 重命名一个容器 docker rename
restart 重启一个或多个容器 docker restart
rm 删除一个或多个容器 docker rm
run 根据镜像创建并运行一个新容器 docker run
start 启动一个或多个已停止的容器 docker start
stats 实时显示容器资源使用统计信息 docker stats
stop 停止一个或多个正在运行的容器 docker stop
top 显示容器中运行的进程 docker top
unpause 取消暂停一个或多个容器内的所有进程 docker unpause
update 更新一个或多个容器的配置 docker update
wait 阻塞直到一个或多个容器停止,然后打印其退出代码 docker wait
  • 运行 docker container COMMAND --help 可获取某个命令的更多信息。

docker create : 创建容器,但不启动

1
2
3
4
5
6
7
$ docker create \
--name my-container \ # 容器名
-e MY_ENV_VAR=my-value \ # 设置环境变量
-p 80:80 \ # 映射端口,格式:宿主机端口:容器端口
-v /path/to/my/dir:/path/in/container \ # 映射目录,格式:宿主机目录:容器目录,都必须是绝对路径
--restart always \ # 设置重启策略
nginx:latest \ # 镜像名,镜像不存在时会自动下载
  • docker createdocker run 的参数基本一致,具体查看下面 docker run 中的介绍。

docker start : 启动一个容器

  • 启动一个容器,容器必须已经创建,并且处于停止状态。

1
2
# 语法:docker start <container_id|container_name>
$ docker start my-container

docker run : 创建并启动一个容器

  • 相当于docker create + docker start

  • 常用参数说明

参数 说明 示例
-d, --detach 后台运行容器(即“守护态”),run独有 docker run -d nginx
-it 交互式运行容器并分配终端(常用于调试) docker run -it ubuntu bash
--name 指定容器名称 docker run --name my-nginx nginx
--rm 容器退出时自动删除 docker run --rm ubuntu
-p, --publish 端口映射(宿主机:容器) docker run -p 8080:80 nginx
-P, --publish-all 自动随机映射容器内部所有暴露端口到宿主机端口 docker run -P nginx
-v, --volume 挂载卷(宿主机目录:容器目录) docker run -v /data:/app/data myapp
--mount 更灵活的挂载方式(推荐新项目使用) docker run --mount type=bind,source=/host,target=/container nginx
--env, -e 设置环境变量 docker run -e ENV=prod myapp
--env-file 从文件中加载多个环境变量 docker run --env-file .env myapp
--network 设置容器使用的网络模式 docker run --network host myapp
--restart 设置容器的自动重启策略 docker run --restart=always myapp
--privileged 给予容器更多的权限(如访问 host 设备) docker run --privileged myapp
--entrypoint 覆盖镜像默认的 ENTRYPOINT docker run --entrypoint /bin/bash myapp
-u, --user 指定容器内运行的用户(格式:UID 或 UID:GID) docker run --user 1000:1000 myapp
-c, --cpu-shares 设置 CPU 权重(相对值) docker run --cpu-shares=512 myapp
-m, --memory 限制容器最大内存(如 512m, 1g docker run --memory=512m myapp
-h, --hostname 设置容器主机名 docker run -h myhost myapp
--link(更推荐使用 --network) 创建链接到其他容器 docker run --link myapp:app myapp2
--cpus 限制容器使用的CPU核数 docker run --cpus="1.5"
  • -p, --publish 端口映射

1
docker run -p [主机IP:]主机端口:容器端口[/协议]
示例 含义说明
-p 8080:80 将主机的 8080 端口映射到容器的 80 端口(默认 TCP)
-p 127.0.0.1:8080:80 仅将主机本地 IP(127.0.0.1)的 8080 映射到容器的 80 端口(外部无法访问)
-p 8080:80/tcp 显式指定协议为 TCP(等同于不加 /tcp
-p 8080:80/udp 映射 UDP 协议端口(如 DNS 服务等)
-p 8080 宿主机随机端口映射到容器的8080端口
-p 3000-3006:4000-4006 范围映射,不能映射非对称范围(如 3000-3006:4000-4006),只能一一对应
多个 -p 可以多次使用 -p,映射多个端口。例如:-p 80:80 -p 443:443
  • -v, --volume 数据卷映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
docker run -v <本地路径>:<容器路径>[:权限]
# <本地路径> 主机上的路径(绝对路径,或命名卷),目录不存在会自动创建
# <容器路径> 容器内的路径,目录不存在会自动创建
# [:权限] 可选:ro(只读) 或 rw(读写,默认)

# 示例
# 挂载本地目录到容器
docker run -v /data:/app/data myapp

# 挂载为只读
docker run -v /data:/app/data:ro myapp

# 挂载多个数据卷
docker run -v /data1:/app/data1 -v /data2:/app/data2 myapp

# 使用命名卷
docker volume create mydata
docker run -v mydata:/app/data myapp
  • --mount 挂载卷

1
2
# --mount 是 Docker 推荐使用的 现代挂载方式,功能和 -v(或 --volume)类似,但语法更清晰、结构更规范,适用于卷(volume)、绑定挂载(bind)和临时挂载(tmpfs)。
docker run --mount type=<类型>,source=<主机路径或卷名>,target=<容器路径>[,readonly]

三种挂载类型对比

类型 (type) 用途 示例 source
volume 使用 Docker 管理的卷 卷名,如 mydata
bind 挂载宿主机的实际路径 绝对路径,如 /home/user/app/config
tmpfs 挂载内存中的临时文件系统 无需指定 source
1
2
3
4
5
6
7
8
9
10
# 使用命名卷挂载(推荐方式),这里 --target 指定容器内的挂载点,也可以替换为 --destination
docker run --mount type=volume,source=mydata,target=/app/data myapp

# 使用本地路径挂载(绑定挂载),source指定的本地路径必须存在
docker run --mount type=bind,source=/home/user/app/config,target=/app/config myapp
# 只读挂载,readonly 可以简写为 ro
docker run --mount type=bind,source=/home/user/app/config,target=/app/config,readonly myapp

# 使用内存中的临时文件系统挂载,数据不会持久化,只存储在容器运行时的内存中
docker run --mount type=tmpfs,target=/app/tmpfs myapp
  • --link 容器间链接

用于在容器之间建立连接,使一个容器可以通过另一个容器的名称访问其网络信息(如 IP、环境变量等)。
注意:--link 已被弃用,建议使用 --network 来实现容器间链接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docker run --link <目标容器名>:<别名> <其他参数> <镜像名>

## 示例
# 场景:一个 web 容器想要连接另一个运行中的 db 容器
# 先启动数据库容器
docker run -d --name db mysql
# 启动 web 容器并连接到 db 容器
docker run -it --rm --name web --link db:mydb ubuntu bash
# 在 web 容器中,现在你可以用 mydb 来访问 db 容器,但反过来 db 容器无法访问 web 容器
docker exec web ping mydb

## 改用 --network 实现
docker network create mynet
docker run -d --name db --network mynet mysql
docker run -it --rm --name web --network mynet ubuntu bash
docker exec web ping db
  • --network 网络模式类型

类型 含义 特点/适用场景 是否允许端口映射
bridge 默认网络类型(用户自定义或 Docker 默认桥接网络) 容器通过虚拟网桥连接,可相互通信;适用于单主机部署 ✅ 是
host 容器与宿主机共享网络栈 没有网络隔离,容器使用宿主机的 IP 和端口,性能高,适合对网络要求高的服务 ❌ 否
none 容器没有网络接口 完全隔离;适用于需要完全控制网络的场景或测试网络不可达性 ❌ 否
<user-defined> 用户自定义的网络名称,通过 docker network create 创建 支持容器名称互解析(DNS),适合多容器通信场景,如 Docker Compose ✅ 是
container:<name|id> 与另一个容器共享网络命名空间 两个容器共享 IP 和端口,适用于主-辅容器模式,如 sidecar 容器共享主容器网络 ❌ 否
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 使用默认 bridge 网络
docker run -p 8080:80 --network bridge --name my-nginx nginx

# 与宿主机共享网络,不能使用-p
docker run --network host nginx

# 不使用任何网络,不能使用-p
docker run --network none nginx

# 使用已创建的自定义网络,相同网络命名空间下的容器,可以通过容器 名称或ID 互相访问
docker network create nginx_net
docker run -p 8080:80 --network nginx_net nginx

# 与另一个容器共享网络命名空间,不能使用-p,并且此时新启动的容器占用的端口不能与要连接的容器端口一致,否则将启动失败
docker run --network container:my-nginx busybox
  • --restart 重启策略

策略 含义
no(默认) 容器退出后不会自动重启
always 无论退出状态码如何,容器总是自动重启
unless-stopped 容器总是自动重启,除非用户手动停止它
on-failure[:N] 仅在容器非 0 状态码退出时自动重启(可选设置最大重启次数 N)
1
2
3
4
5
6
7
8
9
10
11
# 容器非正常退出时自动重启
docker run --restart on-failure my-app

# 最多重启 5 次
docker run --restart on-failure:5 my-app

# 总是重启(即使你重启 Docker 服务后)
docker run --restart always my-app

# 除非手动停止,否则一直重启
docker run --restart unless-stopped my-app
  • --cpu-shares : 设置容器的 CPU 相对权重,即在 CPU 资源竞争时的相对优先级,默认值为 1024。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 容器1,权重 1024(默认)
docker run -d --name c1 --cpu-shares 1024 nginx

# 容器2,权重 512(优先级低)
docker run -d --name c2 --cpu-shares 512 nginx

## 说明:
# c1的权重1024,c2的权重512,不是绝对限制,而是分配比例
# 该权重表示容器在 CPU 竞争下,权重越高则优先级越高,会尽可能使用 CPU 资源。
# 如果这两个容器都运行在 CPU 忙碌的环境下(只有在 多容器共享 CPU 且竞争资源 的情况下才生效):
# c1 将获得大约 2/3 的 CPU 时间
# c2 将获得大约 1/3 的 CPU 时间
# 如果系统 CPU 空闲,所有容器都可以使用 100% 的 CPU。
  • docker run 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
# 启动一个nginx 容器
docker run -d -p 80:80 --name nginx nginx
# 替换nginx镜像默认的启动命令,nginx 镜像默认启动 nginx 服务,此命令会改为执行 nginx -v 显示版本号
docker run --name test_nginx --entrypoint "" nginx nginx -v

# 执行脚本或命令,这里添加 --rm 参数,表示运行结束后自动删除容器,这里是安装 ping 命令
docker run --rm ubuntu bash -c "apt update && apt install -y iputils-ping"
# 交互式执行 shell 命令,执行命令后会进入容器的shell
docker run --rm -it ubuntu /bin/bash
# 这样也可以,因为 ubuntu 的默认启动命令是 /bin/bash
docker run --rm -it ubuntu
# 转到后台运行
docker run --rm -itd ubuntu

docker stop : 停止容器,容器优雅退出

1
2
3
4
5
6
7
8
# 停止容器,通过容器名称
docker stop test_nginx
# 停止容器,通过容器ID
docker stop 5d7c0c5d5c0c
# 停止所有正在运行的容器
docker stop $(docker ps -q)
# 等待5秒后强制关闭
docker stop -t 5 test_nginx

docker kill : 强制停止容器

  • 当容器完全卡死、挂起、不响应 stop 命令时使用

1
2
3
docker kill test_nginx
docker kill 5d7c0c5d5c0c
docker kill $(docker ps -q)

docker restart : 重启容器

1
2
3
docker restart test_nginx
docker restart 5d7c0c5d5c0c
docker restart $(docker ps -q)

docker pause : 暂停容器

  • 暂停后宿主机将不再为容器分配CPU时间片,但内存依然有效,你可以理解为此时为容器保存了快照

1
2
3
docker pause test_nginx
docker pause 5d7c0c5d5c0c
docker pause $(docker ps -q)

docker unpause : 恢复容器

1
2
3
docker unpause test_nginx
docker unpause 5d7c0c5d5c0c
docker unpause $(docker ps -q)

docker ps : 查看容器列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 显示所有正在运行的容器
docker ps
# 显示所有容器
docker ps -a
# 显示所有正在运行的容器的ID
docker ps -q
# 不截断输出,此时 COMMAND 列会显示完整的命令
docker ps -notrunc
# 显示最近创建的5条容器
docker ps -n 5
# 过滤器,显示状态为exited的容器
docker ps -a --filter "status=exited"
# 指定模板,只显示 ID 和 Names
docker ps --format "{{.ID}}: {{.Names}}"

docker inspect : 查看容器信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查看容器信息
docker inspect <container_id>
# 获取容器名称
docker inspect --format='{{.Name}}' <container_id | container_name>
# 获取容器镜像
docker inspect --format='{{.Config.Image}}' <container_id | container_name>
# 获取容器环境变量
docker inspect --format='{{.Config.Env}}' <container_id | container_name>
# 获取容器状态,前面的 json 表示输出为 json 格式
docker inspect --format='{{json .State}}' <container_id | container_name>
# 获取容器内存限制
docker inspect --format='{{.HostConfig.Memory}}' <container_id | container_name>
# 获取容器label
docker inspect --format='{{json .Config.Labels}}' <container_id | container_name>
# 获取容器的网络信息
docker inspect --format='{{json .NetworkSettings}}' <container_id | container_name>

docker logs : 获取容器日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 获取容器日志
docker logs <container_id | container_name>
# 获取容器实时日志
docker logs -f <container_id | container_name>
# 获取容器最新的 10 行日志
docker logs -n 10 <container_id | container_name>
# 获取容器的带时间戳的日志
docker logs -t <container_id | container_name>
# 获取容器的日志,从 1 小时前开始
docker logs --since 1h <container_id | container_name>
# 获取容器的日志,直到 1 小时前
docker logs --until 1h <container_id | container_name>
# 获取容器的详细日志
docker logs --details <container_id | container_name>
# 获取容器的日志,从 2 小时前开始,直到 1 小时前
docker logs --since 2h --until 1h <container_id | container_name>

docker exec : 在已经运行的容器中执行命令

1
2
3
4
# 在已经运行的容器中执行命令
docker exec <container_id | container_name> <command>
# 进入容器shell
docker exec -it <container_id | container_name> bash

docker rename : 重命名容器

1
docker rename <old_container_name> <new_container_name>

docker cp : 容器与宿主机间复制文件

1
2
3
4
5
6
# 宿主机 -> 容器
# docker cp <host_path> <container_id | container_name>:<container_path>
docker cp ./docker-command-container.md nginx:/tmp
# 容器 -> 宿主机
# docker cp <container_id | container_name>:<container_path> <host_path>
docker cp nginx:/tmp/docker-command-container.md ./

docker rm : 删除容器

1
2
3
4
# 删除指定容器
docker rm <container_id | container_name>
# 删除所有容器
docker rm $(docker ps -aq)

docker container prune : 删除所有停止的容器

1
docker container prune

docker update : 更新容器配置

1
2
3
4
# 更新指定容器的CPU核数和内存大小
docker update --cpus=2 --memory=2g <container_id | container_name>
# 更新指定容器自动重启
docker update --restart=always <container_id | container_name>
  • 并不是所有的配置都支持更新,update 命令只支持如下配置,基本上也就只能调一下cpu和内存,以及自动重启策略,所以制作容器时一定要做好规划。

参数名 说明 示例值
--blkio-weight 设置 Block IO 的相对权重,范围是 10 到 1000,设置为 0 表示禁用(默认值为 0) --blkio-weight=500
--cpu-period 设置 CPU CFS(完全公平调度器)的周期限制(单位:微秒) --cpu-period=100000
--cpu-quota 设置 CPU CFS 的配额限制(单位:微秒) --cpu-quota=50000
--cpu-rt-period 设置实时 CPU 的调度周期(单位:微秒) --cpu-rt-period=1000000
--cpu-rt-runtime 设置实时 CPU 的运行时间限制(单位:微秒) --cpu-rt-runtime=950000
-c, --cpu-shares 设置 CPU 共享权重,默认值为 1024 --cpu-shares=512
--cpus 限制容器使用的 CPU 数量(支持小数) --cpus=1.5
--cpuset-cpus 指定容器可以在哪些 CPU 上运行(如 0-3、0,1) --cpuset-cpus="0,1"
--cpuset-mems 指定容器可以使用哪些内存节点(如 0-3、0,1),适用于 NUMA 系统 --cpuset-mems="0"
-m, --memory 设置内存限制(例如 512m、2g) --memory=1g
--memory-reservation 设置内存软限制(低于 --memory 的值时,允许系统在压力较小时回收) --memory-reservation=512m
--memory-swap 设置 swap 限制(内存 + swap 总和),设为 -1 表示无限制 --memory-swap=2g
--pids-limit 设置容器的最大进程数量,设为 -1 表示无限制 --pids-limit=100
--restart 设置容器退出后的重启策略 --restart=always

docker stats : 显示容器的实时资源使用情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 显示所有容器的实时资源使用情况
docker stats
## 输出
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
15caf520e3a5 nginx 0.00% 10.22MiB / 7.752GiB 0.13% 6.38kB / 2.61kB 0B / 28.7kB 13
b680087420b8 dockge 0.01% 199.5MiB / 7.752GiB 2.51% 6.44kB / 1.48kB 94.8MB / 0B 24
861dd9c1475f remote-api 0.00% 4.188MiB / 7.752GiB 0.05% 2.77kB / 126B 3.31MB / 0B 1
### CONTAINER ID 与 NAME:容器 ID 与名称。
### CPU % 与 MEM %:容器使用的 CPU 和内存的百分比。
### MEM USAGE / LIMIT:容器正在使用的总内存,以及允许使用的内存总量。
### NET I/O:容器通过其网络接口发送和接收的数据量。
### BLOCK I/O:容器从主机上的块设备读取和写入的数据量。
### PIDs:容器创建的进程或线程数。

# 列出所有容器的资源使用情况,包括运行和停止的
docker stats -a

# 展示当前状态就直接退出了,不再实时更新。
docker stats --no-stream

# 指定输出模板,这里加不加 table 都可以
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 输出json格式
docker stats --no-stream --format json

# 指定容器
docker stats <container_id | container_name>

docker top : 查看正在运行的进程

1
2
# docker top <container_id | container_name> [ps options]
docker top nginx

docker port : 列出指定的容器的端口映射

1
2
3
# docker port <container_id | container_name>
$ docker port nginx
80/tcp -> 0.0.0.0:8081

docker diff : 列出容器运行时对文件系统的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# docker diff <container_id | container_name>
$ docker diff nginx
C /root
A /root/.bash_history
C /run
A /run/nginx.pid
C /tmp
A /tmp/demo.py
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
  • 前缀含义说明:

标志 含义 说明
A Added(新增) 文件或目录是容器运行后新增的
C Changed(修改) 文件或目录是已有的,但内容或元数据(如权限、时间戳等)被修改了
D Deleted(删除) 文件或目录是存在于原镜像中的,但在容器中被删除

docker commit : 从容器创建一个新的镜像

1
2
# docker commit <container_id | container_name> [image_name[:tag]]
docker commit nginx nginx:v1.0

docker export : 导出容器内容为 tar 文件

1
2
3
docker export nginx > nginx.tar
dcoker export -o nginx.tar nginx
docker export nginx | gzip > nginx.tar.gz
  • Docker Export / Save / Commit 命令对比与导入方式一览表

命令 操作对象 输出内容 是否包含历史层(镜像层) 是否保留元数据(标签、命令等) 典型用途 导入命令
docker export 容器 容器的文件系统(tar 归档) ❌ 否 ❌ 否 备份容器文件系统或迁移容器状态 docker import <tar> <image:tag>
docker save 镜像 镜像的完整内容(含所有层的 tar) ✅ 是 ✅ 是 分发或备份镜像 docker load < <tar>
docker commit 容器 创建一个新的镜像 ✅ 是(但只一层) ✅ 是 将当前容器状态打包成新镜像 不适用(直接生成镜像)