容器管理

一、生命周期管理

docker run — 创建并启动容器(核心命令)

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

这是 Docker 最复杂、最重要的命令。下面按功能分组列出所有参数。

1. 基本配置

参数 说明 示例
--name 指定容器名称 --name myapp
-d / --detach 后台运行 -d
--restart 重启策略 --restart always
--rm 容器退出后自动删除 --rm
-t / --tty 分配伪终端 -t
-i / --interactive 保持 STDIN 打开 -i
--hostname 设置容器主机名 --hostname web-server
--domainname 设置域名 --domainname example.com

重启策略详解

策略 说明
no 默认,不重启
always 任何情况都重启(容器退出、Docker 重启)
on-failure[:max-retries] 仅异常退出(非 0 退出码)时重启
unless-stopped 除手动停止外都重启(推荐生产)
# 生产环境推荐
docker run -d --restart unless-stopped --name app myapp

# 最多重试 5 次
docker run -d --restart on-failure:5 --name app myapp

# 调试临时容器(退出自动删除)
docker run -it --rm --name debug ubuntu bash

2. 端口与网络

参数 说明 示例
-p / --publish 端口映射 -p 8080:80
-P / --publish-all 所有暴露端口随机映射 -P
--network 指定网络 --network my-net
--network-alias 网络别名 --network-alias web
--ip 指定 IP --ip 172.20.0.10
--hostname 容器主机名 --hostname app
--add-host 添加 host 映射 --add-host "db:192.168.1.10"
# 端口映射到宿主机 8080
docker run -d -p 8080:80 nginx

# 绑定到本地(不对外暴露)
docker run -d -p 127.0.0.1:8080:80 nginx

# 多端口映射
docker run -d -p 8080:80 -p 8443:443 nginx

# 使用自定义网络
docker run -d --network my-net --name app myapp

# 添加 host 解析(模拟域名)
docker run -d --add-host "api.local:192.168.1.100" myapp

3. 数据存储

参数 说明 示例
-v / --volume 挂载卷 -v mydata:/app/data
--mount 挂载(更明确语法) --mount type=bind,src=/host,dst=/container
--tmpfs 挂载内存文件系统 --tmpfs /tmp:size=64M
# 命名卷
docker run -d -v app-data:/app/data myapp

# 宿主机目录挂载(bind mount)
docker run -d -v /host/data:/app/data myapp

# 只读挂载
docker run -d -v /host/config:/app/config:ro myapp

# 使用 --mount(语法更清晰)
docker run -d --mount type=bind,source=/host/data,target=/app/data myapp

# 内存文件系统(临时缓存)
docker run -d --tmpfs /tmp:rw,size=100M,uid=1000 myapp

4. 环境变量

参数 说明 示例
-e / --env 设置环境变量 -e TZ=Asia/Shanghai
--env-file 从文件加载环境变量 --env-file .env
# 单个变量
docker run -d -e TZ=Asia/Shanghai -e APP_ENV=prod myapp

# 使用 env-file
docker run -d --env-file .env.production myapp

5. 资源限制

参数 说明 示例
--memory / -m 内存硬限制 --memory 2g
--memory-swap 内存+swap 总限制 --memory-swap 2g
--memory-reservation 内存软限制 --memory-reservation 1g
--cpus CPU 限制 --cpus 1.5
--cpu-shares CPU 权重(相对) --cpu-shares 512
--ulimit 系统资源限制 --ulimit nofile=65535:65535
# 限制 2GB 内存 + 1.5 核 CPU
docker run -d --memory 2g --memory-swap 2g --cpus 1.5 myapp

# 禁用 swap(memory-swap = memory)
docker run -d --memory 2g --memory-swap 2g myapp

# 文件句柄限制(高并发场景)
docker run -d --ulimit nofile=65535:65535 --ulimit nproc=65535:65535 myapp

6. 安全与权限

参数 说明 示例
--user / -u 指定运行用户 --user 1000:1000
--read-only 根文件系统只读 --read-only
--cap-add 添加 Linux 能力 --cap-add NET_BIND_SERVICE
--cap-drop 删除 Linux 能力 --cap-drop ALL
--privileged 特权模式(谨慎 --privileged(不推荐)
--security-opt 安全选项 --security-opt no-new-privileges
--security-opt seccomp seccomp 配置 --security-opt seccomp=default.json
# 非 root 用户运行
docker run -d --user 1000:1000 myapp

# 只读根文件系统 + 可写 tmpfs
docker run -d --read-only --tmpfs /tmp myapp

# 最小权限:删除所有能力,只添加绑定低端口
docker run -d --cap-drop ALL --cap-add NET_BIND_SERVICE myapp

# 禁止提权
docker run -d --security-opt no-new-privileges myapp

7. 健康检查

参数 说明 示例
--health-cmd 健康检查命令 --health-cmd "curl -f http://localhost/ \|\| exit 1"
--health-interval 检查间隔 --health-interval 30s
--health-timeout 检查超时 --health-timeout 5s
--health-retries 失败重试次数 --health-retries 3
--health-start-period 启动缓冲期 --health-start-period 60s
docker run -d \
  --health-cmd "curl -f http://localhost:8080/actuator/health || exit 1" \
  --health-interval 30s \
  --health-timeout 5s \
  --health-retries 3 \
  --health-start-period 60s \
  myapp

8. 其他常用参数

参数 说明 示例
--workdir / -w 工作目录 -w /app
--entrypoint 覆盖入口点 --entrypoint /bin/sh
--label 添加标签 --label version=1.0
--log-driver 日志驱动 --log-driver json-file
--log-opt 日志驱动参数 --log-opt max-size=50m
--sysctl 内核参数 --sysctl net.core.somaxconn=1024

docker start / stop / restart / kill — 容器控制

docker start [OPTIONS] CONTAINER [CONTAINER...]
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker restart [OPTIONS] CONTAINER [CONTAINER...]
docker kill [OPTIONS] CONTAINER [CONTAINER...]

参数

命令 参数 说明
start -a / --attach 附加到容器
stop -t / --time 等待时间(默认 10s)
restart -t / --time 等待时间(默认 10s)
kill -s / --signal 发送的信号(默认 SIGKILL)

使用场景

# 正常启动容器
docker start myapp

# 启动并查看输出
docker start -a myapp

# 优雅停止(SIGTERM,等待 10s)
docker stop myapp

# 指定等待时间(30s)
docker stop -t 30 myapp

# 强制停止(SIGKILL)
docker kill myapp

# 发送自定义信号
docker kill -s SIGHUP myapp   # 让 Nginx 重新加载配置

# 重启
docker restart myapp

docker pause / unpause — 暂停/恢复

docker pause CONTAINER [CONTAINER...]
docker unpause CONTAINER [CONTAINER...]

使用场景

# 暂停容器进程(冻结所有进程)
docker pause myapp

# 恢复
docker unpause myapp

tips:暂停会冻结容器内所有进程,不释放资源。用于调试或临时冻结,长时间暂停不推荐。


docker rm — 删除容器

docker rm [OPTIONS] CONTAINER [CONTAINER...]

参数

参数 说明
-f / --force 强制删除(运行中也可删除)
-v / --volumes 同时删除挂载的匿名卷
-l / --link 移除容器间链接

使用场景

# 删除已停止的容器
docker rm myapp

# 强制删除运行中的容器
docker rm -f myapp

# 删除容器及匿名卷
docker rm -v myapp

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

二、查看与检查

docker ps — 查看容器列表

docker ps [OPTIONS]

常用参数

参数 说明 示例
-a / --all 所有容器(含已停止) docker ps -a
-q / --quiet 只显示容器 ID docker ps -q
-s / --size 显示容器大小 docker ps -s
-f / --filter 按条件过滤 docker ps -f status=exited
--format 自定义输出 docker ps --format "table {{.Names}}\t{{.Status}}"
-n 最近创建的 N 个容器 docker ps -n 5
--no-trunc 不截断输出 docker ps --no-trunc

常用过滤器

过滤器 说明 示例
status=running 运行中 docker ps -f status=running
status=exited 已停止 docker ps -f status=exited
name=xxx 容器名匹配 docker ps -f name=web
label=key=value 标签匹配 docker ps -f label=env=prod
since=container 在某容器之后启动 docker ps -f since=web

使用场景

# 查看所有容器
docker ps -a

# 只看容器 ID(批量操作)
docker ps -q
docker ps -a -q

# 查看停止的容器
docker ps -f status=exited

# 自定义显示格式
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"

# 查看容器大小
docker ps -s

# 查看最近启动的 5 个容器
docker ps -a -n 5

docker inspect — 查看容器详细信息

docker inspect [OPTIONS] CONTAINER [CONTAINER...]

常用查询(使用 --format):

# 查看容器 IP
docker inspect myapp --format='{{.NetworkSettings.IPAddress}}'

# 查看容器所有网络信息
docker inspect myapp --format='{{.NetworkSettings.Networks}}'

# 查看容器挂载
docker inspect myapp --format='{{.Mounts}}'

# 查看容器运行状态
docker inspect myapp --format='{{.State.Status}}'

# 查看容器退出码
docker inspect myapp --format='{{.State.ExitCode}}'

# 查看容器 PID(宿主机视角)
docker inspect myapp --format='{{.State.Pid}}'

# 查看容器启动命令
docker inspect myapp --format='{{.Config.Cmd}}'

# 查看容器环境变量
docker inspect myapp --format='{{.Config.Env}}'

# 查看容器运行用户
docker inspect myapp --format='{{.Config.User}}'

# 查看容器资源限制
docker inspect myapp --format='{{.HostConfig.Memory}} {{.HostConfig.NanoCpus}}'

# 查看容器日志驱动
docker inspect myapp --format='{{.HostConfig.LogConfig.Type}}'

docker logs — 查看容器日志

docker logs [OPTIONS] CONTAINER

参数

参数 说明 示例
-f / --follow 实时跟踪 docker logs -f myapp
--tail 显示最后 N 行 docker logs --tail 100 myapp
--since 从指定时间起 docker logs --since 1h myapp
--until 到指定时间止 docker logs --until 30m myapp
-t / --timestamps 带时间戳 docker logs -t myapp
--details 显示额外详情 docker logs --details myapp

使用场景

# 实时跟踪日志
docker logs -f myapp

# 查看最近 100 行
docker logs --tail 100 myapp

# 查看最近 30 分钟的日志
docker logs --since 30m myapp

# 查看特定时间段
docker logs --since "2024-01-01T10:00:00" --until "2024-01-01T12:00:00" myapp

# 带时间戳
docker logs -t myapp

# 只看错误日志
docker logs myapp 2>&1 | grep ERROR

docker stats — 实时资源监控

docker stats [OPTIONS] [CONTAINER...]

参数

参数 说明
--no-stream 单次输出(不刷新)
--no-trunc 不截断
--format 自定义输出

使用场景

# 实时监控所有容器
docker stats

# 监控指定容器
docker stats myapp mysql

# 单次输出(脚本采集)
docker stats --no-stream

# 自定义格式
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}"

# 查看容器进程数
docker stats --no-stream --format "table {{.Name}}\t{{.PIDs}}"

详细用法参见《docker stats监控.md》。


docker top — 查看容器内进程

docker top CONTAINER [ps OPTIONS]

使用场景

# 查看容器内进程列表
docker top myapp

# 查看进程详细信息
docker top myapp aux

# 查看特定进程
docker top myapp | grep java

docker port — 查看端口映射

docker port CONTAINER [PRIVATE_PORT[/PROTO]]

使用场景

# 查看所有端口映射
docker port myapp

# 查看特定端口
docker port myapp 80
docker port myapp 80/tcp

docker diff — 查看容器文件变化

docker diff CONTAINER

输出说明

前缀 含义
A 新增文件
C 修改文件
D 删除文件

使用场景

# 查看容器相对于镜像的文件变化
docker diff myapp

# 查看具体文件的修改
docker diff myapp | grep app

三、进入与执行

docker exec — 在容器内执行命令

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

参数

参数 说明
-d / --detach 后台执行
-i / --interactive 保持 STDIN 打开
-t / --tty 分配伪终端
-u / --user 指定用户执行
-e / --env 设置环境变量
-w / --workdir 工作目录

使用场景

# 进入容器交互式 shell
docker exec -it myapp /bin/bash
docker exec -it myapp /bin/sh   # Alpine

# 执行单条命令
docker exec myapp ls -la /app

# 以其他用户执行
docker exec -u root myapp chown -R appuser /app/data

# 在工作目录执行
docker exec -w /app myapp python manage.py migrate

# 后台执行
docker exec -d myapp /app/backup.sh

实战技巧:查看容器内的用户和用户组

# 查看容器内当前用户
docker exec myapp whoami

# 查看容器内用户 ID
docker exec myapp id
docker exec myapp id -u    # 只显示 uid
docker exec myapp id -g    # 只显示 gid

# 查看容器内所有用户
docker exec myapp cat /etc/passwd

# 查看容器内用户组
docker exec myapp cat /etc/group

# 查看容器内某个用户信息
docker exec myapp id appuser

# 查看容器内进程的运行用户
docker exec myapp ps aux

实战技巧:排查 Bind Mount 权限问题

# 1. 查看容器内运行用户
docker exec myapp id
# 输出:uid=1000(appuser) gid=1000(appgroup)

# 2. 查看宿主机挂载目录的属主
ls -la /host/data
# 输出:drwxr-xr-x 2 root root 4096...

# 3. 如果用户/组不匹配,容器内无法写入
# 解决方案 A:修改宿主机目录属主
sudo chown -R 1000:1000 /host/data

# 解决方案 B:容器以宿主机用户运行
docker run -d --user $(id -u):$(id -g) -v /host/data:/app/data myapp

# 解决方案 C:在容器内调整权限(如果有 root)
docker exec -it -u root myapp chown -R appuser:appgroup /app/data

# 解决方案 D:容器内创建用户时使用相同的 uid/gid
RUN groupadd -g 1000 appgroup && useradd -u 1000 -g appgroup appuser

# 5. 验证容器内写入权限
docker exec myapp touch /app/data/test.txt

Bind Mount 权限问题完整排查流程

# Step 1: 检查宿主机目录属主
stat -c "%u:%g" /host/data

# Step 2: 检查容器运行用户
docker exec myapp id

# Step 3: 检查容器内挂载目录的权限
docker exec myapp ls -la /app/data

# Step 4: 如果容器用户没有写权限
# 方案 1:宿主机目录改为容器用户 uid
sudo chown -R $(docker exec myapp id -u):$(docker exec myapp id -g) /host/data

# 方案 2:容器使用宿主机用户 uid
docker run -d --user $(id -u):$(id -g) -v /host/data:/app/data myapp

# 方案 3:Dockerfile 中创建与宿主机 uid 一致的用户
ARG UID=1000
RUN adduser -u $UID appuser
USER appuser

docker cp — 复制文件

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH

参数

参数 说明
-a / --archive 保留文件属性(权限、时间戳)
-L / --follow-link 跟随符号链接

使用场景

# 从容器复制文件到宿主机
docker cp myapp:/app/logs/app.log ./app.log

# 从宿主机复制文件到容器
docker cp ./config.yml myapp:/app/config.yml

# 复制目录
docker cp myapp:/app/logs ./logs/

# 保留文件权限
docker cp -a myapp:/app/config ./config/

docker attach — 附加到容器主进程

docker attach [OPTIONS] CONTAINER

使用场景

# 附加到容器查看输出
docker attach myapp

# 退出(不停止容器)
# Ctrl + P + Q

attach 会连接到容器的 STDIN/STDOUT/STDERR。如果容器没有交互式进程,可能无法正常使用。


四、更新与维护

docker rename — 重命名容器

docker rename OLD_NAME NEW_NAME

使用场景

docker rename myapp-old myapp-new

docker update — 动态更新容器配置

docker update [OPTIONS] CONTAINER [CONTAINER...]

可更新的参数

参数 说明
--cpus CPU 限制
--memory 内存限制
--memory-swap 内存+swap 限制
--restart 重启策略

使用场景

# 调整内存限制
docker update --memory 2g --memory-swap 2g myapp

# 调整 CPU 限制
docker update --cpus 2 myapp

# 修改重启策略
docker update --restart unless-stopped myapp

docker wait — 等待容器退出

docker wait CONTAINER [CONTAINER...]

使用场景

# 等待容器退出并返回退出码
docker wait myapp

五、实用技巧与场景

技巧 1:进入容器调试

# 快速进入容器
docker exec -it $(docker ps -q -f name=myapp) bash

# 查看容器内环境变量
docker exec myapp env

# 查看容器内网络
docker exec myapp ip addr show
docker exec myapp netstat -tlnp

# 查看容器内 DNS
docker exec myapp cat /etc/resolv.conf

# 测试容器内网络连通性
docker exec myapp ping 8.8.8.8
docker exec myapp curl http://localhost:8080/health

技巧 2:批量操作

# 停止所有运行中的容器
docker stop $(docker ps -q)

# 删除所有停止的容器
docker rm $(docker ps -a -q -f status=exited)

# 重启所有容器
docker restart $(docker ps -q)

# 批量查看容器 IP
docker ps -q | xargs -I {} docker inspect --format='{{.Name}} {{.NetworkSettings.IPAddress}}' {}

技巧 3:临时调试容器

# 启动一个临时容器(退出自动删除)
docker run -it --rm --name debug ubuntu bash

# 在容器内执行调试命令
docker run -it --rm alpine sh -c "ping google.com -c 4"

# 进入已有容器的 shell(无 bash 时用 sh)
docker exec -it myapp /bin/sh

技巧 4:容器状态监控

# 检查容器是否运行
docker ps -q -f status=running -f name=myapp | grep -q . && echo "running" || echo "stopped"

# 监控容器健康状态
docker inspect myapp --format='{{.State.Health.Status}}'

# 等待容器健康(脚本)
while [ "$(docker inspect --format='{{.State.Health.Status}}' myapp)" != "healthy" ]; do
    echo "Waiting for container to become healthy..."
    sleep 5
done

技巧 5:查看容器日志定位问题

# 查看容器启动错误
docker logs myapp

# 查看容器退出原因
docker inspect myapp --format='{{.State.Error}}'

# 查看容器退出码
docker inspect myapp --format='{{.State.ExitCode}}'

六、常见问题汇总

Q1:容器启动后立刻退出(Exited 0/1/137/143)

退出码 含义 排查方向
0 正常退出 CMD 执行完就结束了
1 程序错误 docker logs 查看错误
137 SIGKILL 内存超限被 kill 或手动 kill
143 SIGTERM 正常终止信号

解决方案

# 查看退出原因
docker logs myapp
docker inspect myapp --format='{{.State.Error}}'

# 前台模式启动(不退出)
docker run -it myapp /bin/bash

# 调试:覆盖 CMD 进入 shell
docker run -it --entrypoint /bin/sh myapp

Q2:Bind Mount 后容器内无写入权限

原因:容器运行用户(如 appuser)与宿主机目录属主不一致。

解决方案(见前面"实战技巧"章节):

  1. 修改宿主机目录属主为容器用户 uid
  2. 容器以宿主机用户 uid 运行(--user $(id -u):$(id -g)
  3. Dockerfile 中创建与宿主机 uid 一致的用户
  4. 容器内用 root 调整权限(chown

Q3:docker exec 提示 "OCI runtime exec failed"

原因:容器内没有指定的命令(如 /bin/bash)。

解决方案

# 尝试 sh
docker exec -it myapp /bin/sh

# 或使用容器存在的 shell
docker exec -it myapp /bin/ash

# 直接执行命令
docker exec -it myapp ls -la

Q4:docker logs 显示日志但容器已停止

# 使用 -a 查看所有容器的日志
docker logs -a myapp

Q5:容器内时间不对

# 挂载宿主机时区
docker run -d -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Shanghai myapp

Q6:容器内 DNS 解析失败

# 查看容器 DNS 配置
docker exec myapp cat /etc/resolv.conf

# 运行容器时指定 DNS
docker run -d --dns 223.5.5.5 --dns 223.6.6.6 myapp

七、命令速查表

操作 命令
创建并启动容器 docker run -d --name <name> <image>
启动容器 docker start <container>
停止容器 docker stop <container>
强制停止 docker kill <container>
重启容器 docker restart <container>
删除容器 docker rm <container>
列出运行中容器 docker ps
列出所有容器 docker ps -a
查看容器详情 docker inspect <container>
查看日志 docker logs -f <container>
实时监控 docker stats <container>
查看进程 docker top <container>
进入容器 docker exec -it <container> /bin/bash
查看容器内用户 docker exec <container> id
复制文件(宿主机←容器) docker cp <container>:/path ./
复制文件(宿主机→容器) docker cp ./file <container>:/path
更新资源限制 docker update --memory 1g <container>
重命名 docker rename <old> <new>
清理停止的容器 docker container prune