【軟件運維】前后端部署啟動的幾種方式

.sh啟動

#!/bin/bash# 解析軟鏈接,獲取真實腳本目錄
SOURCE="${BASH_SOURCE[0]}"
while [ -L "$SOURCE" ]; doDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"SOURCE="$(readlink "$SOURCE")"[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
CURRENT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
echo "當前腳本所在目錄: $CURRENT_DIR"# ================ 配置參數 ================
# conda環境名稱
CONDA_ENV="hr"# 程序路徑 - 使用當前目錄作為基礎
PROGRAM_PATH="$CURRENT_DIR/backend/run.py"# 程序啟動參數(如有)
PROGRAM_ARGS=""# 日志文件路徑 - 使用當前目錄下的logs文件夾
LOG_FILE="$CURRENT_DIR/logs/backend/backend.log"# 日志保留天數
LOG_RETENTION_DAYS=7# 日志切割頻率(分鐘)
LOG_ROTATE_INTERVAL=1440  # 默認24小時# 上次切割日志的時間戳文件
LAST_ROTATE_FILE="/tmp/backend_log_rotate.timestamp"# ================ 函數定義 ================# 加載conda環境
load_conda_env() {# 嘗試加載conda初始化腳本,增加Miniforge的路徑if [ -f "$HOME/miniforge3/etc/profile.d/conda.sh" ]; thensource "$HOME/miniforge3/etc/profile.d/conda.sh"elif [ -f "$HOME/mambaforge/etc/profile.d/conda.sh" ]; thensource "$HOME/mambaforge/etc/profile.d/conda.sh"elif [ -f "$HOME/miniconda3/etc/profile.d/conda.sh" ]; thensource "$HOME/miniconda3/etc/profile.d/conda.sh"elif [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; thensource "$HOME/anaconda3/etc/profile.d/conda.sh"elif [ -f "/opt/conda/etc/profile.d/conda.sh" ]; thensource "/opt/conda/etc/profile.d/conda.sh"else# 嘗試查找系統中的conda.sh文件CONDA_SH=$(find $HOME -name "conda.sh" -path "*/etc/profile.d/*" 2>/dev/null | head -n 1)if [ -n "$CONDA_SH" ]; thensource "$CONDA_SH"elseecho "錯誤: 找不到conda初始化腳本,請檢查Miniforge/conda安裝路徑" >&2exit 1fifi# 激活指定環境conda activate "$CONDA_ENV"if [ $? -ne 0 ]; thenecho "錯誤: 無法激活conda環境 '$CONDA_ENV'" >&2exit 1fiecho "已激活conda環境: $CONDA_ENV"
}# 啟動后端程序
start_backend() {# 確保日志目錄存在LOG_DIR=$(dirname "$LOG_FILE")mkdir -p "$LOG_DIR"# 檢查程序是否已運行if pgrep -f "python.*$PROGRAM_PATH $PROGRAM_ARGS" > /dev/null; thenecho "警告: 程序已在運行中,PID: $(pgrep -f "python.*$PROGRAM_PATH $PROGRAM_ARGS")"return 1fi# 啟動程序并記錄PID - 使用python命令echo "正在啟動程序: python $PROGRAM_PATH $PROGRAM_ARGS"cd "$(dirname "$PROGRAM_PATH")"  # 切換到腳本所在目錄nohup python "$(basename "$PROGRAM_PATH")" $PROGRAM_ARGS > "$LOG_FILE" 2>&1 &PID=$!# 保存PID到文件(可選)echo $PID > "$LOG_DIR/backend.pid"echo "程序已啟動,PID: $PID,日志輸出到: $LOG_FILE"# 啟動守護進程DAEMON_SH="$CURRENT_DIR/deamon.sh"if ! pgrep -f "$DAEMON_SH" > /dev/null; thennohup bash "$DAEMON_SH" > /dev/null 2>&1 &echo "守護進程已啟動"elseecho "守護進程已在運行"fireturn 0
}# 切割日志文件
rotate_log() {# 創建日志目錄(如果不存在)LOG_DIR=$(dirname "$LOG_FILE")mkdir -p "$LOG_DIR"# 生成備份文件名(包含時間戳)TIMESTAMP=$(date +%Y%m%d_%H%M%S)BACKUP_FILE="${LOG_FILE}.${TIMESTAMP}"# 移動當前日志文件到備份if [ -f "$LOG_FILE" ]; thenmv "$LOG_FILE" "$BACKUP_FILE"echo "日志已切割: $BACKUP_FILE"# 更新上次切割時間echo $(date +%s) > "$LAST_ROTATE_FILE"# 清理過期日志find "$LOG_DIR" -name "$(basename $LOG_FILE).*" -type f -mtime +$LOG_RETENTION_DAYS -deletefi
}# 檢查是否需要切割日志
check_rotate_needed() {# 如果時間戳文件不存在,創建并返回需要切割if [ ! -f "$LAST_ROTATE_FILE" ]; thenecho $(date +%s) > "$LAST_ROTATE_FILE"return 0fi# 計算上次切割到現在的時間(分鐘)LAST_ROTATE=$(cat "$LAST_ROTATE_FILE")CURRENT_TIME=$(date +%s)ELAPSED_MINUTES=$(( (CURRENT_TIME - LAST_ROTATE) / 60 ))# 如果超過設定的時間間隔,返回需要切割if [ $ELAPSED_MINUTES -ge $LOG_ROTATE_INTERVAL ]; thenreturn 0fireturn 1
}# 顯示使用幫助
show_help() {echo "用法: $0 [選項]"echo "選項:"echo "  start    啟動后端程序"echo "  rotate   手動切割日志"echo "  status   檢查程序狀態"echo "  stop     停止后端程序"echo "  restart  重啟后端程序"echo "  help     顯示此幫助信息"exit 0
}# 停止后端程序
stop_backend() {LOG_DIR=$(dirname "$LOG_FILE")PID_FILE="$LOG_DIR/backend.pid"# 如果有PID文件,嘗試通過PID停止if [ -f "$PID_FILE" ]; thenPID=$(cat "$PID_FILE")if ps -p $PID > /dev/null; thenecho "正在停止程序,PID: $PID"kill $PID# 等待最多10秒for i in {1..10}; doif ! ps -p $PID > /dev/null; thenecho "程序已停止"rm -f "$PID_FILE"return 0fisleep 1done# 如果10秒后仍在運行,強制終止echo "程序未響應,強制終止"kill -9 $PIDrm -f "$PID_FILE"return 0elseecho "警告: PID文件存在但進程不存在,刪除PID文件"rm -f "$PID_FILE"fifi# 如果沒有PID文件,嘗試通過程序名查找PROGRAM_NAME=$(basename "$PROGRAM_PATH")PID=$(pgrep -f "python.*$PROGRAM_PATH $PROGRAM_ARGS")if [ -n "$PID" ]; thenecho "找到程序實例,PID: $PID"kill $PID# 等待最多10秒for i in {1..10}; doif ! ps -p $PID > /dev/null; thenecho "程序已停止"return 0fisleep 1done# 如果10秒后仍在運行,強制終止echo "程序未響應,強制終止"kill -9 $PIDreturn 0fiecho "未找到運行中的程序實例"return 1
}# 檢查程序狀態
check_status() {LOG_DIR=$(dirname "$LOG_FILE")PID_FILE="$LOG_DIR/backend.pid"if [ -f "$PID_FILE" ]; thenPID=$(cat "$PID_FILE")if ps -p $PID > /dev/null; thenecho "程序正在運行,PID: $PID"echo "日志文件: $LOG_FILE"return 0elseecho "程序未運行"return 1fielseecho "程序未運行"return 1fi
}# ================ 主程序 ================# 檢查命令行參數
case "$1" instart)load_conda_envstart_backend;;rotate)rotate_log;;status)check_status;;stop)stop_backend;;restart)stop_backendload_conda_envstart_backend;;help|--help|-h)show_help;;*)echo "錯誤: 未知命令 '$1'"show_help;;
esacexit 0


這個Bash腳本是一個用于管理Python后端程序的工具腳本,提供了啟動、停止、重啟、狀態檢查以及日志管理等功能。下面我將分部分詳細解釋這個腳本的內容和工作原理。

1. 獲取真實腳本目錄

SOURCE="${BASH_SOURCE[0]}"
while [ -L "$SOURCE" ]; doDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"SOURCE="$(readlink "$SOURCE")"[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
CURRENT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
echo "當前腳本所在目錄: $CURRENT_DIR"

這部分代碼的作用是獲取腳本的真實路徑,即使腳本是通過軟鏈接調用的。它通過以下步驟實現:

  1. 獲取腳本路徑(SOURCE)

  2. 如果路徑是軟鏈接(-L),則解析真實路徑

  3. 處理相對路徑的情況(SOURCE != /*)

  4. 最終獲取腳本所在目錄的絕對路徑(CURRENT_DIR)

2. 配置參數

CONDA_ENV="hr"  # conda環境名稱
PROGRAM_PATH="$CURRENT_DIR/backend/run.py"  # 程序路徑
PROGRAM_ARGS=""  # 程序啟動參數
LOG_FILE="$CURRENT_DIR/logs/backend/backend.log"  # 日志文件路徑
LOG_RETENTION_DAYS=7  # 日志保留天數
LOG_ROTATE_INTERVAL=1440  # 日志切割頻率(分鐘,默認24小時)
LAST_ROTATE_FILE="/tmp/backend_log_rotate.timestamp"  # 上次切割日志的時間戳文件

這部分定義了腳本使用的各種參數,包括:

  • Conda環境名稱

  • 要運行的Python程序路徑

  • 程序啟動參數

  • 日志文件位置和保留策略

3. 函數定義

3.1?load_conda_env?函數

load_conda_env() {# 嘗試從多個可能的位置加載conda初始化腳本if [ -f "$HOME/miniforge3/etc/profile.d/conda.sh" ]; thensource "$HOME/miniforge3/etc/profile.d/conda.sh"elif [ -f ... ]; then  # 其他可能的位置...fi# 激活指定conda環境conda activate "$CONDA_ENV"...
}

這個函數負責加載conda環境,它會嘗試從多個常見位置查找conda初始化腳本,然后激活指定的conda環境(hr)。

3.2?start_backend?函數

start_backend() {# 確保日志目錄存在mkdir -p "$LOG_DIR"# 檢查程序是否已運行if pgrep -f "python.*$PROGRAM_PATH $PROGRAM_ARGS" > /dev/null; thenecho "警告: 程序已在運行中..."return 1fi# 啟動程序并記錄PIDnohup python "$(basename "$PROGRAM_PATH")" $PROGRAM_ARGS > "$LOG_FILE" 2>&1 &PID=$!echo $PID > "$LOG_DIR/backend.pid"# 啟動守護進程DAEMON_SH="$CURRENT_DIR/deamon.sh"if ! pgrep -f "$DAEMON_SH" > /dev/null; thennohup bash "$DAEMON_SH" > /dev/null 2>&1 &fi
}

這個函數負責啟動后端程序,它會:

  1. 創建必要的日志目錄

  2. 檢查程序是否已經在運行

  3. 使用nohup在后臺啟動Python程序,并重定向輸出到日志文件

  4. 保存進程ID(PID)到文件

  5. 啟動守護進程(如果未運行)

3.3 日志管理函數

rotate_log() {# 創建日志備份文件TIMESTAMP=$(date +%Y%m%d_%H%M%S)BACKUP_FILE="${LOG_FILE}.${TIMESTAMP}"mv "$LOG_FILE" "$BACKUP_FILE"# 清理過期日志find "$LOG_DIR" -name "$(basename $LOG_FILE).*" -type f -mtime +$LOG_RETENTION_DAYS -delete
}check_rotate_needed() {# 檢查是否需要切割日志(基于時間間隔)...
}

這些函數負責日志的輪轉(切割)管理:

  • rotate_log: 將當前日志重命名為帶時間戳的備份文件,并清理過期的日志

  • check_rotate_needed: 檢查是否到了需要切割日志的時間

3.4 其他管理函數

stop_backend() {# 通過PID文件或程序名查找并停止程序...
}check_status() {# 檢查程序運行狀態...
}show_help() {# 顯示使用幫助...
}

這些函數提供了其他管理功能:

  • 停止程序

  • 檢查程序狀態

  • 顯示幫助信息

4. 主程序

case "$1" instart)load_conda_envstart_backend;;rotate)rotate_log;;status)check_status;;stop)stop_backend;;restart)stop_backendload_conda_envstart_backend;;help|--help|-h)show_help;;*)echo "錯誤: 未知命令 '$1'"show_help;;
esac

這部分是腳本的入口,根據傳入的參數調用相應的函數:

  • start: 啟動程序

  • rotate: 手動切割日志

  • status: 檢查狀態

  • stop: 停止程序

  • restart: 重啟程序

  • help: 顯示幫助

要啟動這個腳本,你需要根據腳本提供的功能選項來執行相應的命令。以下是使用這個腳本的各種方法:

基本使用方法

bash 腳本文件名.sh [選項]

具體操作命令

  1. 啟動后端程序

    bash script.sh start
    • 這會激活conda環境并啟動Python后端程序

    • 同時會啟動守護進程(如果配置了的話)

  2. 停止后端程序

    bash script.sh stop
  3. 重啟后端程序

    bash script.sh restart
  4. 手動切割日志

    bash script.sh rotate
  5. 檢查程序狀態

    bash script.sh status
  6. 查看幫助信息

    bash script.sh help
    或
    bash script.sh --help
    或
    bash script.sh -h

?守護進程腳本

后端啟動后意外停止的常見原因:

Python 腳本自身崩潰
  • 可能原因

    • 未捕獲的異常(如?KeyError,?ImportError)。

    • 內存泄漏導致被系統 OOM Killer 終止。

    • 第三方庫的 Bug 或兼容性問題。

  • 排查方法

    # 查看腳本是否有崩潰日志(如果未重定向輸出)
    cat nohup.out
    # 或主動記錄錯誤到文件
    python run.py >> run.log 2>&1
系統資源不足
  • 可能原因

    • 內存不足:進程占用內存過多被系統 OOM Killer 殺死。

      dmesg | grep -i "killed"  # 檢查是否有 OOM 記錄
    • CPU/磁盤過載:長時間高負載導致進程卡死。

      top -p $(pgrep -f "run.py")  # 監控資源占用
會話中斷導致信號終止
  • 可能原因

    • nohup?雖然能忽略?SIGHUP?信號,但可能收到其他信號(如?SIGTERM)。

    • 服務器運維操作(如定期重啟、Cron 任務)可能主動終止進程。

  • 排查方法

    # 檢查系統日志(如 syslog/auth.log)
    grep -i "kill" /var/log/syslog
依賴服務不可用
  • 可能原因

    • 數據庫/Redis 等依賴服務斷開,導致 Python 腳本主動退出。

    • 網絡波動導致 HTTP 請求超時。

  • 排查方法

    • 在代碼中添加依賴服務的健康檢查(如數據庫連接重試邏輯)。

Python 環境問題
  • 可能原因

    • 虛擬環境未激活或包版本沖突。

    • Python 解釋器自身崩潰(罕見但可能)。

  • 排查方法

    # 檢查 Python 版本和依賴
    python -V
    pip list | grep "關鍵依賴包名"
定時任務或運維腳本干擾
  • 可能原因

    • 服務器上有其他 Cron 任務或監控腳本誤殺進程。

    crontab -l  # 檢查當前用戶的定時任務

因此用了一個監控和自動重啟后端服務的 Bash 守護進程腳本(deamon.sh)。我來逐步解析它的功能和工作原理:


1. 基礎設置

OP_SCRIPT="$(dirname "$(readlink -f "$0")")/op.sh"
  • 作用:定位同目錄下的?op.sh?腳本(假設這是管理后端服務的腳本)。

  • 技術點:

    • $0?是當前腳本路徑(如?./deamon.sh)。

    • readlink -f?解析符號鏈接并返回絕對路徑。

    • dirname?提取目錄路徑。

CHECK_INTERVAL=300  # 檢查間隔(秒,這里是5分鐘)
LOG_FILE="$(dirname "$OP_SCRIPT")/logs/backend/daemon.log"
  • 定義檢查服務狀態的間隔時間(300秒)和日志文件路徑。


2. 日志函數

log() {echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG_FILE"
}
  • 將帶時間戳的消息追加到日志文件(如?2024-01-01 12:00:00 守護進程啟動...)。


3. 服務狀態檢測

is_running() {"$OP_SCRIPT" status | grep -q "程序正在運行"
}
  • 邏輯

    1. 調用?op.sh status?檢查服務狀態。

    2. 用?grep -q?靜默匹配輸出中是否包含?程序正在運行

    3. 如果匹配成功(服務在運行),返回?0(成功);否則返回非零。


4. 服務啟動函數

start_service() {log "檢測到服務未運行,嘗試啟動...""$OP_SCRIPT" start >> "$LOG_FILE" 2>&1
}
  • 如果服務未運行:

    1. 記錄日志。

    2. 調用?op.sh start?啟動服務,并將輸出和錯誤重定向到日志文件。


5. 主循環

log "守護進程啟動,開始監控后端服務..."
while true; doif ! is_running; thenstart_servicefisleep $CHECK_INTERVAL
done
  • 無限循環

    1. 檢查服務狀態(is_running)。

    2. 如果服務停止,調用?start_service

    3. 休眠?CHECK_INTERVAL?秒后重復檢查。


關鍵點總結

  1. 依賴關系

    • 需要同目錄下的?op.sh?腳本,且該腳本需支持?status?和?start?命令。

    • 假設?op.sh status?的輸出中包含?程序正在運行?字符串。

  2. 日志管理

    • 所有操作記錄到?logs/backend/daemon.log,便于排查問題。

  3. 工作場景

    • 適合監控需要長期運行的后端服務(如Web API、數據庫等)。

    • 當服務意外崩潰時,自動嘗試重啟。

#!/bin/bash# deamon.sh:守護op.sh啟動的后端服務OP_SCRIPT="$(dirname "$(readlink -f "$0")")/op.sh"
CHECK_INTERVAL=300
LOG_FILE="$(dirname "$OP_SCRIPT")/logs/backend/daemon.log"log() {echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG_FILE"
}is_running() {"$OP_SCRIPT" status | grep -q "程序正在運行"
}start_service() {log "檢測到服務未運行,嘗試啟動...""$OP_SCRIPT" start >> "$LOG_FILE" 2>&1
}log "守護進程啟動,開始監控后端服務..."
while true; doif ! is_running; thenstart_servicefisleep $CHECK_INTERVAL
done

Make dev命令

看到了一個谷歌項目,他的前后端啟動方式很方便

https://github.com/google-gemini/gemini-fullstack-langgraph-quickstart/blob/main/README.md

項目最外部有一個makefile

.PHONY: help dev-frontend dev-backend devhelp:@echo "Available commands:"@echo "  make dev-frontend    - Starts the frontend development server (Vite)"@echo "  make dev-backend     - Starts the backend development server (Uvicorn with reload)"@echo "  make dev             - Starts both frontend and backend development servers"dev-frontend:@echo "Starting frontend development server..."@cd frontend && npm run devdev-backend:@echo "Starting backend development server..."@cd backend && langgraph dev# Run frontend and backend concurrently
dev:@echo "Starting both frontend and backend development servers..."@make dev-frontend & make dev-backend 

這個 Makefile 是一個用于管理項目開發工作流的構建文件,特別適合同時包含前端和后端的項目。讓我們逐部分深入分析:

1. .PHONY 聲明

.PHONY: help dev-frontend dev-backend dev
  • .PHONY?是一個特殊目標,用于聲明哪些目標是"偽目標"(不是實際的文件名)

  • 這里聲明了?help,?dev-frontend,?dev-backend?和?dev?都是偽目標

  • 這意味著即使存在同名文件,Make 也會執行這些目標下的命令

2. help 目標

help:@echo "Available commands:"@echo "  make dev-frontend    - Starts the frontend development server (Vite)"@echo "  make dev-backend     - Starts the backend development server (Uvicorn with reload)"@echo "  make dev             - Starts both frontend and backend development servers"
  • 這是一個幫助信息目標,顯示可用的命令及其描述

  • @?符號表示在執行時不顯示命令本身,只顯示輸出

  • 這是典型的自文檔化 Makefile 的做法

3. dev-frontend 目標

dev-frontend:@echo "Starting frontend development server..."@cd frontend && npm run dev
  • 用于啟動前端開發服務器

  • 先顯示啟動信息,然后:

    • cd frontend?進入 frontend 目錄

    • npm run dev?運行 npm 的 dev 腳本(假設使用 Vite,如幫助信息所示)

  • 這要求項目有一個 frontend 目錄,并且其中 package.json 中定義了 dev 腳本

4. dev-backend 目標

dev-backend:@echo "Starting backend development server..."@cd backend && langgraph dev
  • 用于啟動后端開發服務器

  • 先顯示啟動信息,然后:

    • cd backend?進入 backend 目錄

    • langgraph dev?運行 langgraph 的開發命令(看起來是使用某種 Python 框架)

  • 這要求項目有一個 backend 目錄,并且安裝了 langgraph

5. dev 目標

dev:@echo "Starting both frontend and backend development servers..."@make dev-frontend & make dev-backend 
  • 這是最常用的目標,同時啟動前后端開發服務器

  • 使用?&?運算符在后臺并行運行兩個 make 命令

  • 注意:

    • 這種方式簡單但不夠健壯,如果某個進程失敗不會自動停止另一個

    • 更高級的替代方案是使用?concurrently?或?docker-compose?等工具

使用場景

這個 Makefile 典型用于全棧 JavaScript/Python 項目,其中:

  • 前端使用 Vite(現代前端構建工具)

  • 后端使用某種 Python 框架(可能是 FastAPI 或其他,基于?langgraph?命令判斷)

總結

這個 Makefile 提供了一個簡潔的接口來管理常見的開發任務,通過簡單的?make dev?命令就能啟動整個開發環境,大大簡化了開發者的工作流程。它體現了 Makefile 作為項目任務自動化工具的經典用法,特別適合需要同時管理多個服務的項目。

Docker前端啟動

FROM m.daocloud.io/docker.io/library/nginx:latest# 移除默認的nginx配置
RUN rm -rf /etc/nginx/conf.d/*# 創建目錄結構
RUN mkdir -p /usr/share/nginx/html/dist
RUN mkdir -p /etc/nginx/ssl# 暴露端口
EXPOSE 80CMD ["nginx", "-g", "daemon off;"]

這是一個用于配置 Nginx 服務器的 Dockerfile,讓我們逐部分分析它的結構和功能:

基礎鏡像

FROM m.daocloud.io/docker.io/library/nginx:latest
  • 使用 DaoCloud 鏡像源(中國國內常用的鏡像加速源)拉取官方的 Nginx 鏡像

  • library/nginx:latest?表示使用 Docker 官方倉庫中的最新版 Nginx 鏡像

  • m.daocloud.io/?前綴是為了加速在中國地區的下載

清理默認配置

RUN rm -rf /etc/nginx/conf.d/*
  • 刪除 Nginx 默認的配置文件

  • /etc/nginx/conf.d/?是 Nginx 加載額外配置文件的目錄

  • 這樣做是為了準備完全自定義的 Nginx 配置

創建目錄結構

RUN mkdir -p /usr/share/nginx/html/dist
RUN mkdir -p /etc/nginx/ssl
  1. 前端靜態文件目錄

    • /usr/share/nginx/html/dist?是準備存放前端構建產物(如 Vue/React 打包后的文件)的目錄

    • -p?參數確保即使父目錄不存在也會創建

  2. SSL 證書目錄

    • /etc/nginx/ssl?是為 HTTPS 準備的 SSL 證書存放目錄

    • 雖然當前 Dockerfile 沒有配置 HTTPS,但預留了這個目錄

暴露端口

EXPOSE 80
  • 聲明容器將監聽 80 端口(HTTP 默認端口)

  • 這只是文檔性質的聲明,實際端口映射需要在?docker run?時用?-p?參數指定

啟動命令

CMD ["nginx", "-g", "daemon off;"]
  • 以非守護進程模式運行 Nginx

  • -g "daemon off;"?是 Nginx 的參數,表示在前臺運行

  • 這是 Docker 容器的最佳實踐,因為容器需要有一個持續運行的前臺進程

典型使用場景

這個 Dockerfile 適合用于:

  1. 部署前端靜態資源(如 Vue/React 應用)

  2. 需要自定義 Nginx 配置的情況

  3. 作為基礎鏡像進一步擴展

docker-compose.yaml

version: '3'   services:nginx:build: .image: hrfusion-fd-nginx:v1.0container_name: hrfusion-fd-hyqrestart: alwaysports:- "18001:80"                                             # docker端口映射[宿主機端口:容器內部端口]volumes:# - ./ssl_certs:/etc/nginx/ssl                              # 證書目錄- ./frontend/dist:/usr/share/nginx/html/dist              # 項目目錄- ./frontend/default.conf:/etc/nginx/conf.d/default.conf  # 服務配置

這個?docker-compose.yml?文件定義了一個 Nginx 服務的配置,用于部署前端應用。讓我們逐部分深入分析:

文件結構概覽

version: '3'   
services:nginx:# 配置詳情...
  • version: '3'?- 指定使用 Docker Compose 文件格式版本 3

  • services:?- 定義要運行的服務列表

  • nginx:?- 定義一個名為 "nginx" 的服務

服務配置詳解

1. 構建與鏡像

build: .
image: hrfusion-fd-nginx:v1.0
  • build: .?- 使用當前目錄下的 Dockerfile 構建鏡像

  • image: hrfusion-fd-nginx:v1.0?- 為構建的鏡像指定名稱和標簽

    • 這樣構建后會有兩個引用:

      • 一個是通過構建過程生成的匿名鏡像

      • 一個是命名為?hrfusion-fd-nginx:v1.0?的鏡像

2. 容器設置

container_name: hrfusion-fd-hyq
restart: always
  • container_name: hrfusion-fd-hyq?- 為容器指定固定名稱(而不是隨機生成)

  • restart: always?- 容器退出時自動重啟

    • 這確保了服務在崩潰或服務器重啟后自動恢復

3. 端口映射

ports:- "18001:80"
  • 將宿主機的 18001 端口映射到容器的 80 端口

  • 格式:"主機端口:容器端口"

  • 這意味著:

    • 外部訪問?http://主機IP:18001

    • 請求會被轉發到容器的 80 端口

    • Nginx 在容器內監聽 80 端口

4. 數據卷掛載

volumes:# - ./ssl_certs:/etc/nginx/ssl- ./frontend/dist:/usr/share/nginx/html/dist- ./frontend/default.conf:/etc/nginx/conf.d/default.conf
  1. 前端靜態文件

    • ./frontend/dist:/usr/share/nginx/html/dist

    • 將本地?frontend/dist?目錄掛載到容器的 Nginx 靜態文件目錄

    • 這樣前端構建后文件可以直接被 Nginx 服務

  2. Nginx 配置

    • ./frontend/default.conf:/etc/nginx/conf.d/default.conf

    • 使用本地的 Nginx 配置文件覆蓋容器默認配置

    • 這是自定義 Nginx 行為的常見方式

  3. 注釋掉的 SSL 證書

    • 如果需要 HTTPS 支持,可以取消注釋并配置證書路徑

典型工作流程

  1. 前端構建

    • 開發者運行?npm run build?生成?frontend/dist?目錄

  2. 啟動服務

    • 運行?docker-compose up -d?啟動服務

    • Docker 會:

      • 根據 Dockerfile 構建鏡像

      • 創建并啟動容器

      • 設置所有端口映射和卷掛載

  3. 訪問應用

    • 通過?http://服務器IP:18001?訪問應用

    • Nginx 會:

      • 讀取掛載的配置文件

      • 從掛載的?dist?目錄提供靜態文件

配置亮點

  1. 開發-生產一致性

    • 使用相同的 Nginx 配置和部署方式開發和生產環境

  2. 快速更新

    • 修改前端代碼后只需重新構建?dist?目錄

    • 無需重建 Docker 鏡像或重啟容器(Nginx 會自動提供新文件)

  3. 配置與代碼分離

    • Nginx 配置可以獨立修改而不影響應用代碼

這個配置非常適合前端項目的容器化部署,提供了靈活性、可維護性和便捷的開發體驗。

具體聯系

(1)?docker-compose.yml?依賴?Dockerfile?構建鏡像
services:nginx:build: .  # 這里會調用當前目錄下的 Dockerfile 構建鏡像image: hrfusion-fd-nginx:v1.0
  • build: .?表示 Compose 會讀取當前目錄的?Dockerfile?來構建鏡像。

  • 構建后的鏡像會被標記為?hrfusion-fd-nginx:v1.0

(2)?Dockerfile?提供基礎環境,docker-compose.yml?補充運行時配置
  • Dockerfile?中

    • 定義了基礎鏡像(nginx:latest)。

    • 清除了默認配置(rm -rf /etc/nginx/conf.d/*)。

    • 創建了目錄結構(如?/usr/share/nginx/html/dist)。

  • docker-compose.yml?中

    • 通過?volumes?動態掛載了配置文件(default.conf)和前端代碼(dist)。

    • 通過?ports?暴露了端口(18001:80)。

    • 這些配置在容器運行時生效,覆蓋或補充了?Dockerfile?的靜態設置。

總結

下面我將系統性地總結這些啟動方式及其適用場景,并給出如何統一管理的建議:


一、后端啟動方式

1.?直接運行?.py?文件
python main.py  # 或使用模塊方式
python -m uvicorn main:app --reload
  • 適用場景:開發調試、快速驗證

  • 特點

    • 最直接的方式,依賴本地Python環境

    • 需手動安裝所有依賴(pip install -r requirements.txt

2.?通過?.sh?腳本啟動
#!/bin/bash
# run.sh
pip install -r requirements.txt
python main.py
  • 適用場景:標準化本地開發或簡單部署

  • 特點

    • 可封裝復雜命令(如環境變量、參數傳遞)

    • 適合團隊統一開發流程

3.?通過 Docker 啟動
# Dockerfile
FROM python:3.9
COPY . /app
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
docker build -t backend . && docker run -p 8000:8000 backend
  • 適用場景:生產部署、環境隔離

  • 特點

    • 環境一致性高

    • 需提前構建鏡像

4.?通過 Docker Compose 啟動
# docker-compose.yml
services:backend:build: ./backendports:- "8000:8000"
  • 適用場景:多服務協作(如需要同時啟動數據庫)


二、前端啟動方式

1.?開發模式(Node.js 直接運行)
npm run dev  # Vite/Webpack等工具
  • 適用場景:前端開發熱重載

2.?生產構建 + Docker 托管
# 前端Dockerfile
FROM nginx
COPY dist /usr/share/nginx/html
  • 適用場景:生產環境部署

  • 特點

    • 需先執行?npm run build?生成靜態文件

    • 通過Nginx提供高性能靜態資源服務

3.?通過 Docker Compose 與后端聯動
services:frontend:build: ./frontendports:- "80:80"backend:build: ./backendports:- "8000:8000"

三、統一啟動方案

方案1:Makefile 整合多命令
dev:@echo "Starting all services..."cd backend && python main.py & cd frontend && npm run devdocker-up:docker-compose up -d --build
  • 優點:簡單直接,適合開發者本地使用

  • 缺點:進程管理較原始(如用?&?后臺運行)

方案2:Docker Compose 統一管理
version: '3'
services:frontend:build: ./frontendports: ["3000:3000"]volumes:- ./frontend:/app- /app/node_modulesbackend:build: ./backendports: ["8000:8000"]volumes:- ./backend:/codedb:image: postgresenvironment:POSTGRES_PASSWORD: example
  • 優點

    • 一鍵啟動完整環境(前端+后端+數據庫)

    • 環境隔離徹底

  • 缺點

    • 開發時前端熱更新需要配置額外卷(如?node_modules?排除)

方案3:混合模式(開發 vs 生產)
.
├── Makefile           # 開發命令(直接運行.py/npm)
├── docker-compose.yml # 生產環境Docker部署
└── docker-compose.dev.yml # 開發環境(帶熱更新)
  • 開發時

    make dev  # 使用本地Python/Node環境
  • 生產部署

    docker-compose -f docker-compose.prod.yml up -d

四、如何選擇?

場景推薦方案
個人開發調試Makefile + 直接運行.py/npm
團隊統一開發環境Docker Compose + 代碼卷掛載
生產部署Docker Compose(無卷掛載)
需要快速切換多環境混合模式(Makefile + 多Compose文件)

通過靈活組合這些方案,你可以實現從開發到生產的一體化高效工作流!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/914022.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/914022.shtml
英文地址,請注明出處:http://en.pswp.cn/news/914022.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[爬蟲知識] DrissionPage:強大的自動化工具

相關爬蟲實戰案例:[爬蟲實戰] 使用 DrissionPage 自動化采集小紅書筆記 相關爬蟲專欄:JS逆向爬蟲實戰 爬蟲知識點合集 爬蟲實戰案例 逆向知識點合集 前言: 在當今數據驅動的世界里,網絡爬蟲和自動化測試扮演著越來越重要的角…

數據分析師如何構建自己的底層邏輯?

目錄 一、什么是“底層邏輯”? 二、底層邏輯的核心是什么?三句話講清楚 1. 你到底在解決什么問題? 2. 你有沒有一套“框架”來組織你的分析思路? 3. 你能不能用數據說出“結論 因果 建議”? 三、從 BI 視角出發…

殘差連接+層歸一化:Transformer訓練穩定秘訣

什么是:殘差連接+層歸一化 殘差連接 (Residual Connection):防止梯度消失 核心原理 簡單理解:走樓梯時,既可以走樓梯,也可以坐電梯,最后在同一層匯合。 # 殘差連接的數學表示 輸出 = F(輸入) + 輸入 # ↑處理后 ↑原始輸入具體數值例子 處理句子"我愛學習…

公網 IP 不穩定監控實戰:用多點 Ping 策略實現高可達率保障

更多云服務器知識,盡在hostol.com 你有沒有遇到過這種情況:明明服務器的監控系統說一切正常,服務狀態綠油油一片,但用戶那邊卻反饋“時好時壞”、“丟包嚴重”甚至“根本連不上”。你掏出手機連上公網去試試,誒&#…

uniapp類似抖音視頻滑動

最近需求說要做個類似抖音那種視頻的&#xff0c;我二話不說就用了swiper-view組件&#xff0c;但是效果不太理想&#xff0c;后面改用css屬性先放效果圖&#xff1a;<template><view class"video-scroll-container" touchstart"handleTouchStart"…

Umi-OCR 的 Docker(win制作鏡像,Linux(Ubuntu Server 22.04)離線部署)

前置博客&#xff1a;Ubuntu-Server 22.04.4 詳細安裝圖文教程 wget命令在windows終端下不能使用的原因及解決辦法 在 Ubuntu 22.04 LTS 上離線安裝 Docker 手把手教你在Win11下安裝docker Umi-OCR 完整部署流程 第一步&#xff1a;在 Windows 上構建/獲取 Umi-OCR Docker…

AI Agent革命:當大模型學會使用工具、記憶與規劃

以下是針對Lilian Weng的AI Agent綜述文章&#xff08;原文鏈接&#xff09;的深度解析與整理&#xff1a; AI Agent革命&#xff1a;當大模型學會使用工具、記憶與規劃 ——解析LLM驅動的下一代智能體技術架構 一、核心范式轉變 傳統AI模型&#xff08;如ChatGPT&#xff09…

Claude Code:完爆 Cursor 的編程體驗

前言 最近&#xff0c;聽說Claude Code這款代碼輔助編寫產品很強&#xff0c;有人把Cursor比作實習生水平&#xff0c;Claude Code比作高級工程師水平。 起初不以為意&#xff0c;因為特殊原因&#xff0c;Claude 無法直接訪問。然而&#xff0c;有人做了鏡像站&#xff0c;可以…

ModbusTCP通訊

supply服務-ModbusTCP通訊&#xff1a; winForm-HZHControls-Sqllite本地小項目架構補充&#xff1a;

前端面試專欄-算法篇:23. 圖結構與遍歷算法

&#x1f525; 歡迎來到前端面試通關指南專欄&#xff01;從js精講到框架到實戰&#xff0c;漸進系統化學習&#xff0c;堅持解鎖新技能&#xff0c;祝你輕松拿下心儀offer。 前端面試通關指南專欄主頁 前端面試專欄規劃詳情 圖結構與遍歷算法 在計算機科學中&#xff0c;圖&a…

滲透測試之木馬后門實驗

一、實驗背景 根據CNCERT的監測數據顯示&#xff0c;2018年位于美國的1.4萬余臺木馬或僵尸網絡控制服務器&#xff0c;控制了中國境內334萬余臺主機&#xff1b;2018年位于美國的3325個IP地址向中國境內3607個網站植入木馬&#xff0c;根據對控制中國境內主機數量及控制中國境內…

【LeetCode 熱題 100】24. 兩兩交換鏈表中的節點——(解法一)迭代+哨兵

Problem: 24. 兩兩交換鏈表中的節點 題目&#xff1a;給你一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本題&#xff08;即&#xff0c;只能進行節點交換&#xff09;。 文章目錄整體思路完整代碼…

微積分核心考點全解析

一、微積分核心知識框架 1. 極限與連續&#xff08;重點&#xff01;&#xff09; 核心概念&#xff1a; 極限定義&#xff08;ε-δ語言&#xff09;重要極限&#xff1a;lim?x→0sin?xx1limx→0?xsinx?1&#xff0c;lim?x→∞(11x)xelimx→∞?(1x1?)xe連續性判定&am…

TypeScript---泛型

一.簡介TypeScript 就引入了“泛型”&#xff08;generics&#xff09;。泛型的特點就是帶有“類型參數”&#xff08;type parameter&#xff09;。在日常 TypeScript 編程中&#xff0c;我們經常會遇到這樣的場景&#xff1a;函數的參數類型與返回值類型密切相關。此時&#…

手把手一起使用Miniforge3+mamba平替Anaconda(Win10)

Anaconda 開始對企業收費&#xff0c;目前急需平替Anaconda。這里采用Minforgemamba作為替代&#xff0c;可以避免Anaconda追責&#xff0c;并100%兼容原conda倉庫及使用方式&#xff0c;如果各位小伙伴有更好的平替方式&#xff0c;歡迎分享。 Miniforge3安裝 下載并安裝Min…

【Note】Linux Kernel 主題學習之“完整的嵌入式 Linux 環境、構建工具、編譯工具鏈、CPU 架構”

Linux Kernel 主題學習之“完整的嵌入式 Linux 環境、構建工具、編譯工具鏈、CPU 架構” 一、完整的嵌入式 Linux 環境 一個嵌入式 Linux 系統通常包括以下關鍵組件&#xff08;以 Jetson、樹莓派等 ARM 版 SBC 為例&#xff09;&#xff1a; 交叉編譯工具鏈&#xff08;cros…

Lecture #20:Database Logging

Lecture20目錄&#xff1a;崩潰恢復緩沖池管理策略竊取策略強制策略NO-STEAL-FORCE影子分頁執行恢復缺點日志文件預寫日志&#xff08;WAL&#xff09;執行緩沖池策略日志方案檢查點崩潰恢復 恢復算法是一種確保數據庫ACID的技術&#xff0c;數據庫崩潰后&#xff0c; 所有已經…

Kubernetes高級調度1

目錄 一:初始化容器 Initcontainer 1:Initcontainer 的基本概念 2:示例 1--延遲指定時間后啟動 3:示例 2--使用初始化容器修改內核參數 4:示例 3--等待依賴服務啟動 4:pause容器 二&#xff1a;臨時容器 Ephemeral Containers 1.臨時容器的概念 2.臨時容器的使用 三&a…

服務器機柜與網絡機柜各自的優勢

一、服務器機柜優勢服務器機柜設計有強大的承重結構&#xff0c;能承受大量服務器設備堆疊產生的重量&#xff0c;保障設備安全穩定放置&#xff0c;防止因承重不足導致機柜變形甚至設備損壞&#xff0c;同時&#xff0c;服務器在運行的過程中&#xff0c;會產生大量熱量&#…

AI技術通過提示詞工程(Prompt Engineering)正在深度重塑職場生態和行業格局,這種變革不僅體現在效率提升,更在重構人機協作模式。

AI技術通過提示詞工程&#xff08;Prompt Engineering&#xff09;正在深度重塑職場生態和行業格局&#xff0c;這種變革不僅體現在效率提升&#xff0c;更在重構人機協作模式。以下是關鍵影響維度及未來趨勢分析&#xff1a;一、職場效率革命&#xff08;效率提升300%場景&…