本文目录导读:

在Shell脚本中进入容器调试问题,主要有以下几种方法:
直接使用 docker exec 进入容器
基础用法
# 进入容器的交互式shell docker exec -it 容器名称或ID /bin/bash # 或者使用 sh(如果容器没有bash) docker exec -it 容器名称或ID /bin/sh
在脚本中使用
#!/bin/bash
CONTAINER_NAME="myapp"
# 检查容器是否运行
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "进入容器 $CONTAINER_NAME..."
docker exec -it $CONTAINER_NAME /bin/bash
else
echo "容器 $CONTAINER_NAME 未运行"
fi
调试特定服务或进程
查看容器内进程
#!/bin/bash CONTAINER="webapp" # 查看容器内的进程 docker exec $CONTAINER ps aux # 查看特定服务状态 docker exec $CONTAINER systemctl status nginx # 查看日志 docker exec $CONTAINER tail -f /var/log/app.log
复制文件进行调试
将脚本或工具复制到容器
#!/bin/bash CONTAINER="myapp" # 复制调试脚本到容器 docker cp debug.sh $CONTAINER:/tmp/ docker exec $CONTAINER chmod +x /tmp/debug.sh docker exec $CONTAINER /tmp/debug.sh # 从容器复制文件出来 docker cp $CONTAINER:/app/logs/error.log ./error.log
执行一次性调试命令
#!/bin/bash CONTAINER="database" # 检查网络连接 docker exec $CONTAINER ping -c 3 google.com # 检查端口监听 docker exec $CONTAINER netstat -tlnp # 检查磁盘使用 docker exec $CONTAINER df -h # 检查内存使用 docker exec $CONTAINER free -m
完整的调试脚本示例
#!/bin/bash
# 调试脚本 - docker_debug.sh
CONTAINER_NAME=$1
DEBUG_MODE=${2:-"interactive"}
usage() {
echo "用法: $0 <容器名称> [interactive|diagnostic]"
exit 1
}
if [ -z "$CONTAINER_NAME" ]; then
usage
fi
# 检查容器是否存在
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "错误: 容器 $CONTAINER_NAME 未运行"
exit 1
fi
case $DEBUG_MODE in
"interactive")
echo "进入交互式调试模式..."
docker exec -it $CONTAINER_NAME /bin/bash
;;
"diagnostic")
echo "运行诊断检查..."
# 系统信息
echo "=== 系统信息 ==="
docker exec $CONTAINER_NAME uname -a
# 进程列表
echo "=== 运行进程 ==="
docker exec $CONTAINER_NAME ps aux
# 磁盘使用
echo "=== 磁盘使用 ==="
docker exec $CONTAINER_NAME df -h
# 内存使用
echo "=== 内存使用 ==="
docker exec $CONTAINER_NAME free -m
# 网络连接
echo "=== 网络连接 ==="
docker exec $CONTAINER_NAME netstat -tlnp 2>/dev/null || \
docker exec $CONTAINER_NAME ss -tlnp
;;
*)
usage
;;
esac
处理特殊情况
容器没有bash/shell
#!/bin/bash
CONTAINER="minimal-container"
# 尝试不同的shell
for shell in /bin/bash /bin/sh /bin/ash /bin/zsh; do
if docker exec $CONTAINER test -f $shell 2>/dev/null; then
docker exec -it $CONTAINER $shell
break
fi
done
使用nsenter进入容器命名空间
#!/bin/bash
CONTAINER="myapp"
# 获取容器PID
PID=$(docker inspect -f '{{.State.Pid}}' $CONTAINER)
# 使用nsenter进入容器
if [ -n "$PID" ]; then
nsenter -t $PID -m -u -i -n -p
fi
调试Web应用程序
#!/bin/bash
CONTAINER="webapp"
# 检查Web服务器
echo "测试HTTP响应..."
docker exec $CONTAINER curl -s -o /dev/null -w "%{http_code}" http://localhost:80/
# 检查应用日志
echo "查看最近10行日志..."
docker exec $CONTAINER tail -10 /var/log/app.log
# 检查环境变量
echo "环境变量..."
docker exec $CONTAINER env | grep -E "APP_|DB_"
实用技巧
- 别名简化命令
alias dexec='docker exec -it'
使用
dexec myapp /bin/bash
2. **批量调试多个容器**
```bash
#!/bin/bash
# 调试所有运行中的容器
for container in $(docker ps --format '{{.Names}}'); do
echo "=== 调试 $container ==="
docker exec $container hostname
docker exec $container df -h /data
done
- 安全考虑
# 以非root用户进入容器 docker exec -u www-data -it myapp /bin/bash
只读模式挂载
docker exec -it --read-only myapp /bin/bash
选择哪种方式取决于你的调试需求:
- **交互式调试**:使用 `docker exec -it`
- **批量检查**:使用一次性命令
- **文件传输**:使用 `docker cp`
- **高级调试**:使用 `nsenter` 或 `docker inspect`