使用注意事项

11.1 安全注意事项

不要用 root 运行容器

# 危险:容器内 root 可以逃逸到宿主机
docker run -it --user root ubuntu bash
 
# 正确:使用非 root 用户
docker run -it --user 1000:1000 ubuntu bash
 
# Dockerfile 中设置
RUN useradd -m appuser
USER appuser

不要挂载 Docker Socket

# 极度危险:容器获得 Docker 完整控制权
docker run -v /var/run/docker.sock:/var/run/docker.sock docker
 
# 这等于给容器 root 权限,可以:
# - 创建特权容器
# - 访问宿主机文件系统
# - 完全控制 Docker daemon

不要使用 —privileged

# 危险:容器获得宿主机所有 capabilities
docker run --privileged ubuntu bash
 
# --privileged 会:
# - 禁用所有安全机制
# - 可以访问宿主机设备
# - 可以加载内核模块
 
# 替代方案:只添加必要的 capabilities
docker run --cap-add=NET_BIND_SERVICE nginx

镜像来源审查

# 只从官方或可信来源拉取镜像
docker pull nginx:alpine           # 官方镜像
docker pull myregistry/myapp:v1    # 检查来源
 
# 扫描镜像漏洞
docker scout cves nginx:alpine
trivy image nginx:alpine

敏感数据处理

# 不要在 Dockerfile 中硬编码密钥
ENV MYSQL_PASSWORD=secret123
 
# 使用环境变量或 secrets
docker run -e MYSQL_PASSWORD=$ecret docker run --secret db_pass
 
# 不要在镜像中存储私钥
COPY id_rsa /root/.ssh/
 
# 使用 BuildKit secret mount
RUN --mount=type=secret,id=ssh_key \
    cat /run/secrets/ssh_key

11.2 资源限制

内存限制

# 限制容器内存
docker run --memory=512m --name web nginx
# 超过 512MB 会被 OOM Kill
 
# 内存 + swap 限制
docker run --memory=512m --memory-swap=1g nginx
# swap 可以用 512MB
 
# 禁用 swap
docker run --memory=512m --memory-swap=512m nginx

CPU 限制

# 限制 CPU 核心数
docker run --cpus=1.5 nginx
# 最多使用 1.5 个核心
 
# CPU 份额(相对权重)
docker run --cpu-shares=512 nginx  # 默认 1024
docker run --cpu-shares=2048 nginx # 2 倍权重
 
# 绑定 CPU 核心
docker run --cpuset-cpus="0,1" nginx  # 只用核心 0 和 1

PID 限制

# 防止 fork bomb
docker run --pids-limit=100 nginx
# 最多 100 个进程

磁盘限制

# 限制容器可写层大小
docker run --storage-opt size=1G nginx

资源限制检查

# 查看容器资源使用
docker stats web

11.3 日志管理

日志驱动

// daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

查看日志

# 容器日志
docker logs web
docker logs -f web          # 跟踪
docker logs --tail 100 web  # 最后 100 行
docker logs --since 1h web  # 最近 1 小时
 
# 清理日志
docker truncate -s 0 $(docker inspect --format='{{.LogPath}}' web)

避免日志撑爆磁盘

# 定期清理
docker system prune -f
 
# 或配置日志轮转(见上文 daemon.json)

11.4 清理策略

# 查看 Docker 磁盘使用
docker system df
docker system df -v
 
# 清理已停止容器
docker container prune
 
# 清理悬空镜像
docker image prune
 
# 清理所有未使用资源
docker system prune -a
docker system prune -a --volumes  # 深度清理
 
# 定期执行(建议 cron)
docker system prune -af --volumes

11.5 权限问题

容器内文件权限

# 宿主机 UID 1000 = 容器内 UID 1000
# 如果容器内以 root 运行,创建的文件在宿主机也是 root
 
# 解决:统一 UID/GID
docker run --user $(id -u):$(id -g) -v $(pwd):/app alpine
 
# 或在 Dockerfile 中
RUN groupadd -g 1000 appgroup && useradd -u 1000 -g appgroup appuser
USER appuser

Docker Socket 权限

# Docker 组的用户可以免 sudo 使用 docker
sudo usermod -aG docker $USER
# 需要重新登录
 
# 检查权限
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker

11.6 内核兼容性

cgroups v1 vs v2

# 查看 cgroups 版本
stat -fc %T /sys/fs/cgroup/
# cgroup2fs = v2
# tmpfs = v1
 
# Docker 20.10+ 支持 cgroups v2
# 某些旧版功能可能不兼容

旧内核限制

# 内核 3.10 不支持某些功能:
# - overlay2 存储驱动(需要 4.0+)
# - 某些 seccomp 功能
# - 部分网络功能
 
# 检查内核版本
uname -r

Docker 版本兼容性

# 检查 Docker 版本
docker version
 
# 建议使用 Docker 20.10+ 或更新版本
# 老版本可能缺少重要安全修复

存储驱动兼容性

# 查看当前存储驱动
docker info | grep "Storage Driver"
 
# 常见存储驱动及内核要求:
# overlay2    -> 内核 4.0+
# devicemapper -> 内核 3.10+
# btrfs      -> 内核 3.9+
# zfs        -> 内核 2.6.37+

11.7 生产环境最佳实践

镜像管理

# 使用具体版本标签,避免 latest
docker pull nginx:1.25.3-alpine
 
# 使用多阶段构建减小镜像体积
docker build --target=builder -t myapp:builder .
docker build -t myapp:latest .

容器重启策略

# 容器退出后自动重启
docker run --restart=always nginx
 
# 只在非正常退出时重启
docker run --restart=unless-stopped nginx

数据持久化

# 使用命名卷而非绑定挂载
docker volume create mydata
docker run -v mydata:/data nginx
 
# 备份卷数据
docker run --rm -v mydata:/data -v /backup:/backup alpine \
  tar czf /backup/mydata.tar.gz -C /data .
 
# 恢复卷数据
docker run --rm -v mydata:/data -v /backup:/backup alpine \
  tar xzf /backup/mydata.tar.gz -C /data

11.8 常见问题排查

容器无法启动

# 查看容器日志
docker logs web
 
# 常见退出码:
# 0   -> 正常退出
# 1   -> 应用错误
# 137 -> OOM Kill
# 139 -> 段错误

网络不通

# 检查容器网络配置
docker inspect web | grep IPAddress
 
# 进入容器测试网络
docker exec -it web ping google.com

磁盘空间不足

# 查看磁盘使用
docker system df
 
# 清理未使用资源
docker system prune -a --volumes

容器内时间不对

# 查看容器时间
docker exec web date
 
# 同步宿主机时区
docker run -v /etc/localtime:/etc/localtime:ro nginx