27.1 镜像问题
27.1.1 镜像拉取失败
问题1: 网络超时
bash
# 错误信息
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout
# 解决方案1: 配置镜像加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
EOF
sudo systemctl restart docker
# 解决方案2: 使用HTTP代理
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS_PROXY=http://proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
问题2: 磁盘空间不足
bash
# 错误信息
no space left on device
# 检查磁盘使用
docker system df
df -h /var/lib/docker
# 清理无用资源
docker system prune -a --volumes # 清理所有未使用资源
docker image prune -a # 清理未使用镜像
docker volume prune # 清理未使用卷
# 修改Docker数据目录
sudo systemctl stop docker
sudo mv /var/lib/docker /data/docker
sudo ln -s /data/docker /var/lib/docker
sudo systemctl start docker
问题3: 镜像校验失败
bash
# 错误信息
failed to verify certificate: x509: certificate signed by unknown authority
# 解决方案: 添加不安全的仓库
sudo tee -a /etc/docker/daemon.json <<EOF
{
"insecure-registries": ["registry.internal.com:5000"]
}
EOF
sudo systemctl restart docker
27.1.2 镜像构建问题
问题1: 构建缓存导致旧依赖
bash
# 不使用缓存重新构建
docker build --no-cache -t myapp:latest .
# 仅从特定层开始重建
docker build --cache-from myapp:base -t myapp:latest .
问题2: ADD/COPY权限问题
dockerfile
# 错误写法: 文件权限为root
FROM alpine
COPY app.py /app/
USER appuser # 切换用户后无法访问
# 正确写法: 明确设置权限
FROM alpine
RUN adduser -D appuser
COPY --chown=appuser:appuser app.py /app/
USER appuser
问题3: 多阶段构建文件缺失
dockerfile
# 错误: 忘记复制必要文件
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
FROM alpine
COPY --from=builder /app/myapp /myapp # 缺少依赖库
# 正确: 使用静态编译或复制依赖
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o myapp # 静态编译
FROM alpine
COPY --from=builder /app/myapp /myapp
27.2 容器问题
27.2.1 容器启动失败
问题1: 端口已被占用
bash
# 错误信息
Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use
# 查找占用端口的进程
sudo lsof -i :80
sudo netstat -tulnp | grep :80
# 解决方案1: 停止占用进程
sudo kill <PID>
# 解决方案2: 使用其他端口
docker run -d -p 8080:80 nginx
问题2: 容器立即退出
bash
# 查看容器退出状态
docker ps -a
docker inspect <container> | grep -A 5 State
# 查看退出日志
docker logs <container>
# 常见退出码含义
# 0: 正常退出
# 1: 应用错误
# 125: Docker守护进程错误
# 126: 命令无法执行
# 127: 命令未找到
# 137: SIGKILL (OOM或手动kill -9)
# 143: SIGTERM (docker stop)
# 调试: 覆盖ENTRYPOINT
docker run -it --entrypoint /bin/sh myapp
问题3: 健康检查失败
bash
# 查看健康检查状态
docker inspect <container> | grep -A 20 Health
# 手动执行健康检查命令
docker exec <container> curl -f http://localhost/ || exit 1
# 调整健康检查参数
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s # 增加超时
retries: 5 # 增加重试次数
start_period: 60s # 增加启动等待时间
27.2.2 容器运行问题
问题1: 容器内存溢出
bash
# 错误信息
container killed by OOM killer
# 查看OOM状态
docker inspect <container> | grep OOMKilled
# 解决方案1: 增加内存限制
docker run -d -m 1g --memory-swap=1g myapp
# 解决方案2: 优化应用内存使用
# Java应用
docker run -d -m 1g -e JAVA_OPTS="-Xmx768m -Xms512m" myapp
# Node.js应用
docker run -d -m 512m node --max-old-space-size=400 app.js
问题2: 容器无法访问外网
bash
# 检查DNS配置
docker exec <container> cat /etc/resolv.conf
# 检查网络连接
docker exec <container> ping 8.8.8.8
docker exec <container> ping google.com
# 解决方案1: 指定DNS服务器
docker run -d --dns 8.8.8.8 --dns 8.8.4.4 nginx
# 解决方案2: 修改Docker默认DNS
sudo tee /etc/docker/daemon.json <<EOF
{
"dns": ["8.8.8.8", "8.8.4.4"]
}
EOF
sudo systemctl restart docker
27.3 网络问题
27.3.1 容器间通信失败
问题1: 容器无法互相访问
bash
# 检查容器网络
docker network inspect bridge
# 确保容器在同一网络
docker network create mynet
docker run -d --name app1 --network mynet nginx
docker run -d --name app2 --network mynet alpine
# 测试连通性
docker exec app2 ping app1
docker exec app2 wget -O- http://app1
# 检查防火墙
sudo iptables -L DOCKER-USER
问题2: 自定义网络DNS解析失败
bash
# 使用网络别名
docker run -d --name db --network mynet --network-alias database postgres
# 应用通过别名访问
docker run -d --name app --network mynet \
-e DB_HOST=database \
myapp
27.3.2 端口映射问题
问题1: 端口映射不生效
bash
# 检查端口映射
docker ps
docker port <container>
# 检查iptables规则
sudo iptables -t nat -L -n | grep <port>
# 检查容器内服务是否监听
docker exec <container> netstat -tulnp
# 确保服务绑定到0.0.0.0而非127.0.0.1
# 错误: 只监听localhost
nginx -g 'daemon off; listen 127.0.0.1:80;'
# 正确: 监听所有接口
nginx -g 'daemon off; listen 0.0.0.0:80;'
问题2: 无法访问宿主机服务
bash
# 从容器访问宿主机
# Linux: 使用host.docker.internal (需要添加)
docker run --add-host=host.docker.internal:host-gateway myapp
# 或使用宿主机IP
HOST_IP=$(ip route | grep docker0 | awk '{print $9}')
docker run -e DB_HOST=$HOST_IP myapp
# 或使用host网络模式
docker run --network host myapp
27.4 权限问题
27.4.1 文件权限问题
问题1: 挂载目录无权限
bash
# 错误: Permission denied
docker run -v /data:/data -u 1000:1000 alpine touch /data/test
# 解决方案1: 修改宿主机目录权限
sudo chown -R 1000:1000 /data
sudo chmod -R 755 /data
# 解决方案2: 使用root用户(不推荐)
docker run -v /data:/data alpine touch /data/test
# 解决方案3: 在容器内切换用户
docker run -v /data:/data alpine sh -c "
adduser -D -u 1000 appuser
chown appuser:appuser /data
su appuser -c 'touch /data/test'
"
问题2: Volume权限问题
bash
# 创建volume时设置权限
docker volume create mydata
# 使用初始化容器设置权限
docker run --rm -v mydata:/data alpine sh -c "
chown -R 1000:1000 /data
chmod -R 755 /data
"
# 应用容器使用
docker run -v mydata:/data -u 1000:1000 myapp
27.4.2 Docker权限问题
问题1: 普通用户无法执行docker命令
bash
# 错误信息
permission denied while trying to connect to the Docker daemon socket
# 解决方案: 添加用户到docker组
sudo usermod -aG docker $USER
newgrp docker # 或重新登录
# 验证
docker ps
问题2: GPU设备权限
bash
# 错误: 无法访问GPU设备
# 解决方案: 添加用户到video组
sudo usermod -aG video,render $USER
# 检查设备权限
ls -l /dev/kfd /dev/dri
# 容器运行时添加组
docker run --device=/dev/kfd --device=/dev/dri \
--group-add video --group-add render \
rocm/pytorch:latest
27.5 存储问题
27.5.1 磁盘空间管理
问题1: Docker占用大量空间
bash
# 检查Docker磁盘使用
docker system df -v
# 清理构建缓存
docker builder prune -a
# 清理未使用的镜像
docker image prune -a
# 清理停止的容器
docker container prune
# 清理未使用的卷
docker volume prune
# 一键清理(危险!)
docker system prune -a --volumes
问题2: 日志文件过大
bash
# 查找大日志文件
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail -n 10
# 清理特定容器日志
sudo truncate -s 0 /var/lib/docker/containers/<container-id>/*-json.log
# 配置日志轮转
sudo tee /etc/docker/daemon.json <<EOF
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
sudo systemctl restart docker
27.5.2 数据卷问题
问题1: 数据卷丢失
bash
# 列出所有卷(包括悬空)
docker volume ls -f dangling=true
# 备份卷数据
docker run --rm -v mydata:/data -v $(pwd):/backup alpine \
tar czf /backup/mydata-backup.tar.gz /data
# 恢复卷数据
docker volume create mydata-restored
docker run --rm -v mydata-restored:/data -v $(pwd):/backup alpine \
tar xzf /backup/mydata-backup.tar.gz -C /
27.6 性能问题
27.6.1 容器性能慢
问题1: I/O性能差
bash
# 使用volume代替bind mount
# 慢: bind mount
docker run -v $(pwd)/data:/data myapp
# 快: named volume
docker volume create appdata
docker run -v appdata:/data myapp
# Mac/Windows: 使用缓存模式
docker run -v $(pwd)/data:/data:cached myapp
问题2: 网络性能差
bash
# 使用host网络(牺牲隔离性)
docker run --network host myapp
# 调整MTU
docker network create --opt com.docker.network.driver.mtu=9000 mynet
27.6.2 资源限制问题
问题1: CPU限流
bash
# 检查CPU限流
docker stats <container>
# 查看限流次数
CONTAINER_ID=$(docker inspect -f '{{.Id}}' <container>)
cat /sys/fs/cgroup/cpu/docker/$CONTAINER_ID/cpu.stat | grep throttled
# 增加CPU配额
docker update --cpus=2.0 <container>
27.7 ROCm相关问题
27.7.1 GPU访问问题
问题1: 容器内看不到GPU
bash
# 检查设备映射
docker inspect <container> | grep -A 10 Devices
# 正确映射GPU设备
docker run -it --rm \
--device=/dev/kfd \
--device=/dev/dri \
--group-add video \
rocm/pytorch rocminfo
# 检查宿主机GPU
rocminfo | grep "Name:"
rocm-smi
问题2: ROCm版本不匹配
bash
# 检查版本兼容性
# 宿主机ROCm版本
cat /opt/rocm/.info/version
# 容器内ROCm版本
docker run --rm rocm/pytorch:latest cat /opt/rocm/.info/version
# 使用匹配的镜像版本
docker run --device=/dev/kfd --device=/dev/dri \
rocm/pytorch:rocm6.0-py3.10 python3
27.8 故障排查工具
27.8.1 综合诊断脚本
bash
#!/bin/bash
# docker-doctor.sh - Docker健康检查
echo "=== Docker版本信息 ==="
docker version
echo -e "\n=== Docker守护进程状态 ==="
sudo systemctl status docker
echo -e "\n=== 磁盘使用情况 ==="
docker system df
df -h /var/lib/docker
echo -e "\n=== 运行中的容器 ==="
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo -e "\n=== 容器资源使用 ==="
docker stats --no-stream
echo -e "\n=== 网络列表 ==="
docker network ls
echo -e "\n=== 数据卷使用 ==="
docker volume ls
docker system df -v | grep -A 5 "Local Volumes"
echo -e "\n=== 最近的容器日志错误 ==="
for container in $(docker ps -q); do
name=$(docker inspect -f '{{.Name}}' $container | sed 's/\///')
echo "[$name]"
docker logs --tail 10 $container 2>&1 | grep -i error || echo "无错误"
done
echo -e "\n=== Docker配置 ==="
cat /etc/docker/daemon.json 2>/dev/null || echo "无配置文件"
echo -e "\n=== 悬空资源 ==="
echo "悬空镜像: $(docker images -f dangling=true -q | wc -l)"
echo "悬空卷: $(docker volume ls -f dangling=true -q | wc -l)"
27.8.2 快速修复脚本
bash
#!/bin/bash
# docker-fix.sh - 常见问题快速修复
fix_permissions() {
echo "修复Docker权限..."
sudo usermod -aG docker $USER
echo "请重新登录生效"
}
fix_disk_space() {
echo "清理Docker磁盘空间..."
docker system prune -a -f
docker volume prune -f
echo "完成清理"
}
fix_network() {
echo "重置Docker网络..."
docker network prune -f
sudo systemctl restart docker
echo "网络已重置"
}
fix_dns() {
echo "修复DNS配置..."
sudo tee /etc/docker/daemon.json <<EOF
{
"dns": ["8.8.8.8", "8.8.4.4"]
}
EOF
sudo systemctl restart docker
echo "DNS已更新"
}
case "$1" in
permissions) fix_permissions ;;
disk) fix_disk_space ;;
network) fix_network ;;
dns) fix_dns ;;
*)
echo "用法: $0 {permissions|disk|network|dns}"
exit 1
;;
esac
27.9 调试技巧
27.9.1 容器调试
bash
# 1. 使用调试镜像
docker run -it --rm nicolaka/netshoot
# 2. 查看容器进程
docker top <container>
# 3. 实时查看容器事件
docker events --filter container=<container>
# 4. 导出容器文件系统
docker export <container> > container.tar
# 5. 进入容器命名空间
PID=$(docker inspect -f '{{.State.Pid}}' <container>)
sudo nsenter -t $PID -n ip addr # 网络命名空间
27.9.2 日志分析
bash
# 跟踪特定错误
docker logs -f <container> 2>&1 | grep -i error
# 统计错误频率
docker logs <container> 2>&1 | grep -i error | wc -l
# 导出日志到文件
docker logs <container> > /tmp/container.log 2>&1
# 使用jq解析JSON日志
docker logs <container> 2>&1 | jq -r 'select(.level=="error")'
27.10 总结
27.10.1 问题分类速查
| 问题类型 | 常见原因 | 快速检查 |
|---|---|---|
| 镜像拉取失败 | 网络、空间、证书 | docker pull, df -h |
| 容器启动失败 | 端口占用、权限、配置 | docker logs, lsof -i |
| 网络不通 | DNS、防火墙、网络模式 | ping, curl, iptables |
| 权限错误 | 用户组、文件权限、SELinux | ls -l, groups, getenforce |
| 磁盘空间不足 | 镜像、日志、卷 | docker system df |
| 性能问题 | 资源限制、I/O、网络 | docker stats, iostat |
27.10.2 排查流程
- 查看日志 :
docker logs <container> - 检查状态 :
docker inspect <container> - 测试网络 :
docker exec <container> ping/curl - 资源使用 :
docker stats <container> - 系统事件 :
docker events - 重启服务 :
sudo systemctl restart docker
27.10.3 预防措施
- 定期清理无用资源
- 配置日志轮转
- 设置资源限制
- 使用健康检查
- 监控磁盘空间
- 备份重要数据
- 文档化配置变更
参考资源:
- Docker官方故障排查指南
- Stack Overflow Docker标签
- Docker社区论坛