From 654ceb1e4321ecf02785d06424dc1ae2fa2fbaa1 Mon Sep 17 00:00:00 2001 From: xzx3344521 Date: Mon, 20 Oct 2025 17:26:21 +0800 Subject: [PATCH] =?UTF-8?q?Update=20Docker=E5=AE=B9=E5=99=A8=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Docker容器管理面板 | 658 ++++++++++++++++++--------------------------- 1 file changed, 259 insertions(+), 399 deletions(-) diff --git a/Docker容器管理面板 b/Docker容器管理面板 index 4fe7533..297a86e 100644 --- a/Docker容器管理面板 +++ b/Docker容器管理面板 @@ -1,449 +1,309 @@ #!/bin/bash -# Docker 管理脚本 -# 功能:容器管理、端口监控、镜像管理、源配置 - -CONFIG_FILE="/etc/docker-manager.conf" -DOCKER_DAEMON_FILE="/etc/docker/daemon.json" -BACKUP_DIR="/opt/docker-backup" +# 实用型 Docker 容器管理脚本 +# 主要功能:容器检测、通过序列号管理容器 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' # No Color +CYAN='\033[0;36m' +NC='\033[0m' # 日志函数 log() { - echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" + echo -e "${GREEN}[✓]${NC} $1" } error() { - echo -e "${RED}[ERROR]${NC} $1" + echo -e "${RED}[✗]${NC} $1" } warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" + echo -e "${YELLOW}[!]${NC} $1" } -# 检查 Docker 是否安装 +# 检查 Docker check_docker() { if ! command -v docker &> /dev/null; then - error "Docker 未安装,请先安装 Docker" + error "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 +# 获取容器状态中文显示 +get_chinese_status() { + local status="$1" + case "$status" in + "Up"*) + echo "运行中" + ;; + "Exited"*) + echo "已停止" + ;; + "Created") + echo "已创建" + ;; + "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 - 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}" + 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 + 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 + done < <(docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | tail -n +2) + + echo + return $count } -# 功能2: 查看容器详细信息 -inspect_container() { - list_containers - echo - read -p "请输入容器名称: " container_name +# 通过编号获取容器名称 +get_container_name() { + local number=$1 + local count=0 - 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 - }' + 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 不存在" + error "容器重启失败: $container_name" fi } -# 功能3: 启动/停止/重启容器 -manage_container() { - list_containers - echo - read -p "请输入容器名称: " container_name +# 停止容器 +stop_container() { + local container_name=$1 + echo -e "\n${YELLOW}停止容器: $container_name${NC}" - if docker inspect "$container_name" &> /dev/null; then - echo - echo "1. 启动容器" - echo "2. 停止容器" - echo "3. 重启容器" - echo "4. 查看容器日志" - read -p "请选择操作: " action + if docker stop "$container_name" &> /dev/null; then + log "容器停止成功: $container_name" + else + error "容器停止失败: $container_name" + fi +} + +# 启动容器 +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) - docker start "$container_name" - log "容器 $container_name 已启动" + # 显示容器列表 + 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 + 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) - docker stop "$container_name" - log "容器 $container_name 已停止" + 8) + cleanup_containers ;; - 3) - docker restart "$container_name" - log "容器 $container_name 已重启" + 9) + show_resources ;; - 4) - docker logs -f "$container_name" + 0) + echo + log "再见!" + exit 0 ;; *) 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 + if [ "$choice" -ne 6 ]; then + echo + read -p "按回车键继续..." 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 +check_docker +main_menu