#!/bin/bash # 简单实用的 Docker 容器管理脚本 # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' NC='\033[0m' # 检查 Docker check_docker() { if ! command -v docker &> /dev/null; then echo -e "${RED}Docker 未安装${NC}" exit 1 fi } # 显示容器列表 show_containers() { echo -e "\n${BLUE}=== 容器列表 ===${NC}" echo "编号 | 容器名称 | 状态 | 镜像" echo "----|----------|------|------" local count=0 docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | tail -n +2 | while read 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/ $//') # 状态显示 if [[ "$status" == "Up"* ]]; then status_display="${GREEN}运行中${NC}" elif [[ "$status" == "Exited"* ]]; then status_display="${RED}已停止${NC}" else status_display="${YELLOW}$status${NC}" fi echo -e "$count | $name | $status_display | $image" fi done echo } # 显示镜像列表 show_images() { echo -e "\n${PURPLE}=== 镜像列表 ===${NC}" echo "编号 | 镜像名称:标签 | 镜像ID | 大小 | 创建时间" echo "----|---------------|--------|------|----------" local count=0 docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}\t{{.Size}}\t{{.CreatedSince}}" | tail -n +2 | while read line; do if [ -n "$line" ]; then count=$((count + 1)) repo_tag=$(echo "$line" | awk '{print $1}') image_id=$(echo "$line" | awk '{print $2}') size=$(echo "$line" | awk '{print $3}') created=$(echo "$line" | awk '{for(i=4;i<=NF;i++) printf $i" "; print ""}' | sed 's/ $//') # 截断过长的镜像名称 if [ ${#repo_tag} -gt 25 ]; then repo_tag="${repo_tag:0:22}..." fi # 截断镜像ID image_id_short="${image_id:0:12}" echo -e "$count | $repo_tag | $image_id_short | $size | $created" fi done echo } # 通过编号获取容器名称 get_container_name() { local number=$1 local count=0 docker ps -a --format "table {{.Names}}" | tail -n +2 | while read name; do if [ -n "$name" ]; then count=$((count + 1)) if [ $count -eq $number ]; then echo "$name" fi fi done } # 通过编号获取镜像ID get_image_id() { local number=$1 local count=0 docker images --format "table {{.ID}}" | tail -n +2 | while read image_id; do if [ -n "$image_id" ]; then count=$((count + 1)) if [ $count -eq $number ]; then echo "$image_id" fi fi done } # 批量删除容器 batch_delete_containers() { local numbers="$1" local confirm="$2" # 处理输入,支持空格和逗号分隔 numbers=$(echo "$numbers" | sed 's/,/ /g') local success_count=0 local fail_count=0 for number in $numbers; do if [[ "$number" =~ ^[0-9]+$ ]]; then container_name=$(get_container_name $number) if [ -n "$container_name" ]; then if [ "$confirm" != "y" ]; then echo -e "${YELLOW}删除容器: $container_name${NC}" read -p "确认删除?(Y/n): " confirm_delete confirm_delete=${confirm_delete:-Y} # 默认Y if [[ "$confirm_delete" != "y" && "$confirm_delete" != "Y" ]]; then echo -e "${GREEN}跳过: $container_name${NC}" continue fi fi if docker rm -f "$container_name" &> /dev/null; then echo -e "${GREEN}✓ 删除成功: $container_name${NC}" success_count=$((success_count + 1)) else echo -e "${RED}✗ 删除失败: $container_name${NC}" fail_count=$((fail_count + 1)) fi else echo -e "${RED}✗ 容器编号不存在: $number${NC}" fail_count=$((fail_count + 1)) fi else echo -e "${RED}✗ 无效编号: $number${NC}" fail_count=$((fail_count + 1)) fi done echo if [ $success_count -gt 0 ]; then echo -e "${GREEN}成功删除 $success_count 个容器${NC}" fi if [ $fail_count -gt 0 ]; then echo -e "${RED}删除失败 $fail_count 个${NC}" fi } # 批量删除镜像 batch_delete_images() { local numbers="$1" local confirm="$2" # 处理输入,支持空格和逗号分隔 numbers=$(echo "$numbers" | sed 's/,/ /g') local success_count=0 local fail_count=0 for number in $numbers; do if [[ "$number" =~ ^[0-9]+$ ]]; then image_id=$(get_image_id $number) if [ -n "$image_id" ]; then # 获取镜像名称用于显示 image_name=$(docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}" | grep "$image_id" | awk '{print $1}') if [ "$confirm" != "y" ]; then echo -e "${YELLOW}删除镜像: $image_name${NC}" read -p "确认删除?(Y/n): " confirm_delete confirm_delete=${confirm_delete:-Y} # 默认Y if [[ "$confirm_delete" != "y" && "$confirm_delete" != "Y" ]]; then echo -e "${GREEN}跳过: $image_name${NC}" continue fi fi if docker rmi "$image_id" &> /dev/null; then echo -e "${GREEN}✓ 删除成功: $image_name${NC}" success_count=$((success_count + 1)) else echo -e "${RED}✗ 删除失败: $image_name (可能有容器在使用此镜像)${NC}" fail_count=$((fail_count + 1)) fi else echo -e "${RED}✗ 镜像编号不存在: $number${NC}" fail_count=$((fail_count + 1)) fi else echo -e "${RED}✗ 无效编号: $number${NC}" fail_count=$((fail_count + 1)) fi done echo if [ $success_count -gt 0 ]; then echo -e "${GREEN}成功删除 $success_count 个镜像${NC}" fi if [ $fail_count -gt 0 ]; then echo -e "${RED}删除失败 $fail_count 个${NC}" fi } # 清理悬空镜像 clean_dangling_images() { echo -e "${YELLOW}清理悬空镜像...${NC}" local dangling_count=$(docker images -f "dangling=true" -q | wc -l) if [ $dangling_count -gt 0 ]; then read -p "确认删除 $dangling_count 个悬空镜像?(Y/n): " confirm_dangling confirm_dangling=${confirm_dangling:-Y} if [[ "$confirm_dangling" == "y" || "$confirm_dangling" == "Y" ]]; then docker image prune -f echo -e "${GREEN}已清理 $dangling_count 个悬空镜像${NC}" else echo -e "${GREEN}取消清理${NC}" fi else echo -e "${GREEN}没有悬空镜像${NC}" fi } # 镜像管理菜单 image_management() { while true; do clear echo -e "${PURPLE}" echo "========================================" echo " Docker 镜像管理" echo "========================================" echo -e "${NC}" show_images echo -e "${PURPLE}镜像操作选项:${NC}" echo "1. 删除镜像 (支持批量: 1 2 3 或 1,2,3)" echo "2. 批量删除所有镜像" echo "3. 清理悬空镜像" echo "4. 返回主菜单" echo read -p "请选择操作: " choice case $choice in 1) echo echo -e "${YELLOW}删除镜像 (支持批量删除)${NC}" echo "输入单个编号: 1" echo "输入多个编号: 1 2 3 或 1,2,3" echo "输入 all 删除所有镜像" read -p "请输入镜像编号: " input if [[ "$input" == "all" ]]; then echo -e "${RED}警告:将删除所有镜像!${NC}" read -p "确认删除所有镜像?(Y/n): " confirm_all confirm_all=${confirm_all:-Y} if [[ "$confirm_all" == "y" || "$confirm_all" == "Y" ]]; then total_count=$(docker images -q | wc -l) docker rmi -f $(docker images -q) &> /dev/null echo -e "${GREEN}已删除所有 $total_count 个镜像${NC}" else echo -e "${GREEN}取消删除${NC}" fi else batch_delete_images "$input" "n" fi ;; 2) echo -e "${RED}警告:将删除所有镜像!${NC}" read -p "确认删除所有镜像?(Y/n): " confirm_all confirm_all=${confirm_all:-Y} if [[ "$confirm_all" == "y" || "$confirm_all" == "Y" ]]; then total_count=$(docker images -q | wc -l) docker rmi -f $(docker images -q) &> /dev/null echo -e "${GREEN}已删除所有 $total_count 个镜像${NC}" else echo -e "${GREEN}取消删除${NC}" fi ;; 3) clean_dangling_images ;; 4) return ;; *) echo -e "${RED}无效选择${NC}" ;; esac echo read -p "按回车键继续..." done } # 主菜单 main_menu() { while true; do clear echo -e "${BLUE}" echo "========================================" echo " 简单 Docker 容器管理" echo "========================================" echo -e "${NC}" show_containers echo -e "${BLUE}容器操作选项:${NC}" echo "1. 启动容器" echo "2. 停止容器" echo "3. 重启容器" echo "4. 删除容器 (支持批量: 1 2 3 或 1,2,3)" echo "5. 批量删除所有已停止容器" echo "6. 查看容器日志" echo -e "${PURPLE}镜像操作选项:${NC}" echo "7. 查看和管理镜像" echo "0. 退出" echo read -p "请选择操作: " choice case $choice in 1|2|3|6) echo read -p "请输入容器编号: " container_number if ! [[ "$container_number" =~ ^[0-9]+$ ]]; then echo -e "${RED}无效的编号${NC}" read -p "按回车键继续..." continue fi container_name=$(get_container_name $container_number) if [ -z "$container_name" ]; then echo -e "${RED}容器编号不存在${NC}" read -p "按回车键继续..." continue fi case $choice in 1) echo -e "${YELLOW}启动容器: $container_name${NC}" docker start "$container_name" && echo -e "${GREEN}启动成功${NC}" || echo -e "${RED}启动失败${NC}" ;; 2) echo -e "${YELLOW}停止容器: $container_name${NC}" docker stop "$container_name" && echo -e "${GREEN}停止成功${NC}" || echo -e "${RED}停止失败${NC}" ;; 3) echo -e "${YELLOW}重启容器: $container_name${NC}" docker restart "$container_name" && echo -e "${GREEN}重启成功${NC}" || echo -e "${RED}重启失败${NC}" ;; 6) echo -e "${BLUE}查看容器日志: $container_name${NC}" echo "按 Ctrl+C 退出" docker logs -f "$container_name" continue # 日志查看后直接继续,不等回车 ;; esac ;; 4) echo echo -e "${YELLOW}删除容器 (支持批量删除)${NC}" echo "输入单个编号: 1" echo "输入多个编号: 1 2 3 或 1,2,3" echo "输入 all 删除所有容器" read -p "请输入容器编号: " input if [[ "$input" == "all" ]]; then echo -e "${RED}警告:将删除所有容器!${NC}" read -p "确认删除所有容器?(Y/n): " confirm_all confirm_all=${confirm_all:-Y} if [[ "$confirm_all" == "y" || "$confirm_all" == "Y" ]]; then total_count=$(docker ps -aq | wc -l) docker rm -f $(docker ps -aq) &> /dev/null echo -e "${GREEN}已删除所有 $total_count 个容器${NC}" else echo -e "${GREEN}取消删除${NC}" fi else batch_delete_containers "$input" "n" fi ;; 5) echo -e "${YELLOW}批量删除所有已停止的容器...${NC}" stopped_count=$(docker ps -aq -f status=exited | wc -l) if [ $stopped_count -gt 0 ]; then read -p "确认删除 $stopped_count 个已停止容器?(Y/n): " confirm_stopped confirm_stopped=${confirm_stopped:-Y} if [[ "$confirm_stopped" == "y" || "$confirm_stopped" == "Y" ]]; then docker rm $(docker ps -aq -f status=exited) &> /dev/null echo -e "${GREEN}已删除 $stopped_count 个已停止容器${NC}" else echo -e "${GREEN}取消删除${NC}" fi else echo -e "${GREEN}没有已停止的容器${NC}" fi ;; 7) image_management ;; 0) echo echo -e "${GREEN}再见!${NC}" exit 0 ;; *) echo -e "${RED}无效选择${NC}" ;; esac echo read -p "按回车键继续..." done } # 启动脚本 check_docker main_menu