# Docker部署故障排除指南 ## 常见问题与解决方案 ### 1. 端口被占用 ⚠️ **错误信息**: ``` Ports are not available: exposing port TCP 0.0.0.0:8888 -> 0.0.0.0:0: listen tcp 0.0.0.0:8888: bind: address already in use ``` **原因**: 8888端口已被其他进程占用 **解决方案A - 停止占用进程**: ```bash # 1. 查找占用端口的进程 lsof -i :8888 # 或 netstat -tlnp | grep 8888 # 2. 停止进程(替换PID为实际进程ID) kill # 3. 重新启动Docker docker-compose up -d ``` **解决方案B - 更换端口**: ```bash # 修改 docker-compose.yml ports: - "9999:8888" # 使用9999端口 # 或使用命令行 docker run -d -p 9999:8888 sign-server:latest # 访问地址变为: http://localhost:9999 ``` --- ### 2. 容器名称冲突 ⚠️ **错误信息**: ``` The container name "/sm2-sign-server" is already in use ``` **解决方案**: ```bash # 删除旧容器 docker rm -f sm2-sign-server # 重新启动 docker-compose up -d ``` --- ### 3. 镜像构建失败 ⚠️ **错误信息**: ``` ERROR: failed to solve: failed to compute cache key ``` **可能原因**: bin目录或lib目录不存在 **解决方案**: ```bash # 1. 确保已编译(在本地有Java环境时) javac -encoding UTF-8 -d bin -cp "lib/*" $(find src -name "*.java") # 2. 检查目录结构 ls -la bin/ ls -la lib/ # 3. 重新构建 docker-compose build --no-cache docker-compose up -d ``` --- ### 4. 容器启动后立即退出 ⚠️ **检查方法**: ```bash # 查看容器状态 docker ps -a # 查看日志 docker logs sm2-sign-server ``` **常见原因和解决方案**: **原因1: Java版本不兼容** ```bash # 修改Dockerfile使用不同的Java版本 FROM openjdk:11-jre-slim # 改用Java 11 ``` **原因2: 类文件缺失** ```bash # 确保所有class文件存在 find bin -name "*.class" # 如果缺失,重新编译 javac -encoding UTF-8 -d bin -cp "lib/*" $(find src -name "*.java") ``` --- ### 5. 无法访问服务 ⚠️ **症状**: curl无法连接或超时 **排查步骤**: **步骤1: 检查容器是否运行** ```bash docker ps # 确保STATUS显示"Up" ``` **步骤2: 检查端口映射** ```bash docker port sm2-sign-server # 应该显示: 8888/tcp -> 0.0.0.0:8888 ``` **步骤3: 检查容器日志** ```bash docker logs sm2-sign-server # 查看是否有错误信息 ``` **步骤4: 测试容器内部** ```bash # 进入容器 docker exec -it sm2-sign-server sh # 在容器内测试 wget -O- http://localhost:8888/api/health ``` **步骤5: 检查防火墙** ```bash # CentOS/RHEL firewall-cmd --list-ports # Ubuntu ufw status # 如需开放端口 firewall-cmd --permanent --add-port=8888/tcp firewall-cmd --reload ``` --- ### 6. Docker未安装 ⚠️ **错误信息**: ``` docker: command not found ``` **解决方案**: ```bash # 安装Docker (Linux) curl -fsSL https://get.docker.com | sh systemctl start docker systemctl enable docker # 验证安装 docker --version docker-compose --version ``` --- ### 7. 权限不足 ⚠️ **错误信息**: ``` permission denied while trying to connect to the Docker daemon ``` **解决方案**: ```bash # 方案A: 添加用户到docker组 sudo usermod -aG docker $USER # 重新登录生效 # 方案B: 使用sudo sudo docker-compose up -d ``` --- ### 8. 内存不足 ⚠️ **症状**: 容器频繁重启或OOM错误 **解决方案**: ```bash # 限制内存使用 docker run -d \ --name sm2-sign-server \ -p 8888:8888 \ --memory="256m" \ --memory-swap="512m" \ sign-server:latest # 或修改docker-compose.yml services: sign-server: deploy: resources: limits: memory: 256M ``` --- ### 9. 环境变量不生效 ⚠️ **症状**: 传入的私钥未使用 **检查**: ```bash # 查看容器环境变量 docker exec sm2-sign-server env | grep SM2 ``` **正确设置方式**: **docker-compose.yml**: ```yaml services: sign-server: environment: SM2_PRIVATE_KEY: "您的私钥" REQ_ORG_NO: "您的机构号" ``` **命令行**: ```bash docker run -d \ -e SM2_PRIVATE_KEY="私钥" \ -e REQ_ORG_NO="机构号" \ sign-server:latest ``` --- ### 10. 配置文件挂载失败 ⚠️ **错误**: 配置文件不生效 **正确挂载方式**: ```bash # 1. 创建配置文件 cat > config.properties << EOF reqOrgNo=201811200001003 priKey=您的私钥 EOF # 2. 挂载到容器 docker run -d \ -v $(pwd)/config.properties:/app/config.properties:ro \ sign-server:latest # 注意: 使用绝对路径或$(pwd) ``` **docker-compose.yml**: ```yaml services: sign-server: volumes: - ./config.properties:/app/config.properties:ro ``` --- ## 快速诊断命令 ```bash # 一键诊断脚本 #!/bin/bash echo "=== Docker状态 ===" docker --version echo "" echo "=== 容器状态 ===" docker ps -a | grep sm2-sign-server echo "" echo "=== 端口占用 ===" lsof -i :8888 echo "" echo "=== 容器日志(最后20行)===" docker logs --tail 20 sm2-sign-server echo "" echo "=== 网络测试 ===" curl -s http://localhost:8888/api/health || echo "❌ 服务不可访问" ``` --- ## 日志查看技巧 ```bash # 实时查看日志 docker logs -f sm2-sign-server # 查看最近100行 docker logs --tail 100 sm2-sign-server # 查看带时间戳的日志 docker logs -t sm2-sign-server # 查看最近10分钟的日志 docker logs --since 10m sm2-sign-server ``` --- ## 完全重置 如果以上都不行,完全重置: ```bash # 1. 停止并删除所有相关容器 docker stop sm2-sign-server docker rm sm2-sign-server # 2. 删除镜像 docker rmi sign-server:latest # 3. 清理缓存(可选) docker system prune -a # 4. 重新构建和启动 docker-compose build --no-cache docker-compose up -d # 5. 验证 docker logs -f sm2-sign-server ``` --- ## 获取帮助 如果问题仍未解决: 1. **查看完整日志**: ```bash docker logs sm2-sign-server > docker.log cat docker.log ``` 2. **检查系统资源**: ```bash df -h # 磁盘空间 free -h # 内存 docker stats # 容器资源使用 ``` 3. **容器详细信息**: ```bash docker inspect sm2-sign-server ``` --- ## 常用管理命令速查 ```bash # 启动 docker-compose up -d # 停止 docker-compose down # 重启 docker-compose restart # 查看状态 docker-compose ps # 查看日志 docker-compose logs -f # 重新构建 docker-compose build --no-cache # 强制重启 docker-compose down docker-compose up -d --force-recreate # 更新镜像 docker-compose pull docker-compose up -d ``` --- ## 性能优化建议 ### 1. 使用更小的基础镜像 ```dockerfile # 当前使用 (85MB) FROM openjdk:8-jre-alpine # 备选方案 (更小) FROM adoptopenjdk:8-jre-hotspot-alpine ``` ### 2. 限制日志大小 ```bash docker run -d \ --log-opt max-size=10m \ --log-opt max-file=3 \ sign-server:latest ``` ### 3. 健康检查 在Dockerfile添加: ```dockerfile HEALTHCHECK --interval=30s --timeout=3s \ CMD wget --quiet --tries=1 --spider http://localhost:8888/api/health || exit 1 ``` --- ## 最佳实践 1. ✅ 使用docker-compose管理容器 2. ✅ 通过环境变量传递敏感信息 3. ✅ 设置合理的资源限制 4. ✅ 配置日志轮转 5. ✅ 启用自动重启(restart: unless-stopped) 6. ✅ 定期更新基础镜像 7. ✅ 使用健康检查 8. ✅ 生产环境使用HTTPS --- ## 紧急恢复 **服务完全失败时的快速恢复**: ```bash #!/bin/bash # emergency-recovery.sh echo "开始紧急恢复..." # 停止所有 docker-compose down docker rm -f sm2-sign-server # 清理 docker system prune -f # 重建 docker-compose build --no-cache # 启动 docker-compose up -d # 等待 sleep 5 # 测试 curl http://localhost:8888/api/health echo "恢复完成" ``` --- **提示**: 将此文档保存为 `故障排除.md`,遇到问题时快速查阅。