Update Docker容器管理面板
This commit is contained in:
658
Docker容器管理面板
658
Docker容器管理面板
@@ -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
|
"Exited"*)
|
||||||
AUTO_CLEAN=false
|
echo "已停止"
|
||||||
LOG_RETENTION_DAYS=7
|
;;
|
||||||
EOF
|
"Created")
|
||||||
log "配置文件已创建: $CONFIG_FILE"
|
echo "已创建"
|
||||||
fi
|
;;
|
||||||
|
"Restarting")
|
||||||
|
echo "重启中"
|
||||||
|
;;
|
||||||
|
"Paused")
|
||||||
|
echo "已暂停"
|
||||||
|
;;
|
||||||
|
"Dead")
|
||||||
|
echo "已死亡"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$status"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示容器列表和编号
|
||||||
|
show_containers() {
|
||||||
|
echo -e "\n${CYAN}=== 容器列表 ===${NC}"
|
||||||
|
printf "%-4s | %-20s | %-10s | %s\n" "编号" "容器名称" "状态" "镜像"
|
||||||
|
echo "----|----------------------|----------|-------------------"
|
||||||
|
|
||||||
if [ ! -d "$BACKUP_DIR" ]; then
|
local count=0
|
||||||
mkdir -p "$BACKUP_DIR"
|
while IFS= read -r line; do
|
||||||
fi
|
if [ -n "$line" ]; then
|
||||||
}
|
count=$((count + 1))
|
||||||
|
name=$(echo "$line" | awk '{print $1}')
|
||||||
# 加载配置
|
status=$(echo "$line" | awk '{print $2}')
|
||||||
load_config() {
|
image=$(echo "$line" | awk '{for(i=3;i<=NF;i++) printf $i" "; print ""}' | sed 's/ $//')
|
||||||
if [ -f "$CONFIG_FILE" ]; then
|
|
||||||
source "$CONFIG_FILE"
|
# 获取中文状态
|
||||||
fi
|
chinese_status=$(get_chinese_status "$status")
|
||||||
}
|
|
||||||
|
# 状态颜色
|
||||||
# 显示菜单
|
if [[ "$status" == "Up"* ]]; then
|
||||||
show_menu() {
|
status_display="${GREEN}$chinese_status${NC}"
|
||||||
clear
|
elif [[ "$status" == "Exited"* ]]; then
|
||||||
echo "======================================"
|
status_display="${RED}$chinese_status${NC}"
|
||||||
echo " Docker 容器管理面板"
|
else
|
||||||
echo "======================================"
|
status_display="${YELLOW}$chinese_status${NC}"
|
||||||
echo "1. 查看所有容器状态和端口"
|
fi
|
||||||
echo "2. 查看容器详细信息"
|
|
||||||
echo "3. 启动/停止/重启容器"
|
# 截断镜像名称
|
||||||
echo "4. 删除容器"
|
if [ ${#image} -gt 25 ]; then
|
||||||
echo "5. 查看镜像列表"
|
image="${image:0:22}..."
|
||||||
echo "6. 删除镜像"
|
fi
|
||||||
echo "7. 清理无用镜像和容器"
|
|
||||||
echo "8. 设置 Docker 镜像源"
|
printf "%-4s | %-20s | %-10s | %s\n" "$count" "$name" "$status_display" "$image"
|
||||||
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
|
fi
|
||||||
done
|
done < <(docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | tail -n +2)
|
||||||
|
|
||||||
|
echo
|
||||||
|
return $count
|
||||||
}
|
}
|
||||||
|
|
||||||
# 功能2: 查看容器详细信息
|
# 通过编号获取容器名称
|
||||||
inspect_container() {
|
get_container_name() {
|
||||||
list_containers
|
local number=$1
|
||||||
echo
|
local count=0
|
||||||
read -p "请输入容器名称: " container_name
|
|
||||||
|
|
||||||
if docker inspect "$container_name" &> /dev/null; then
|
while IFS= read -r line; do
|
||||||
echo
|
if [ -n "$line" ]; then
|
||||||
log "容器 $container_name 的详细信息:"
|
count=$((count + 1))
|
||||||
echo "--------------------------------------"
|
if [ $count -eq $number ]; then
|
||||||
docker inspect "$container_name" | jq '.[0] | {
|
echo $(echo "$line" | awk '{print $1}')
|
||||||
Name: .Name,
|
return 0
|
||||||
State: .State.Status,
|
fi
|
||||||
Running: .State.Running,
|
fi
|
||||||
IPAddress: .NetworkSettings.IPAddress,
|
done < <(docker ps -a --format "table {{.Names}}" | tail -n +2)
|
||||||
Ports: .NetworkSettings.Ports,
|
|
||||||
Image: .Config.Image,
|
return 1
|
||||||
Created: .Created,
|
}
|
||||||
Mounts: .Mounts
|
|
||||||
}'
|
# 重启容器
|
||||||
|
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
|
else
|
||||||
error "容器 $container_name 不存在"
|
error "容器重启失败: $container_name"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# 功能3: 启动/停止/重启容器
|
# 停止容器
|
||||||
manage_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
|
||||||
echo
|
log "容器停止成功: $container_name"
|
||||||
echo "1. 启动容器"
|
else
|
||||||
echo "2. 停止容器"
|
error "容器停止失败: $container_name"
|
||||||
echo "3. 重启容器"
|
fi
|
||||||
echo "4. 查看容器日志"
|
}
|
||||||
read -p "请选择操作: " action
|
|
||||||
|
# 启动容器
|
||||||
|
start_container() {
|
||||||
|
local container_name=$1
|
||||||
|
echo -e "\n${YELLOW}启动容器: $container_name${NC}"
|
||||||
|
|
||||||
|
if docker start "$container_name" &> /dev/null; then
|
||||||
|
log "容器启动成功: $container_name"
|
||||||
|
else
|
||||||
|
error "容器启动失败: $container_name"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 删除容器
|
||||||
|
remove_container() {
|
||||||
|
local container_name=$1
|
||||||
|
echo -e "\n${RED}删除容器: $container_name${NC}"
|
||||||
|
|
||||||
|
# 检查容器是否在运行
|
||||||
|
if docker ps | grep -q "$container_name"; then
|
||||||
|
warning "容器正在运行,先停止再删除"
|
||||||
|
docker stop "$container_name" &> /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
log "没有已停止的容器需要清理"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示系统资源
|
||||||
|
show_resources() {
|
||||||
|
echo -e "\n${CYAN}=== 系统资源使用 ===${NC}"
|
||||||
|
docker system df
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主菜单
|
||||||
|
main_menu() {
|
||||||
|
while true; do
|
||||||
|
clear
|
||||||
|
echo -e "${BLUE}"
|
||||||
|
echo "========================================"
|
||||||
|
echo " Docker 容器管理工具"
|
||||||
|
echo "========================================"
|
||||||
|
echo -e "${NC}"
|
||||||
|
|
||||||
case $action in
|
# 显示容器列表
|
||||||
1)
|
show_containers
|
||||||
docker start "$container_name"
|
local container_count=$?
|
||||||
log "容器 $container_name 已启动"
|
|
||||||
|
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
|
||||||
|
1|2|3|4|5|6|7)
|
||||||
|
if [ "$container_count" -eq 0 ]; then
|
||||||
|
error "没有可用的容器"
|
||||||
|
read -p "按回车键继续..."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -p "请输入容器编号: " container_number
|
||||||
|
|
||||||
|
if ! [[ "$container_number" =~ ^[0-9]+$ ]]; then
|
||||||
|
error "无效的编号"
|
||||||
|
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
|
||||||
;;
|
;;
|
||||||
2)
|
8)
|
||||||
docker stop "$container_name"
|
cleanup_containers
|
||||||
log "容器 $container_name 已停止"
|
|
||||||
;;
|
;;
|
||||||
3)
|
9)
|
||||||
docker restart "$container_name"
|
show_resources
|
||||||
log "容器 $container_name 已重启"
|
|
||||||
;;
|
;;
|
||||||
4)
|
0)
|
||||||
docker logs -f "$container_name"
|
echo
|
||||||
|
log "再见!"
|
||||||
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
error "无效选择"
|
error "无效选择"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
|
||||||
error "容器 $container_name 不存在"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 功能4: 删除容器
|
|
||||||
delete_container() {
|
|
||||||
list_containers
|
|
||||||
echo
|
|
||||||
read -p "请输入要删除的容器名称: " container_name
|
|
||||||
|
|
||||||
if docker inspect "$container_name" &> /dev/null; then
|
|
||||||
read -p "确定要删除容器 $container_name 吗?(y/N): " confirm
|
|
||||||
if [[ $confirm == "y" || $confirm == "Y" ]]; then
|
|
||||||
docker rm -f "$container_name"
|
|
||||||
log "容器 $container_name 已删除"
|
|
||||||
else
|
|
||||||
log "操作已取消"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
error "容器 $container_name 不存在"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 功能5: 查看镜像列表
|
|
||||||
list_images() {
|
|
||||||
log "镜像列表:"
|
|
||||||
echo
|
|
||||||
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 功能6: 删除镜像
|
|
||||||
delete_image() {
|
|
||||||
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
|
|
||||||
log "操作已取消"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
error "镜像 $image_id 不存在"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 功能7: 清理无用资源
|
|
||||||
cleanup() {
|
|
||||||
log "正在清理无用资源..."
|
|
||||||
|
|
||||||
echo
|
|
||||||
read -p "是否清理已停止的容器?(y/N): " clean_containers
|
|
||||||
if [[ $clean_containers == "y" || $clean_containers == "Y" ]]; then
|
|
||||||
stopped_containers=$(docker ps -aq -f status=exited)
|
|
||||||
if [ -n "$stopped_containers" ]; then
|
|
||||||
docker rm $stopped_containers
|
|
||||||
log "已清理已停止的容器"
|
|
||||||
else
|
|
||||||
log "没有已停止的容器需要清理"
|
|
||||||
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"
|
|
||||||
|
|
||||||
# 导出容器配置
|
if [ "$choice" -ne 6 ]; then
|
||||||
docker inspect "$container" > "$temp_dir/${container}_inspect.json"
|
echo
|
||||||
|
read -p "按回车键继续..."
|
||||||
# 如果容器正在运行,创建提交点
|
|
||||||
if docker ps | grep -q "$container"; then
|
|
||||||
docker commit -p "$container" "backup_${container}:$timestamp" > /dev/null 2>&1
|
|
||||||
fi
|
fi
|
||||||
done
|
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() {
|
|
||||||
log "Docker 资源使用情况:"
|
|
||||||
echo
|
|
||||||
docker system df
|
|
||||||
|
|
||||||
echo
|
|
||||||
log "容器资源使用情况:"
|
|
||||||
echo
|
|
||||||
docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主循环
|
|
||||||
main() {
|
|
||||||
check_docker
|
|
||||||
init_config
|
|
||||||
load_config
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
show_menu
|
|
||||||
read -p "请选择功能 (1-12): " choice
|
|
||||||
|
|
||||||
case $choice in
|
|
||||||
1) list_containers ;;
|
|
||||||
2) inspect_container ;;
|
|
||||||
3) manage_container ;;
|
|
||||||
4) delete_container ;;
|
|
||||||
5) list_images ;;
|
|
||||||
6) delete_image ;;
|
|
||||||
7) cleanup ;;
|
|
||||||
8) set_registry_mirror ;;
|
|
||||||
9) backup_containers ;;
|
|
||||||
10) restore_containers ;;
|
|
||||||
11) show_resources ;;
|
|
||||||
12)
|
|
||||||
log "再见!"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
error "无效选择,请重新输入"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo
|
|
||||||
read -p "按回车键继续..."
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 脚本入口
|
# 脚本入口
|
||||||
if [ "$(id -u)" -ne 0 ]; then
|
check_docker
|
||||||
error "请使用 root 用户运行此脚本"
|
main_menu
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
main
|
|
||||||
|
|||||||
Reference in New Issue
Block a user