为了方便使用Docker compose进行批发性的部署,下面提供了一个通用的使用DockerCompose的Docker项目部署脚本
其中
PROJECT NAME 为项目显示名称COMPOSE_URL 为存放Docker compose文件的URLPLACEHOLDER_PORT 为占位符,不需要修改DEFAULT_PORT 为默认的对外端口bash#!/bin/sh
# ================= PROFILE =================
PROJECT_NAME="PROJECT NAME"
COMPOSE_URL="https://.../.../*.yaml"
PLACEHOLDER_PORT="PORT"
DEFAULT_PORT="6688"
COMPOSE_TEMPLATE="docker-compose-${PROJECT_NAME}.yaml"
COMPOSE_FILE="docker-compose.yaml"
# ===========================================
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
CYAN='\033[36m'
WHITE='\033[37m'
BOLD='\033[1m'
PLAIN='\033[0m'
log_info() { printf "${CYAN}│ [INFO] ${PLAIN} %s\n" "$1"; }
log_success() { printf "${GREEN}│ [OK] ${PLAIN} %s\n" "$1"; }
log_warn() { printf "${YELLOW}│ [WARN] ${PLAIN} %s\n" "$1"; }
log_err() { printf "${RED}│ [ERR] ${PLAIN} %s\n" "$1"; }
check_env() {
if ! command -v docker > /dev/null 2>&1; then
printf "\n"
log_err "未检测到 Docker,请先安装。"
exit 1
fi
}
download_compose_file() {
if [ -f "$COMPOSE_TEMPLATE" ]; then return; fi
log_info "正在下载配置模板..."
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$COMPOSE_URL" -o "$COMPOSE_TEMPLATE"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$COMPOSE_TEMPLATE" "$COMPOSE_URL"
else
log_err "缺少 curl 或 wget,无法下载。"
return 1
fi
[ -f "$COMPOSE_TEMPLATE" ] || { log_err "下载失败。"; return 1; }
log_success "模板下载完成。"
}
do_up() {
check_env
download_compose_file || return
printf "\n"
printf "${BLUE}╭── ${BOLD}⚙️ 配置向导${PLAIN}${BLUE}───────────────────────────${PLAIN}\n"
printf "${BLUE}│${PLAIN}\n"
printf "${BLUE}│${PLAIN} 请输入宿主机对外端口 (默认: ${CYAN}%s${PLAIN}): " "$DEFAULT_PORT"
read INPUT_PORT < /dev/tty
PORT="${INPUT_PORT:-$DEFAULT_PORT}"
case "$PORT" in
''|*[!0-9]*) log_err "端口必须是数字。"; return ;;
esac
if grep -q "$PLACEHOLDER_PORT" "$COMPOSE_TEMPLATE"; then
sed "s/$PLACEHOLDER_PORT/$PORT/g" "$COMPOSE_TEMPLATE" > "$COMPOSE_FILE"
else
cp "$COMPOSE_TEMPLATE" "$COMPOSE_FILE"
fi
log_info "正在启动容器..."
docker compose up -d
if [ $? -eq 0 ]; then
printf "${BLUE}│${PLAIN}\n"
log_success "服务部署成功!"
printf "${BLUE}│${PLAIN} 🔗 访问地址: http://localhost:${BOLD}%s${PLAIN}\n" "$PORT"
printf "${BLUE}╰─────────────────────────────────────────${PLAIN}\n"
printf "\n"
else
log_err "启动失败,请检查报错。"
fi
}
do_down() {
if [ ! -f "$COMPOSE_FILE" ]; then
log_warn "未发现配置文件。"
return
fi
printf "${BLUE}│${PLAIN}\n"
printf "${BLUE}│${PLAIN} ${YELLOW}请选择清理级别:${PLAIN}\n"
printf "${BLUE}│${PLAIN} ${GREEN}1.${PLAIN}仅停止并删除容器和网络\n"
printf "${BLUE}│${PLAIN} ${GREEN}2.${PLAIN} 同时删除挂载卷(数据会丢失!)\n"
printf "${BLUE}│${PLAIN} ${GREEN}3.${PLAIN} 同时删除本地构建的镜像(不影响公共镜像)\n"
printf "${BLUE}│${PLAIN} ${GREEN}4.${PLAIN} 删除一切(含公共镜像如redis/mysql)\n"
printf "${BLUE}│${PLAIN}\n"
printf "👉 请选择 [1-4](默认 1): "
read level < /dev/tty
level="${level:-1}"
case "$level" in
1) docker compose down ;;
2) docker compose down -v ;;
3) docker compose down -v --rmi local ;;
4) docker compose down -v --rmi all ;;*) log_err "无效选择"; return ;;
esac
rm -f "$COMPOSE_FILE" "$COMPOSE_TEMPLATE"
log_success "清理完成。"
}
do_start() {
[ -f "$COMPOSE_FILE" ] || { log_err "请先执行 [1] 部署"; return; }
docker compose start && log_success "服务已启动"
}
do_stop() {
[ -f "$COMPOSE_FILE" ] || { log_err "请先执行 [1] 部署"; return; }
docker compose stop && log_success "服务已暂停"
}
do_restart() {
[ -f "$COMPOSE_FILE" ] || { log_err "请先执行 [1] 部署"; return; }
docker compose restart && log_success "服务已重启"
}
do_update() {
[ -f "$COMPOSE_FILE" ] || { log_err "请先执行 [1] 部署"; return; }
log_info "拉取镜像..." && docker compose pull
log_info "重建容器..." && docker compose up -d
log_success "更新完成"
}
do_status() {
[ -f "$COMPOSE_FILE" ] || { log_err "未配置服务"; return; }
printf "\n"
docker compose ps
printf "\n"
}
show_menu() {
printf "${BLUE}╭─────────────────────────────────────────${PLAIN}\n"
printf "${BLUE}│${PLAIN} ${BOLD}🐳 Docker ${PLAIN} ${CYAN}%s${PLAIN}\n" "$PROJECT_NAME"
printf "${BLUE}├─────────────────────────────────────────${PLAIN}\n"
printf "${BLUE}│${PLAIN}\n"
printf "${BLUE}│${PLAIN} ${GREEN}1.${PLAIN} 🚀 %-30s\n" "一键部署 (Up)"
printf "${BLUE}│${PLAIN} ${GREEN}2.${PLAIN} 🗑️ %-30s\n" "彻底删除 (Down)"
printf "${BLUE}│${PLAIN}\n"
printf "${BLUE}│${PLAIN} ${GREEN}3.${PLAIN} ▶️ %-30s\n" "启动服务 (Start)"
printf "${BLUE}│${PLAIN} ${GREEN}4.${PLAIN} ⏹️ %-30s\n" "停止服务 (Stop)"
printf "${BLUE}│${PLAIN} ${GREEN}5.${PLAIN} 🔄 %-30s\n" "重启服务 (Restart)"
printf "${BLUE}│${PLAIN} ${GREEN}6.${PLAIN} 🆙 %-30s\n" "更新镜像 (Update)"
printf "${BLUE}│${PLAIN} ${GREEN}7.${PLAIN} 📊 %-30s\n" "查看状态 (Status)"
printf "${BLUE}│${PLAIN}\n"
printf "${BLUE}│${PLAIN} ${GREEN}0.${PLAIN} 🚪 %-30s\n" "退出脚本 (Exit)"
printf "${BLUE}│${PLAIN}\n"
printf "${BLUE}╰─────────────────────────────────────────${PLAIN}\n"
}
while :; do
show_menu
printf " 👉 请输入指令 [0-7]: "
read choice < /dev/tty
case "$choice" in
1) do_up ;;
2) do_down ;;
3) do_start ;;
4) do_stop ;;
5) do_restart ;;
6) do_update ;;
7) do_status ;;
0) printf "\n👋 Bye!\n\n"; exit 0 ;;
*) printf "\n${RED}❌ 无效指令${PLAIN}\n"; sleep 1 ;;
esac
printf "\n 按 Enter 继续..."
read _ < /dev/tty
done
bashservices:
redis:
image: redis:7
container_name: redis-db
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
fastapi:
image: xly23333/fastapi-redis
container_name: fastapi-app
ports:
- "PORT:6001"
environment:
REDIS_HOST: redis
REDIS_PORT: 6379
depends_on:
redis:
condition: service_healthy
volumes:
redis_data:
这里的核心是:对外port的位置一定要书写为"PORT:容器内端口",这样脚本就可以自动替换默认/用户输入的脚本
将脚本和compose全部放置在服务器上,开启一个web服务器,随后再任意设备上运行下面的命令来使用
bashwget -N https://<URL>/<shellName>.sh && sudo sh ./<shellName>.sh
其中<URL>和<shellName>请根据自己的需要进行修改
本文作者:XLY23333
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!