2-2同步
This commit is contained in:
@@ -1,18 +1,45 @@
|
||||
# ==================== 安装依赖阶段(构建镜像)====================
|
||||
# 基础镜像:3.12-slim轻量化,小镜像
|
||||
FROM python:3.12-slim as builder
|
||||
FROM python:3.12-slim AS builder
|
||||
|
||||
# 构建阶段:隔离构建依赖,最终镜像仅保留运行时,镜像瘦身
|
||||
WORKDIR /app
|
||||
|
||||
# 默认测试环境,可通过env修改 development/production
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
UV_SYSTEM_PYTHON=1 \
|
||||
UV_HTTP_TIMEOUT=600 \
|
||||
UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
|
||||
UV_EXTRA_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
|
||||
UV_EXTRA_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
# 安装构建依赖
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
g++ \
|
||||
build-essential \
|
||||
python3-dev \
|
||||
ca-certificates \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get clean
|
||||
|
||||
# 复制uv和依赖文件
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
COPY pyproject.toml uv.lock ./
|
||||
|
||||
# 安装依赖:--frozen锁定版本,--no-dev默认安装生产依赖
|
||||
# 依赖安装到venv,保证隔离性,同时支持uv run调用
|
||||
RUN uv sync --frozen --no-dev
|
||||
|
||||
|
||||
# ==================== 运行时阶段(最终镜像)====================
|
||||
FROM python:3.12-slim AS runtime
|
||||
|
||||
# 默认测试环境,可通过 env 修改
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
# 可外部覆盖的核心启动参数
|
||||
APP_ENV=test \
|
||||
ENV=test \
|
||||
APP_PORT=8031 \
|
||||
APP_HOST=0.0.0.0 \
|
||||
# 是否开启热重载:默认关闭(生产/测试环境不需要),开发环境可设为1
|
||||
@@ -20,32 +47,6 @@ ENV PYTHONUNBUFFERED=1 \
|
||||
# 日志配置文件:默认使用json配置,可设为空关闭
|
||||
APP_LOG_CONFIG=logging_config.json
|
||||
|
||||
# 安装构建依赖(仅builder阶段需要,运行时镜像会剔除)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
g++ \
|
||||
build-essential \
|
||||
python3-dev \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
# 清理apt缓存,进一步减小构建层体积
|
||||
&& apt-get clean
|
||||
|
||||
# 复制uv和依赖文件(**核心缓存层**:仅pyproject.toml/uv.lock变更时才重新安装依赖)
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
||||
COPY pyproject.toml uv.lock ./
|
||||
|
||||
# 安装依赖:--frozen锁定版本,--no-dev默认安装生产依赖(开发环境可通过uv sync --dev覆盖)
|
||||
# 依赖安装到venv,保证隔离性,同时支持uv run调用
|
||||
RUN uv sync --frozen --no-dev
|
||||
|
||||
# ==================== 运行时阶段(最终镜像)====================
|
||||
FROM python:3.12-slim as runtime
|
||||
|
||||
# 继承构建阶段的环境变量(可被外部传参覆盖)
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
UV_SYSTEM_PYTHON=1
|
||||
|
||||
# 设置工作目录,与构建阶段一致
|
||||
WORKDIR /app
|
||||
|
||||
@@ -62,9 +63,5 @@ EXPOSE ${APP_PORT}
|
||||
|
||||
# 启动脚本:用shell脚本解析环境变量,动态生成启动命令
|
||||
CMD ["/bin/sh", "-c", \
|
||||
"if [ $APP_RELOAD -eq 1 ]; then \
|
||||
uv run uvicorn app.main:app --host $APP_HOST --port $APP_PORT --reload ${APP_LOG_CONFIG:+-log-config $APP_LOG_CONFIG}; \
|
||||
else \
|
||||
uv run uvicorn app.main:app --host $APP_HOST --port $APP_PORT ${APP_LOG_CONFIG:+-log-config $APP_LOG_CONFIG}; \
|
||||
fi" \
|
||||
"exec uv run uvicorn app.main:app --host ${APP_HOST} --port ${APP_PORT} --log-config logging_config.json" \
|
||||
]
|
||||
@@ -1,10 +1,54 @@
|
||||
# 使用 Nginx 官方轻量镜像
|
||||
FROM nginx:1.25-alpine
|
||||
# # 使用 Nginx 官方轻量镜像
|
||||
# FROM nginx:1.25-alpine
|
||||
|
||||
# 拷贝前端构建产物
|
||||
COPY dist/ /usr/share/nginx/html/
|
||||
# # 拷贝前端构建产物
|
||||
# COPY dist/ /usr/share/nginx/html/
|
||||
|
||||
# 暴露端口
|
||||
# # 暴露端口
|
||||
# EXPOSE 80
|
||||
|
||||
# CMD ["nginx", "-g", "daemon off;"]
|
||||
|
||||
|
||||
|
||||
# 第一阶段:构建阶段 - 使用指定node20.15.0版本,安装pnpm
|
||||
FROM node:20.15.0-alpine AS builder
|
||||
|
||||
# 设定工作目录(容器内的项目目录)
|
||||
WORKDIR /app
|
||||
|
||||
# 配置pnpm源(可选,加速国内安装)
|
||||
ENV PNPM_REGISTRY=https://registry.npmmirror.com/
|
||||
# 全局安装pnpm(node20+推荐corepack管理pnpm,更适配)
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
|
||||
# 复制包管理文件(先复制lock文件,利用docker层缓存,避免代码变动重复装包)
|
||||
COPY package.json pnpm-lock.yaml* ./
|
||||
|
||||
# 安装项目依赖(--frozen-lockfile 锁定依赖版本,保证构建一致性)
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# 复制整个项目代码到容器
|
||||
COPY . .
|
||||
|
||||
# 构建参数:指定构建环境(默认im,可在build时覆盖为test/im/prod等)
|
||||
ARG BUILD_ENV=im
|
||||
# 执行对应环境的构建命令(拼接为pnpm build:xxx)
|
||||
RUN pnpm build:${BUILD_ENV}
|
||||
|
||||
RUN mv /app/dist/main/index.html /app/dist/
|
||||
|
||||
|
||||
# 第二阶段:运行阶段 - 使用官方Nginx稳定版,仅保留dist目录,减小镜像体积
|
||||
FROM nginx:stable-alpine
|
||||
|
||||
# 暴露Nginx默认端口(前端项目常规端口)
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
# 可选:替换Nginx默认配置(解决前端路由刷新404、开启gzip压缩,优化静态资源)
|
||||
# COPY ./nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# 从构建阶段(builder)复制构建后的dist目录到Nginx的静态资源根目录
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
# Nginx镜像默认会启动nginx,无需额外CMD/ENTRYPOINT
|
||||
@@ -38,7 +38,7 @@ pipeline {
|
||||
)
|
||||
choice(
|
||||
name: 'BUILD_ENV',
|
||||
choices: ['im', 's2', 'prod'],
|
||||
choices: ['im', 'prod'],
|
||||
description: '选择构建的环境配置, 默认为 pnpm build:im 构建'
|
||||
)
|
||||
string(
|
||||
@@ -97,6 +97,8 @@ pipeline {
|
||||
stage('获取信息') {
|
||||
steps {
|
||||
script {
|
||||
def cause = currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause')
|
||||
env.ACTUAL_USER = cause ? cause.userName[0] : "系统/自动触发"
|
||||
// 获取分支名
|
||||
env.Code_branch = "${params.Code_branch}"
|
||||
// 获取最近一次提交的哈希值(短格式,前8位)
|
||||
@@ -170,23 +172,6 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('pnpm i&b') {
|
||||
steps {
|
||||
script {
|
||||
def buildEnv = params.BUILD_ENV // 获取参数
|
||||
sh """
|
||||
export PATH="/data/nvm/versions/node/v20.15.0/bin:$PATH"
|
||||
echo "开始安装依赖包"
|
||||
cd ${WORKSPACE}/ && rm -rf node_modules && pnpm install
|
||||
echo "开始构建"
|
||||
pnpm build:${buildEnv}
|
||||
mv dist/main/index.html dist/
|
||||
chmod -R 755 dist/
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('登录容器') {
|
||||
steps {
|
||||
withCredentials([usernamePassword(
|
||||
@@ -206,7 +191,7 @@ pipeline {
|
||||
script {
|
||||
// 构建镜像,添加标签信息
|
||||
sh """
|
||||
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} \
|
||||
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} --build-arg BUILD_ENV=${params.BUILD_ENV} \
|
||||
--label "git-branch='${Code_branch}'" \
|
||||
--label "git-commit='${GIT_COMMIT_SHORT}'" \
|
||||
--label "git-author='${GIT_AUTHOR}'" \
|
||||
|
||||
@@ -16,7 +16,7 @@ pipeline {
|
||||
name: 'IMAGE_NAME',
|
||||
description: 'sit 仓库镜像 (除非输入 CUSTOM_IMAGE, 否则使用这里的)',
|
||||
registry: 'https://uswccr.ccs.tencentyun.com',
|
||||
image: 'lessiesit/lessie-review-service',
|
||||
image: 'lessiesit/lessie-email',
|
||||
credentialId: 'dxin_img_hub_auth',
|
||||
filter: '.*',
|
||||
defaultTag: '',
|
||||
@@ -26,7 +26,7 @@ pipeline {
|
||||
string(
|
||||
name: 'CUSTOM_IMAGE',
|
||||
defaultValue: '',
|
||||
description: '手输完整镜像<registry>/<namespace>/<repo>:<tag>,例如: uswccr.ccs.tencentyun.com/lessiesit/lessie-sourcing-agents:v0.0.1 (填充后,则忽略镜像仓库选择)'
|
||||
description: '手输完整镜像<registry>/<namespace>/<repo>:<tag>,例如: uswccr.ccs.tencentyun.com/lessiesit/lessie-email:v0.0.1 (填充后,则忽略镜像仓库选择)'
|
||||
)
|
||||
booleanParam(
|
||||
name: 'ROLLBACK_VERSION',
|
||||
@@ -42,11 +42,11 @@ pipeline {
|
||||
environment {
|
||||
LARK_ROBOT = "4b8d66d0-c0f0-4587-b0e5-cff772cb3046" // 飞书机器人ID,用于发送部署通知
|
||||
KUBECONFIG = credentials('k8s-test-config-admin') // k8s 凭证 ID, Jenkins 中配置的凭证名称
|
||||
Deployment_yaml = "${WORKSPACE}/lessie-ai/sit/s1/lessie-review-service.yaml"
|
||||
Deployment_name = "sit-lessie-review-service"
|
||||
Deployment_yaml = "${WORKSPACE}/lessie-ai/sit/s1/lessie-email.yaml"
|
||||
Deployment_name = "s1-lessie-email"
|
||||
K8s_namespace = "sit"
|
||||
Pod_container_name = "lessie-review-service"
|
||||
Pod_environment = "sit"
|
||||
Pod_container_name = "lessie-email"
|
||||
Pod_environment = "s1"
|
||||
}
|
||||
stages {
|
||||
stage('回滚上版') {
|
||||
@@ -86,7 +86,7 @@ pipeline {
|
||||
def matcher = (customImage =~ imageRegex)
|
||||
if (!matcher.matches()) {
|
||||
error "CUSTOM_IMAGE 格式不正确,必须是 registry/namespace/repository:tag 格式\n" +
|
||||
"示例: uswccr.ccs.tencentyun.com/lessiesit/lessie-sourcing-agents:v1.0.0\n" +
|
||||
"示例: uswccr.ccs.tencentyun.com/lessie-ai-web:v1.0.0\n" +
|
||||
"当前输入: ${customImage}"
|
||||
}
|
||||
|
||||
@@ -188,21 +188,25 @@ pipeline {
|
||||
sh """
|
||||
echo "--- Deployment 状态 ---"
|
||||
kubectl describe deployment ${Deployment_name} -n ${K8s_namespace} || true
|
||||
echo " "
|
||||
|
||||
echo '--- Pod 列表 ---'
|
||||
kubectl get pods -n ${K8s_namespace} -l "app=${Pod_container_name},environment=${Pod_environment}" -o wide || true
|
||||
echo " "
|
||||
|
||||
echo "--- Pod 描述 (describe) ---"
|
||||
for pod in \$(kubectl get pods -n ${K8s_namespace} -l "app=${Pod_container_name},environment=${Pod_environment}" -o jsonpath='{.items[*].metadata.name}'); do
|
||||
echo "-- Pod 描述 \$pod --"
|
||||
kubectl describe pod \$pod -n ${K8s_namespace} || true
|
||||
done
|
||||
echo " "
|
||||
|
||||
echo "--- 最近 200 行 Pod 日志 ---"
|
||||
for pod in \$(kubectl get pods -n ${K8s_namespace} -l "app=${Pod_container_name},environment=${Pod_environment}" -o jsonpath='{.items[*].metadata.name}'); do
|
||||
echo "-- logs \$pod --"
|
||||
kubectl logs \$pod -n ${K8s_namespace} --tail=200 || true
|
||||
done
|
||||
echo " "
|
||||
"""
|
||||
error("=== Deployment 发布失败,请检查以上输出定位问题 ===")
|
||||
}
|
||||
Reference in New Issue
Block a user