容器管理
一、生命周期管理
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)与宿主机目录属主不一致。
解决方案(见前面"实战技巧"章节):
- 修改宿主机目录属主为容器用户 uid
- 容器以宿主机用户 uid 运行(
--user $(id -u):$(id -g)) - Dockerfile 中创建与宿主机 uid 一致的用户
- 容器内用 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 |