Update Docker容器管理面板

This commit is contained in:
2025-10-20 17:26:21 +08:00
committed by GitHub
parent c14c356d5e
commit 654ceb1e43

View File

@@ -1,449 +1,309 @@
#!/bin/bash #!/bin/bash
# Docker 管理脚本 # 实用型 Docker 容器管理脚本
# 功能:容器管理、端口监控、镜像管理、源配置 # 主要功能:容器检测、通过序列号管理容器
CONFIG_FILE="/etc/docker-manager.conf"
DOCKER_DAEMON_FILE="/etc/docker/daemon.json"
BACKUP_DIR="/opt/docker-backup"
# 颜色定义 # 颜色定义
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
NC='\033[0m' # No Color CYAN='\033[0;36m'
NC='\033[0m'
# 日志函数 # 日志函数
log() { log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" echo -e "${GREEN}[]${NC} $1"
} }
error() { error() {
echo -e "${RED}[ERROR]${NC} $1" echo -e "${RED}[]${NC} $1"
} }
warning() { warning() {
echo -e "${YELLOW}[WARNING]${NC} $1" echo -e "${YELLOW}[!]${NC} $1"
} }
# 检查 Docker 是否安装 # 检查 Docker
check_docker() { check_docker() {
if ! command -v docker &> /dev/null; then if ! command -v docker &> /dev/null; then
error "Docker 未安装,请先安装 Docker" error "Docker 未安装"
exit 1 exit 1
fi fi
} }
# 初始化配置 # 获取容器状态中文显示
init_config() { get_chinese_status() {
if [ ! -f "$CONFIG_FILE" ]; then local status="$1"
mkdir -p $(dirname "$CONFIG_FILE") case "$status" in
cat > "$CONFIG_FILE" << EOF "Up"*)
# Docker 管理器配置文件 echo "运行中"
DEFAULT_REGISTRY_MIRROR="https://docker.mirrors.ustc.edu.cn"
BACKUP_ENABLED=true
AUTO_CLEAN=false
LOG_RETENTION_DAYS=7
EOF
log "配置文件已创建: $CONFIG_FILE"
fi
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR"
fi
}
# 加载配置
load_config() {
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
fi
}
# 显示菜单
show_menu() {
clear
echo "======================================"
echo " Docker 容器管理面板"
echo "======================================"
echo "1. 查看所有容器状态和端口"
echo "2. 查看容器详细信息"
echo "3. 启动/停止/重启容器"
echo "4. 删除容器"
echo "5. 查看镜像列表"
echo "6. 删除镜像"
echo "7. 清理无用镜像和容器"
echo "8. 设置 Docker 镜像源"
echo "9. 备份容器配置"
echo "10. 恢复容器配置"
echo "11. 查看资源使用情况"
echo "12. 退出"
echo "======================================"
}
# 功能1: 查看所有容器状态和端口
list_containers() {
log "正在获取容器信息..."
echo
echo -e "${BLUE}容器名称\t状态\t端口映射${NC}"
echo "--------------------------------------"
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | tail -n +2 | while read line; do
name=$(echo "$line" | awk '{print $1}')
status=$(echo "$line" | awk '{print $2}')
ports=$(echo "$line" | awk '{$1=$2=""; print $0}' | sed 's/^ *//')
if [[ "$status" == "Up" ]]; then
echo -e "${GREEN}$name\t$status\t$ports${NC}"
else
echo -e "${RED}$name\t$status\t$ports${NC}"
fi
done
}
# 功能2: 查看容器详细信息
inspect_container() {
list_containers
echo
read -p "请输入容器名称: " container_name
if docker inspect "$container_name" &> /dev/null; then
echo
log "容器 $container_name 的详细信息:"
echo "--------------------------------------"
docker inspect "$container_name" | jq '.[0] | {
Name: .Name,
State: .State.Status,
Running: .State.Running,
IPAddress: .NetworkSettings.IPAddress,
Ports: .NetworkSettings.Ports,
Image: .Config.Image,
Created: .Created,
Mounts: .Mounts
}'
else
error "容器 $container_name 不存在"
fi
}
# 功能3: 启动/停止/重启容器
manage_container() {
list_containers
echo
read -p "请输入容器名称: " container_name
if docker inspect "$container_name" &> /dev/null; then
echo
echo "1. 启动容器"
echo "2. 停止容器"
echo "3. 重启容器"
echo "4. 查看容器日志"
read -p "请选择操作: " action
case $action in
1)
docker start "$container_name"
log "容器 $container_name 已启动"
;; ;;
2) "Exited"*)
docker stop "$container_name" echo "已停止"
log "容器 $container_name 已停止"
;; ;;
3) "Created")
docker restart "$container_name" echo "已创建"
log "容器 $container_name 已重启"
;; ;;
4) "Restarting")
docker logs -f "$container_name" echo "重启中"
;;
"Paused")
echo "已暂停"
;;
"Dead")
echo "已死亡"
;; ;;
*) *)
error "无效选择" echo "$status"
;; ;;
esac esac
}
# 显示容器列表和编号
show_containers() {
echo -e "\n${CYAN}=== 容器列表 ===${NC}"
printf "%-4s | %-20s | %-10s | %s\n" "编号" "容器名称" "状态" "镜像"
echo "----|----------------------|----------|-------------------"
local count=0
while IFS= read -r line; do
if [ -n "$line" ]; then
count=$((count + 1))
name=$(echo "$line" | awk '{print $1}')
status=$(echo "$line" | awk '{print $2}')
image=$(echo "$line" | awk '{for(i=3;i<=NF;i++) printf $i" "; print ""}' | sed 's/ $//')
# 获取中文状态
chinese_status=$(get_chinese_status "$status")
# 状态颜色
if [[ "$status" == "Up"* ]]; then
status_display="${GREEN}$chinese_status${NC}"
elif [[ "$status" == "Exited"* ]]; then
status_display="${RED}$chinese_status${NC}"
else else
error "容器 $container_name 不存在" status_display="${YELLOW}$chinese_status${NC}"
fi
# 截断镜像名称
if [ ${#image} -gt 25 ]; then
image="${image:0:22}..."
fi
printf "%-4s | %-20s | %-10s | %s\n" "$count" "$name" "$status_display" "$image"
fi
done < <(docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | tail -n +2)
echo
return $count
}
# 通过编号获取容器名称
get_container_name() {
local number=$1
local count=0
while IFS= read -r line; do
if [ -n "$line" ]; then
count=$((count + 1))
if [ $count -eq $number ]; then
echo $(echo "$line" | awk '{print $1}')
return 0
fi
fi
done < <(docker ps -a --format "table {{.Names}}" | tail -n +2)
return 1
}
# 重启容器
restart_container() {
local container_name=$1
echo -e "\n${YELLOW}重启容器: $container_name${NC}"
if docker restart "$container_name" &> /dev/null; then
log "容器重启成功: $container_name"
else
error "容器重启失败: $container_name"
fi fi
} }
# 功能4: 删除容器 # 停止容器
delete_container() { stop_container() {
list_containers local container_name=$1
echo echo -e "\n${YELLOW}停止容器: $container_name${NC}"
read -p "请输入要删除的容器名称: " container_name
if docker inspect "$container_name" &> /dev/null; then if docker stop "$container_name" &> /dev/null; then
read -p "确定要删除容器 $container_name 吗?(y/N): " confirm log "容器停止成功: $container_name"
if [[ $confirm == "y" || $confirm == "Y" ]]; then
docker rm -f "$container_name"
log "容器 $container_name 已删除"
else else
log "操作已取消" error "容器停止失败: $container_name"
fi
else
error "容器 $container_name 不存在"
fi fi
} }
# 功能5: 查看镜像列表 # 启动容器
list_images() { start_container() {
log "镜像列表:" local container_name=$1
echo echo -e "\n${YELLOW}启动容器: $container_name${NC}"
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"
}
# 功能6: 删除镜像 if docker start "$container_name" &> /dev/null; then
delete_image() { log "容器启动成功: $container_name"
list_images
echo
read -p "请输入要删除的镜像ID: " image_id
if docker images --no-trunc | grep -q "$image_id"; then
read -p "确定要删除镜像 $image_id 吗?(y/N): " confirm
if [[ $confirm == "y" || $confirm == "Y" ]]; then
# 检查是否有容器使用此镜像
if docker ps -a --filter ancestor="$image_id" | grep -q "$image_id"; then
error "有容器正在使用此镜像,请先删除相关容器"
return
fi
docker rmi "$image_id"
log "镜像 $image_id 已删除"
else else
log "操作已取消" error "容器启动失败: $container_name"
fi
else
error "镜像 $image_id 不存在"
fi fi
} }
# 功能7: 清理无用资源 # 删除容器
cleanup() { remove_container() {
log "正在清理无用资源..." local container_name=$1
echo -e "\n${RED}删除容器: $container_name${NC}"
echo # 检查容器是否在运行
read -p "是否清理已停止的容器?(y/N): " clean_containers if docker ps | grep -q "$container_name"; then
if [[ $clean_containers == "y" || $clean_containers == "Y" ]]; then warning "容器正在运行,先停止再删除"
stopped_containers=$(docker ps -aq -f status=exited) docker stop "$container_name" &> /dev/null
if [ -n "$stopped_containers" ]; then fi
docker rm $stopped_containers
log "已清理已停止的容器" if docker rm "$container_name" &> /dev/null; then
log "容器删除成功: $container_name"
else
error "容器删除失败: $container_name"
fi
}
# 强制删除容器
force_remove_container() {
local container_name=$1
echo -e "\n${RED}强制删除容器: $container_name${NC}"
if docker rm -f "$container_name" &> /dev/null; then
log "容器强制删除成功: $container_name"
else
error "容器强制删除失败: $container_name"
fi
}
# 查看容器日志
view_logs() {
local container_name=$1
echo -e "\n${BLUE}查看容器日志: $container_name${NC}"
echo "按 Ctrl+C 退出日志查看"
docker logs -f --tail=50 "$container_name"
}
# 查看容器详细信息
inspect_container() {
local container_name=$1
echo -e "\n${CYAN}容器详细信息: $container_name${NC}"
docker inspect "$container_name" | grep -E "(Name|Status|Running|IPAddress|Ports|Image)" | head -10
}
# 清理无用容器
cleanup_containers() {
echo -e "\n${YELLOW}清理已停止的容器...${NC}"
local stopped_count=$(docker ps -aq -f status=exited | wc -l)
if [ "$stopped_count" -gt 0 ]; then
docker container prune -f
log "已清理 $stopped_count 个已停止的容器"
else else
log "没有已停止的容器需要清理" log "没有已停止的容器需要清理"
fi fi
fi
echo
read -p "是否清理悬空镜像?(y/N): " clean_images
if [[ $clean_images == "y" || $clean_images == "Y" ]]; then
dangling_images=$(docker images -q -f dangling=true)
if [ -n "$dangling_images" ]; then
docker rmi $dangling_images
log "已清理悬空镜像"
else
log "没有悬空镜像需要清理"
fi
fi
echo
read -p "是否清理无用网络?(y/N): " clean_networks
if [[ $clean_networks == "y" || $clean_networks == "Y" ]]; then
docker network prune -f
log "已清理无用网络"
fi
echo
read -p "是否清理构建缓存?(y/N): " clean_build_cache
if [[ $clean_build_cache == "y" || $clean_build_cache == "Y" ]]; then
docker system prune -f
log "已清理构建缓存"
fi
} }
# 功能8: 设置 Docker 镜像 # 显示系统资
set_registry_mirror() {
echo
echo "可用的镜像源:"
echo "1. 中科大镜像源 (https://docker.mirrors.ustc.edu.cn)"
echo "2. 阿里云镜像源 (需要自行配置)"
echo "3. 网易镜像源 (https://hub-mirror.c.163.com)"
echo "4. 自定义镜像源"
echo "5. 恢复默认配置"
read -p "请选择镜像源: " mirror_choice
case $mirror_choice in
1)
registry_mirror="https://docker.mirrors.ustc.edu.cn"
;;
2)
read -p "请输入阿里云镜像源地址: " custom_mirror
registry_mirror="$custom_mirror"
;;
3)
registry_mirror="https://hub-mirror.c.163.com"
;;
4)
read -p "请输入自定义镜像源地址: " custom_mirror
registry_mirror="$custom_mirror"
;;
5)
registry_mirror=""
;;
*)
error "无效选择"
return
;;
esac
# 备份原有配置
if [ -f "$DOCKER_DAEMON_FILE" ]; then
cp "$DOCKER_DAEMON_FILE" "$DOCKER_DAEMON_FILE.bak"
log "原配置已备份到 $DOCKER_DAEMON_FILE.bak"
fi
# 创建新的配置
if [ -n "$registry_mirror" ]; then
cat > "$DOCKER_DAEMON_FILE" << EOF
{
"registry-mirrors": ["$registry_mirror"]
}
EOF
log "已设置镜像源: $registry_mirror"
else
# 恢复默认配置
if [ -f "$DOCKER_DAEMON_FILE" ]; then
rm "$DOCKER_DAEMON_FILE"
fi
log "已恢复默认配置"
fi
# 重启 Docker 服务
echo
read -p "需要重启 Docker 服务使配置生效,是否继续?(y/N): " restart_docker
if [[ $restart_docker == "y" || $restart_docker == "Y" ]]; then
systemctl restart docker
log "Docker 服务已重启,镜像源设置完成"
else
warning "请手动重启 Docker 服务以使配置生效"
fi
}
# 功能9: 备份容器配置
backup_containers() {
log "正在备份容器配置..."
timestamp=$(date +%Y%m%d_%H%M%S)
backup_file="$BACKUP_DIR/backup_$timestamp.tar.gz"
# 获取所有容器
containers=$(docker ps -a --format "{{.Names}}")
if [ -z "$containers" ]; then
error "没有找到任何容器"
return
fi
temp_dir=$(mktemp -d)
for container in $containers; do
log "备份容器: $container"
# 导出容器配置
docker inspect "$container" > "$temp_dir/${container}_inspect.json"
# 如果容器正在运行,创建提交点
if docker ps | grep -q "$container"; then
docker commit -p "$container" "backup_${container}:$timestamp" > /dev/null 2>&1
fi
done
# 打包备份文件
tar -czf "$backup_file" -C "$temp_dir" .
rm -rf "$temp_dir"
log "备份完成: $backup_file"
}
# 功能10: 恢复容器配置
restore_containers() {
log "可用的备份文件:"
ls -1 "$BACKUP_DIR"/*.tar.gz 2>/dev/null || echo "没有找到备份文件"
read -p "请输入备份文件名: " backup_file
full_path="$BACKUP_DIR/$backup_file"
if [ ! -f "$full_path" ]; then
error "备份文件不存在: $full_path"
return
fi
temp_dir=$(mktemp -d)
tar -xzf "$full_path" -C "$temp_dir"
for inspect_file in "$temp_dir"/*_inspect.json; do
if [ -f "$inspect_file" ]; then
container_name=$(basename "$inspect_file" | sed 's/_inspect.json//')
log "恢复容器配置: $container_name"
# 这里可以实现更复杂的恢复逻辑
cat "$inspect_file" | docker config create "${container_name}_config" - > /dev/null 2>&1
fi
done
rm -rf "$temp_dir"
log "恢复完成"
}
# 功能11: 查看资源使用情况
show_resources() { show_resources() {
log "Docker 资源使用情况:" echo -e "\n${CYAN}=== 系统资源使用 ===${NC}"
echo
docker system df docker system df
echo
log "容器资源使用情况:"
echo
docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
} }
# 主循环 # 主菜单
main() { main_menu() {
check_docker
init_config
load_config
while true; do while true; do
show_menu clear
read -p "请选择功能 (1-12): " choice echo -e "${BLUE}"
echo "========================================"
echo " Docker 容器管理工具"
echo "========================================"
echo -e "${NC}"
# 显示容器列表
show_containers
local container_count=$?
echo -e "${BLUE}操作选项:${NC}"
echo "1. 重启容器"
echo "2. 停止容器"
echo "3. 启动容器"
echo "4. 删除容器"
echo "5. 强制删除容器"
echo "6. 查看容器日志"
echo "7. 查看容器详情"
echo "8. 清理已停止容器"
echo "9. 查看系统资源"
echo "0. 退出"
echo
read -p "请选择操作 [0-9]: " choice
case $choice in case $choice in
1) list_containers ;; 1|2|3|4|5|6|7)
2) inspect_container ;; if [ "$container_count" -eq 0 ]; then
3) manage_container ;; error "没有可用的容器"
4) delete_container ;; read -p "按回车键继续..."
5) list_images ;; continue
6) delete_image ;; fi
7) cleanup ;;
8) set_registry_mirror ;; read -p "请输入容器编号: " container_number
9) backup_containers ;;
10) restore_containers ;; if ! [[ "$container_number" =~ ^[0-9]+$ ]]; then
11) show_resources ;; error "无效的编号"
12) read -p "按回车键继续..."
continue
fi
container_name=$(get_container_name $container_number)
if [ -z "$container_name" ]; then
error "容器编号不存在"
read -p "按回车键继续..."
continue
fi
case $choice in
1) restart_container "$container_name" ;;
2) stop_container "$container_name" ;;
3) start_container "$container_name" ;;
4) remove_container "$container_name" ;;
5) force_remove_container "$container_name" ;;
6) view_logs "$container_name" ;;
7) inspect_container "$container_name" ;;
esac
;;
8)
cleanup_containers
;;
9)
show_resources
;;
0)
echo
log "再见!" log "再见!"
exit 0 exit 0
;; ;;
*) *)
error "无效选择,请重新输入" error "无效选择"
;; ;;
esac esac
if [ "$choice" -ne 6 ]; then
echo echo
read -p "按回车键继续..." read -p "按回车键继续..."
fi
done done
} }
# 脚本入口 # 脚本入口
if [ "$(id -u)" -ne 0 ]; then check_docker
error "请使用 root 用户运行此脚本" main_menu
exit 1
fi
main