本页目录

Docker 操作手册

Docker 是 Linux 容器运行时。核心概念: image (只读模板), container (镜像的运行实例), volume (持久化存储), network (容器间通信), compose (多容器编排)。

容器

# 列出容器
docker ps                               # 正在运行的
docker ps -a                            # 全部 (含已停止的)
docker ps -a --format '{{.ID}} {{.Names}} {{.Status}}'  # 自定义列
docker ps -q                            # 只输出 ID (给脚本用)

# 运行
docker run -d --name myapp \
  -p 8080:80 \                          # host:8080 → container:80
  -v /data:/app/data \                  # host 目录 → container 目录
  -v app_data:/app/storage \            # named volume → container 目录
  -e DATABASE_URL=postgres://... \      # 环境变量
  --restart unless-stopped \            # 自动重启策略
  --network mynet \                     # 加入指定网络
  --memory 512m \                       # 内存限制
  image:tag

# 重启策略:
#   no:              不自动重启 (默认)
#   on-failure[:N]:  退出码非 0 时重启 (可选: 最多 N 次)
#   unless-stopped:   除非手动 stop, 否则总是重启 (dockerd 重启后也生效)
#   always:           任何情况下都重启

# 生命周期
docker stop myapp                       # SIGTERM → 等 10s → SIGKILL
docker stop -t 30 myapp                 # 等 30s
docker kill myapp                       # 直接 SIGKILL
docker restart myapp
docker rm myapp                         # 删除已停止的容器
docker rm -f myapp                      # 强制删除 (即使正在运行)
docker container prune                  # 删除所有已停止的容器
docker container prune --filter "until=24h"  # 只删 24h 前的

# 调试
docker logs myapp --tail 100 -f         # 日志 (stdout/stderr)
docker logs myapp --since 5m            # 最近 5 分钟
docker inspect myapp | jq '.[0].State'  # 完整状态 (PID, ExitCode, Mounts, ...)
docker inspect myapp | jq '.[0].NetworkSettings.IPAddress'
docker exec -it myapp sh                # 进入容器 shell
docker exec myapp cat /etc/resolv.conf  # 单条命令
docker top myapp                        # 容器内进程 (host 视角)
docker stats --no-stream                # CPU/Mem 快照
docker cp myapp:/app/config.yml ./      # 从容器复制文件出来

# 提交当前容器状态为新镜像 (调试用, 不是标准部署方式)
docker commit myapp myapp:debug

镜像

docker images                            # 本地镜像
docker images --format '{{.Repository}}:{{.Tag}} {{.Size}}'
docker pull alpine:3.20
docker tag alpine:3.20 myrepo/alpine:latest

docker rmi alpine:3.20                   # 删除 (必须没有任何容器引用)
docker image prune                       # 删除 dangling (<none> tag)
docker image prune -a                    # 删除所有未使用的
docker image prune -a --filter "until=7d"  # 保留最近 7 天的

# 跨机器传输 (不经过 registry)
docker save alpine:3.20 -o alpine.tar    # 导出为 tar
docker load -i alpine.tar                # 导入
# 适用: 墙内机器无法从 Docker Hub 拉取时, 在能拉的机器上 save → scp → load

# 查看镜像层
docker history alpine:3.20
docker image inspect alpine:3.20 | jq '.[0].RootFS.Layers'

Docker Compose

docker compose up -d                     # 启动 (后台)
docker compose up -d --build            # 重新 build 再启动
docker compose down                      # 停止并删除容器/网络
docker compose down -v                   # 同时删除 volumes (数据丢失!)
docker compose restart                   # 重启所有容器
docker compose restart nginx             # 重启单个服务
docker compose logs -f --tail=50
docker compose ps
docker compose exec app sh              # 进入服务容器
docker compose pull                      # 拉取最新镜像

网络

docker network ls
docker network inspect bridge            # 默认 bridge 网络

# 自定义 bridge 网络 (推荐: 容器间用容器名互相访问)
docker network create --driver bridge mynet
# → 内置 DNS: 容器名自动解析为 IP
# 默认 bridge 没有这个功能, 只能用 IP 互访

docker network connect mynet myapp       # 运行时加入网络
docker network disconnect mynet myapp

docker volume ls
docker volume inspect app_data           # Mountpoint = host 实际路径
docker volume prune                      # 删除未使用的 (数据丢失!)

清理

# 一键清理所有未使用资源 (谨慎!)
docker system prune -a --volumes
# -a: 含未使用的镜像
# --volumes: 含未使用的卷

# 查看磁盘占用
docker system df
docker system df -v                      # 每个对象的大小

故障排查

# 容器不断重启
docker logs myapp --tail=50              # 看退出前日志
docker inspect myapp | jq '.[0].State'    # ExitCode + Error

# 容器内 DNS 不通
docker exec myapp cat /etc/resolv.conf
# → 检查 dockerd 启动参数 --dns
# → 检查 host /etc/docker/daemon.json: { "dns": ["8.8.8.8"] }

# 端口冲突
ss -tlnp | grep <port>

# docker.sock 权限
sudo usermod -aG docker $USER           # 免 sudo 用 docker (需重新登录)