This commit is contained in:
dxin
2025-10-16 11:52:59 +08:00
parent aa16443f1d
commit 82a4aa0e14
8 changed files with 315 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
# 使用 Python 3.12.9 官方镜像
FROM python:3.12.9-slim
# 系统优化与依赖和编译环境
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
gcc \
autoconf \
make \
libssl-dev \
libffi-dev \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
# 设置时区
ENV TZ=Asia/Shanghai
# 创建应用目录
WORKDIR /app
# 复制依赖清单
COPY requirements.txt .
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt
# 复制项目代码
COPY . .
# 创建日志目录(即使宿主机未挂载也能运行)
RUN mkdir -p /app/logs
RUN chmod +x /app/start.sh
# 启动环境(默认 prod
ENV APP_ENV=prod
# Entrypoint 会根据 APP_ENV 动态决定配置文件
# 这里不直接启动 gunicorn而是用 start.sh 控制日志等
ENTRYPOINT ["bash", "start.sh"]
#-----------------------------------------------
# 基于你自己的基础镜像
FROM uswccr.ccs.tencentyun.com/lessie/python:3.12.9-base
LABEL maintainer="lessie <ops@lessie.ai>"
ENV TZ=Asia/Shanghai
WORKDIR /app
# 拷贝依赖文件并安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 拷贝项目代码
COPY . .
# 创建日志目录
RUN mkdir -p /app/logs && chmod +x /app/start.sh
# 环境变量(可在 compose 覆盖)
ENV APP_ENV=local
# 启动命令
ENTRYPOINT ["bash", "start.sh"]
#-----------------------------------------------
# docker build -t lessie/lessie-sourcing-agents:v0.0.1 .
# docker images | grep lessie
# docker tag lessie/lessie-sourcing-agents:v0.0.1 uswccr.ccs.tencentyun.com/lessie/lessie-sourcing-agents:v0.0.1
# docker push uswccr.ccs.tencentyun.com/lessie/lessie-sourcing-agents:v0.0.1
# --------------------------
# Stage 1: Builder
# --------------------------
FROM uswccr.ccs.tencentyun.com/lessie/python:3.12.9-base AS builder
LABEL maintainer="lessie <ops@lessie.ai>"
ENV TZ=Asia/Shanghai
WORKDIR /app
# 拷贝依赖文件并安装依赖到 /app/deps
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/app/deps -r requirements.txt
# --------------------------
# Stage 2: Runtime
# --------------------------
# 最终运行镜像,用 slim 最小化
FROM python:3.12.9-slim
ENV TZ=Asia/Shanghai
WORKDIR /app
# 拷贝已安装的依赖
COPY --from=builder /app/deps /usr/local
# 拷贝项目代码
COPY . .
# 创建日志目录
RUN mkdir -p /app/logs && chmod +x /app/start.sh
# 环境变量(可在 docker-compose 覆盖)
ENV APP_ENV=local
# 启动命令
ENTRYPOINT ["bash", "start.sh"]

View File

@@ -0,0 +1,45 @@
# 基础镜像:官方 Python 3.12.9
FROM python:3.12.9-slim
LABEL maintainer="lessie" \
description="Python 3.12.9 base image with optimized system tools and build environment" \
version="3.12.9"
# 环境变量
ENV TZ=Asia/Shanghai \
LANG=C.UTF-8 \
DEBIAN_FRONTEND=noninteractive \
PATH="/usr/local/bin:$PATH"
# 系统优化与常用工具安装
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential \
gcc \
g++ \
make \
curl \
wget \
vim \
git \
tzdata \
ca-certificates \
net-tools \
iputils-ping \
libssl-dev \
libffi-dev \
libpq-dev \
libxml2-dev \
libxslt-dev \
zlib1g-dev \
libjpeg-dev \
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# pip 优化:禁用缓存,升级工具链
RUN pip install --no-cache-dir --upgrade pip setuptools wheel
WORKDIR /app
CMD ["python3"]

View File

@@ -0,0 +1,37 @@
version: "3.9"
networks:
lessie_network:
name: lessie_network
driver: bridge
ipam:
config:
- subnet: 10.17.1.0/24
services:
sourcing-agents:
container_name: lessie-sourcing-agents-s2
image: uswccr.ccs.tencentyun.com/lessie/lessie-sourcing-agents:latest
restart: always
environment:
APP_ENV: s2
TZ: Asia/Shanghai
ports:
- "7001:7001"
volumes:
# 日志映射
- ./logs:/app/logs
# 凭证映射
- /root/.aws:/root/.aws
- /root/.google:/root/.google
# 使用固定网络
networks:
- lessie_network
command: ["/bin/bash", "/app/start.sh"]

View File

@@ -0,0 +1,47 @@
FROM python:3.12-slim AS builder
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
UV_LINK_MODE=copy \
UV_VERSION=0.4.17 \
UV_PROJECT_ENVIRONMENT=/opt/venv
WORKDIR /app
# Install build prerequisites, fetch uv, then remove leftover apt metadata.
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates build-essential && \
rm -rf /var/lib/apt/lists/*
RUN curl -LsSf https://astral.sh/uv/install.sh | sh -s -- --version "${UV_VERSION}"
# Pre-copy manifests for better layer caching.
COPY pyproject.toml uv.lock requirements.txt ./
RUN /root/.local/bin/uv sync --frozen --no-dev --python /usr/local/bin/python && \
/root/.local/bin/uv cache prune --ci
FROM python:3.12-slim AS runtime
ARG APP_PORT=8000
ENV APP_ENV=local \
APP_PORT=${APP_PORT}
WORKDIR /app
# Runtime dependencies required by packages like faiss-cpu.
RUN apt-get update && apt-get install -y --no-install-recommends libgomp1 && \
rm -rf /var/lib/apt/lists/*
# Bring in the pre-built virtual environment from the builder stage.
COPY --from=builder /opt/venv /opt/venv
# Ship only the application sources in the runtime image.
COPY . .
ENV PATH="/opt/venv/bin:${PATH}" \
VIRTUAL_ENV="/opt/venv"
EXPOSE ${APP_PORT}
CMD ["sh", "-c", "python server.py --host ${HOST:-0.0.0.0} --port ${APP_PORT:-8000}"]

View File

@@ -0,0 +1,75 @@
# chmod +x start.sh
#-----------------------------------------
#!/usr/bin/env bash
set -e
# 打印启动环境
echo "[*] Starting app with APP_ENV=${APP_ENV}"
# 日志路径(宿主机会挂载)
LOG_DIR="/app/logs"
mkdir -p "$LOG_DIR"
# 动态生成日志文件名
LOGFILE="${LOG_DIR}/lessie_sourcing_agents_$(date +'%Y%m%d_%H%M%S').log"
LATEST_LOG="${LOG_DIR}/lessie_sourcing_agents_latest.log"
# 启动命令
echo "[*] Launching Gunicorn..."
nohup env APP_ENV=${APP_ENV} \
gunicorn -w 4 -k uvicorn.workers.UvicornWorker \
-b 0.0.0.0:7001 --timeout 300 dialogue.app:app \
--max-requests 500 --max-requests-jitter 50 \
> "$LOGFILE" 2>&1 &
# 建立软链方便查看最新日志
ln -sf "$LOGFILE" "$LATEST_LOG"
echo "[*] App started. Logs: $LATEST_LOG"
# 前台挂起(防止容器退出)
tail -F "$LOGFILE"
#-----------------------------------------
#!/bin/bash
#脚本出错立即退出,防止容器假活
set -e
# 进入项目目录
cd /app
# 日志目录
LOG_DIR="/app/logs"
mkdir -p "$LOG_DIR"
# 日志文件(同时软链一个 latest.log 方便定位)
LOG_FILE="${LOG_DIR}/lessie_sourcing_agents_$(date +'%Y%m%d_%H%M%S').log"
ln -sf "$LOG_FILE" "${LOG_DIR}/lessie_sourcing_agents_latest.log"
# 环境变量(默认 prod可通过 docker run -e APP_ENV=s1 覆盖)
APP_ENV="${APP_ENV:-prod}"
echo "[INFO] Starting app in environment: ${APP_ENV}"
# Python 环境检查
echo "[INFO] Python version:"
python3 --version
# 启动 Gunicorn
# 输出到 stdout 的同时 tee 一份到日志文件
echo "[INFO] Launching Gunicorn..."
exec gunicorn -w ${cfg_gunicornWorkers:-4} \
-k uvicorn.workers.UvicornWorker \
-b 0.0.0.0:${cfg_port:-7001} \
--timeout 300 \
--max-requests 500 \
--max-requests-jitter 50 \
--access-logfile - \
--error-logfile - \
dialogue.app:app \
2>&1 | tee -a "$LOG_FILE"

View File

@@ -0,0 +1,23 @@
# 构建Docker镜像 -t 标志用于指定镜像名称和标签 | . 表示当前目录作为构建上下文(即 Dockerfile 和代码所在目录)
docker build -t uswccr.ccs.tencentyun.com/lessie/lessie-sourcing-agents:v0.1 .
# 查看镜像
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# myapp latest 9f4e919c2146 4 minutes ago 1.55GB
docker login uswccr.ccs.tencentyun.com -u 100038894437
docker push uswccr.ccs.tencentyun.com/lessie/lessie-sourcing-agents:v0.1
# 登录
docker login uswccr.ccs.tencentyun.com -u 100038894437 回车后输出密码: h8H1o6Fd!HLXn
# 打 tag
docker tag lessie/python:3.12.9-base uswccr.ccs.tencentyun.com/lessie/python:3.12.9-base
# 推送
docker push uswccr.ccs.tencentyun.com/lessie/python:3.12.9-base

View File

@@ -0,0 +1,19 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5akNDQWJLZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQ0FYRFRJMU1UQXhNVEE1TWpFd09Wb1lEekl3TlRVeE1EQTBNRGt5TVRBNVdqQVZNUk13RVFZRApWUVFERXdwcmRXSmxjbTVsZEdWek1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCnpFNHZKbXFhLytkWnpDV01QN2RYb3RzREM2RU9Nb2VSSjFSZ3ZvS1F6cFpTLzBpakFqeGEwWHZoRGs5eS91Zi8KWUk3Ukw2WVhxWVQ3c1YyanN5U21JVFVRVXhscGptUHBPb0lQdmltMnRaelBwakI5RDF5d0llWVRzbU11K3loMwpBL1RpU1pQVnVQMFpKNHJCdyt1bU1HQ25FUjJXNVc0WmpuWGV2WndCOWk2WW5oc3FNWVA4azJ6N3RhdnJRSWpOClFuSXlGRUNac3ZMbHlRRlZnR3EyWU9WRERkRUNORXptQjU4Z3NQeFZaOGFTdTZjTVA1MzN4cTNObzJwTWN6cEUKSnRvTEFqZFNCYkU4ZFpBUUFtRXB5WkEwUzJXZnAxK0NYekg0UEhHT2pjVVI0eVQ1T0NQeE5nRGxsenFNVnExOApSQlkvNGI0U3lVbmxHV0luN2tNdWhRSURBUUFCb3lNd0lUQU9CZ05WSFE4QkFmOEVCQU1DQXBRd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFpM3lDWk9zbG1ScVh4eDRkY1BJaXp2K1QKWmRiT05hbHo5S3R2QmlFZHdVKytLRWRaZm5aWlpFMWFPbitxckxPSHpGcGdvblp1eTRKNFlodWRHakFYVE1McwpLWC9WUVZLcndYUVVUMXNybnZVR3FpV21teVZsd1dpUi8yT1A5aHdUVjRaYkVxMzZPMlAvOVJNUXVaYUZDbXZYCm5tcDNYUE5keVVSaHcyeWxVUWJQRGRFKyt0a1B4ZENPOXZlV3VJRUJpQXdaeC9zOFZCZVA2eWNXSjQxdmgrUVMKN2VUbXU1YVFwdllUcWNqMTFycTA1NnMzQlhYUU02TnAvV2tkVStFTHpzT2gwZzhXRU16Q0gvL1lNdFdVWGMyOQo1Z3AzcURNWW1LUW1JSHBIWEtHcEN2OEcvNmFhdWVvWGJnamtFVTRWVkhyWmg3Q1JLZGxsbkhjWU9OemY3UT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
server: https://lb-r7qx8b82-x9ivq4pstdm8f1zc.clb.usw-tencentclb.cloud
name: cls-pl1yhr34
contexts:
- context:
cluster: cls-pl1yhr34
user: "100038894437"
name: cls-pl1yhr34-100038894437-context-default
current-context: cls-pl1yhr34-100038894437-context-default
kind: Config
preferences: {}
users:
- name: "100038894437"
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREakNDQWZhZ0F3SUJBZ0lJWXNKUHJZc2EwbHN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWdGdzB5TlRFd01UTXdOek01TVRCYUdBOHlNRFUxTVRBeE16QTNNemt4TUZvdwpOakVTTUJBR0ExVUVDaE1KZEd0bE9uVnpaWEp6TVNBd0hnWURWUVFERXhjeE1EQXdNemc0T1RRME16Y3RNVGMyCk1ETTBNVEUxTURDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTlMvSEdiVHBvMXUKaXdGSXVjSVlNQ2RVNnAzN3hwYmdwNDR4Vld3MG1lUU4zdkRZdlBWcXZNdmVWK0dzZWd1aWVCZEZNd082OGJqUQpGTFlKQnZpVmc5RXFYMWZkUVJ5ZCtzQUh5VXZQZmNaK3UrMG1qT1RqNHdaRC9VVlI0Q3FRWnVrc0Zsamp0aERJClhOeENYVEtOU2xmdEJiQXJENTVlenN4WmdyRnNDWnd4WTRZSDlrbEYvRllNWUVhZHVGQWZETzJUcHVDLzUzVnAKNVFyaFpZTzczK3VaZjR4QnpSZmwrTXYxUm9XOWF4RzN0M3dTYklRclorUU9UbUx0ZnFTSnN0QmZGT0lHdW15VAoyemNKVEl3MjloNXZSNnk0VHhXSWJMRGtrTkxJWGdONDBOZmxBcS9yNnVlalRjVmwwVmcrRHk1dy9HYzU4MXV6CmdBZjE2alJCRWZNQ0F3RUFBYU0vTUQwd0RnWURWUjBQQVFIL0JBUURBZ0tFTUIwR0ExVWRKUVFXTUJRR0NDc0cKQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFNQmdOVkhSTUJBZjhFQWpBQU1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQgpBUUEwZmVYcHNqNGo4cGl2WURhTVlpdXpNUytLQStNL0hJb3krNk1SalFrTUtVNUU5azdmMlk1Z2hJeXhzR3AwCjFEOWlRZ1JYU2E5K2xGS1hTdHVBeWt3WDYzeUlyVDhKbDc3S2FXSUs0MWdCVk1jaTcycFAyWklFOU40U05oVksKSzVaaWRRcGlIWWxFeG9WaEthSWxxS3N1WkZsbGQ5cjV3WGtoaWd6ZEhiOGpXY2QzaWVHSGh6U0liUElwN25aYgppeUpyOHN6c2tnSk9ucmFtMFQzNWg3K29tSm5YTFJCbGdMNVRFRHFjZ2ZBd01oOG5oVkNPRDJsM1Nnam5vOGl1CkcyclJnSjE4MlUvQ3BYSXY2VDNDeGVyazJTUFplZEZndE9yY3I2eHBjcGpWTGViQVpMdVNlcDVWS0JYRExwdzUKd2JyNDJYNFRkaXZCbTBFYldlVHUyUEZvCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMUw4Y1p0T21qVzZMQVVpNXdoZ3dKMVRxbmZ2R2x1Q25qakZWYkRTWjVBM2U4Tmk4CjlXcTh5OTVYNGF4NkM2SjRGMFV6QTdyeHVOQVV0Z2tHK0pXRDBTcGZWOTFCSEozNndBZkpTODk5eG42NzdTYU0KNU9QakJrUDlSVkhnS3BCbTZTd1dXT08yRU1oYzNFSmRNbzFLViswRnNDc1BubDdPekZtQ3NXd0puREZqaGdmMgpTVVg4Vmd4Z1JwMjRVQjhNN1pPbTRML25kV25sQ3VGbGc3dmY2NWwvakVITkYrWDR5L1ZHaGIxckViZTNmQkpzCmhDdG41QTVPWXUxK3BJbXkwRjhVNGdhNmJKUGJOd2xNakRiMkhtOUhyTGhQRlloc3NPU1Ewc2hlQTNqUTErVUMKcit2cTU2Tk54V1hSV0Q0UExuRDhaem56VzdPQUIvWHFORUVSOHdJREFRQUJBb0lCQVFDcURXekZZSTV6NUpWbAozRnpuSVhCMEwvTXRmdEFaVDg5KzRENDR0TDhCeEhpY3FaSTQxUzIrQTZiWmM0VkdnWUplajJpY3BiU0xsbi9ICmxlV2xrOVYrdnREaEtiRGZFQVFidE4yWkpHeVQyaithNjBLWnZ2SjcwcUxDNHhRODBab0E3Y1diSGNFdEh3cmkKNElVZ1lFRzVrSE1JZ3hNRDh5SjN3MkN0TXY5bmdiakhLUVFBZHFXRFMxS0hWa0lxTnhIcDlJcStnT2x4WmdrVgpNcC81TzczbEZudFJLVTVSdXNJN3hldE4rVVlkakhpZ2NINlBRaU5NaTdsOU5YSUhPMFdLekNueEJ6VEM1UzVtCnFYTjZ2Zkd6WGRpMlVlRGNYcldsSWtTN0x4a2VLTU1JbDdndkF2dmhNTFJPa3hPSk5BODYvOHhEZWlrWHFDQW8KT0ptcXdPSlJBb0dCQU5qcFJFc3BPenNIdCt1Q0dMQjQzbTRJRVc5cE5GTTBKa0swL2JjOEFhcE9aWnYyQmtWSwpiQzB1ajJMdzdjKzhwMDRGQ0ZyY3RyTE5WKzhvSnNPZzhwcEdGUFFZVFB1SVc3WTUzTGI4WGxoaW1uY3hWUjUrCmI3TXRxZWhVQTlYOUNLMGw5V1FpcmhqbU9abDlJZEZ0MExzOW83RGsvbitEUjRpeldndEtYMHZKQW9HQkFQc1YKdDB0R3NiWUt2clUyZW1zeHFLbDhmZS90Y0RqNG1uOFBqY0R3WlNOQ2ZZU1QyLzZGRWphQ0dCdlplcEhJdm1zMQp4aldrZGpIMTBFNTdoeWtmU3VWR3ZVeCsxVXRMM3VKSFdtSXVIYTl6dTNYMkVmQjgwNlM0T2xuWklkSVpkVnVSCjhWWHl6TlM2QnZVS3hGNDdQNTVmWmFtRVBscEE3VXM0M2YyeHhkWGJBb0dBS1NNTUphajdKN1hPQnFjVW9aczYKcStseHpReEp0U0hsdzY3cGt5K1pMVUJTK3VJTXpHVlI0THU4eThuZmdBOUtOM3l5MmZDVDRaTWFBeXc5TmNxMwpWOVRFc29wTlIwTFVDZG90WnJLei9kVXRjRDkxNGlPZWNYL09nbFkwcUFlbDlwaUZVbWxWVlRtTVlQU2ZUa1dpCldYQldNLzBwMnVyOXpRb2VvSmVKUFNrQ2dZQS80WnlLMkdlcWF6MXVHWGc0QWFCcHpyU3o4SE1XNjVsVExuL2cKVU1sS21VWWFEd3h2eXllQkdzUkxnWjkvcTlWV3JZM0taQmQyU3BZL0FZcTMyYkJTZVJiOGVXQ0hFYnlaVVpJYgpYS1JNMldNZWRnYkdhdHZtRXNFMXp0cWQrOEF5RmdXUzJuMW11aFcvRG9nN2VWT01WYlVsMWZHUFFPbWVzODgzCkZwM0E5UUtCZ1FDbERKUlN4NFFvNzlmTG9rS2Z5eWVKQzJJRnJVaVlPRTYzdTRsd0U1K1pkTmNqUWxtY2p4ZDAKNlI1a29iaXc4bUhVQkdOSk9XQzBWeC9ZVnZnVEhVMm9KdTVCOUQ5SEhHa1NZb0ljR2x4T2ZLWUJLdXpNcWJzZgpnTjhIcUlnMjlCWTU2MkFYci9MN0sxT3ZLWWtERzJjQ0dLenR4SzNUTldnYWFMaGU1bkdPZVE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=