Repository navigation
Expand file tree
/
Copy pathDockerfile.python
More file actions
123 lines (98 loc) · 4.41 KB
/
Copy pathDockerfile.python
File metadata and controls
123 lines (98 loc) · 4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 共用镜像:api / worker / tgbot / migrate / bootstrap 共用本镜像,
# 具体启动命令与 working_dir 由 docker-compose 提供。
ARG PYTHON_BASE
FROM ${PYTHON_BASE} AS builder
ARG UV_VERSION=0.11.14
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1 \
UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir "uv==${UV_VERSION}"
WORKDIR /app
ENV TIKTOKEN_CACHE_DIR=/app/.cache/tiktoken
COPY pyproject.toml uv.lock ./
COPY packages/core/pyproject.toml packages/core/pyproject.toml
COPY apps/api/pyproject.toml apps/api/pyproject.toml
COPY apps/worker/pyproject.toml apps/worker/pyproject.toml
COPY apps/tgbot/pyproject.toml apps/tgbot/pyproject.toml
COPY image-job/pyproject.toml image-job/pyproject.toml
COPY image-job/README.md image-job/README.md
# hatchling editable 构建需要 wheel target 目录存在;先放占位 __init__.py
# 让 uv sync --all-packages 能完成依赖解析与 .venv 物化,随后再拷完整源码。
RUN mkdir -p packages/core/lumen_core apps/api/app apps/worker/app apps/tgbot/app \
image-job/image_job \
&& touch packages/core/lumen_core/__init__.py \
apps/api/app/__init__.py \
apps/worker/app/__init__.py \
apps/tgbot/app/__init__.py \
image-job/image_job/__init__.py
# Resolve the SDK's hash-checked vocabulary during the build, never on a live
# request. A stalled download fails the build rather than hanging indefinitely.
RUN uv sync --frozen --no-dev --all-packages \
&& timeout 120 .venv/bin/python -c 'import tiktoken; tiktoken.get_encoding("o200k_base")'
COPY packages/ packages/
COPY apps/api/ apps/api/
COPY apps/worker/ apps/worker/
COPY apps/tgbot/ apps/tgbot/
COPY apps/agent-runtime/ apps/agent-runtime/
COPY image-job/ image-job/
# Release-time files: 打包到 image 让 update.sh 能在 host 不是 git repo 时用
# `docker create + docker cp` 从 image 提取出来同步到 host release dir。
# 这样无论 host 上 update.sh 多老,只要拉到新 image 就能自愈到新代码。
COPY docker-compose.yml docker-compose.dev.yml docker-compose.bluegreen.yml docker-compose.public-dns.yml VERSION ./
COPY deploy/ deploy/
COPY scripts/ scripts/
FROM ${PYTHON_BASE} AS runtime
ARG LUMEN_VERSION=0.0.0
ARG LUMEN_GIT_SHA=unknown
ARG LUMEN_BUILD_TIME=1970-01-01T00:00:00Z
ARG LUMEN_APP_UID=10001
ARG LUMEN_APP_GID=10001
LABEL org.opencontainers.image.source="https://github.com/cyeinfpro/Lumen" \
org.opencontainers.image.version="${LUMEN_VERSION}" \
org.opencontainers.image.revision="${LUMEN_GIT_SHA}" \
org.opencontainers.image.created="${LUMEN_BUILD_TIME}"
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH=/app/.venv/bin:$PATH \
LUMEN_VERSION=${LUMEN_VERSION}
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
ca-certificates \
openssh-client \
sshpass \
ffmpeg \
libvips42 \
libpq5 \
&& rm -rf /var/lib/apt/lists/*
# Trade-off:LUMEN_APP_UID/GID 在 build 时烙进镜像 → 同一镜像不能跨主机共用
# (host 上 storage 目录的 ownership 必须跟 build-arg 对齐)。改成 runtime entrypoint
# chown 可以解锁跨主机共用,但要新增 entrypoint + 处理 CIFS forceuid 上的 EPERM,
# 工作量较大;目前 GHCR 镜像默认 10001:10001,运维侧约定 host 数据目录与之一致即可。
# TODO(post-1.0): runtime chown via entrypoint, drop build-time uid bake-in.
RUN groupadd -g "${LUMEN_APP_GID}" lumen \
&& useradd -m -u "${LUMEN_APP_UID}" -g "${LUMEN_APP_GID}" -s /bin/bash lumen
WORKDIR /app
ENV TIKTOKEN_CACHE_DIR=/app/.cache/tiktoken
COPY --from=builder --chown=lumen:lumen /app /app
RUN python - <<'PY'
import pyvips
version = (int(pyvips.major), int(pyvips.minor))
if version < (8, 14):
raise SystemExit(f"libvips >= 8.14 is required, got {pyvips.major}.{pyvips.minor}")
print(f"libvips runtime OK: {pyvips.major}.{pyvips.minor}.{pyvips.micro}")
PY
USER lumen
# Prove the final, unprivileged image can load its cache without network access.
RUN --network=none python -c 'import tiktoken; assert tiktoken.get_encoding("o200k_base").encode("hello world")'
CMD ["python"]