Files
dock/Docker容器管理面板

450 lines
12 KiB
Bash

#!/bin/bash
# Docker 管理脚本
# 功能:容器管理、端口监控、镜像管理、源配置
CONFIG_FILE="/etc/docker-manager.conf"
DOCKER_DAEMON_FILE="/etc/docker/daemon.json"
BACKUP_DIR="/opt/docker-backup"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
}
warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
# 检查 Docker 是否安装
check_docker() {
if ! command -v docker &> /dev/null; then
error "Docker 未安装,请先安装 Docker"
exit 1
fi
}
# 初始化配置
init_config() {
if [ ! -f "$CONFIG_FILE" ]; then
mkdir -p $(dirname "$CONFIG_FILE")
cat > "$CONFIG_FILE" << EOF
# Docker 管理器配置文件
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)
docker stop "$container_name"
log "容器 $container_name 已停止"
;;
3)
docker restart "$container_name"
log "容器 $container_name 已重启"
;;
4)
docker logs -f "$container_name"
;;
*)
error "无效选择"
;;
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"
# 导出容器配置
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() {
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
error "请使用 root 用户运行此脚本"
exit 1
fi
main