Skip to content

Commit b9b5c2c

Browse files
authored
First submission of the project
1 parent a0dd029 commit b9b5c2c

21 files changed

Lines changed: 4778 additions & 0 deletions

Dockerfile

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
FROM node:20-slim AS frontend-builder
2+
3+
WORKDIR /frontend
4+
5+
# Copy dependency manifests first for better layer caching.
6+
COPY frontend/package*.json ./
7+
RUN npm ci
8+
9+
COPY frontend/ ./
10+
RUN npm run build
11+
12+
13+
FROM python:3.12-slim AS app
14+
15+
ENV PYTHONUNBUFFERED=1 \
16+
PYTHONDONTWRITEBYTECODE=1 \
17+
PIP_DISABLE_PIP_VERSION_CHECK=1 \
18+
PIP_NO_CACHE_DIR=1 \
19+
PORT=8080 \
20+
TZ=Asia/Shanghai
21+
22+
WORKDIR /app
23+
24+
RUN apt-get update && apt-get install -y --no-install-recommends build-essential tzdata gosu && \
25+
rm -rf /var/lib/apt/lists/*
26+
27+
# Copy project sources and install Python dependencies from pyproject.
28+
COPY . /app
29+
RUN pip install --no-cache-dir . && \
30+
pip install --no-cache-dir psycopg2-binary
31+
32+
# Install tgcrypto only on amd64 to avoid arm64 build failures.
33+
ARG TARGETPLATFORM
34+
RUN if [ "${TARGETPLATFORM:-}" = "linux/amd64" ] || [ "$(uname -m)" = "x86_64" ]; then \
35+
pip install --no-cache-dir tgcrypto; \
36+
else \
37+
echo "Skipping tgcrypto on ${TARGETPLATFORM:-unknown}"; \
38+
fi
39+
40+
# Frontend static files served from /web.
41+
RUN mkdir -p /web
42+
COPY --from=frontend-builder /frontend/out /web
43+
44+
# Data dir (mapped via volume).
45+
RUN mkdir -p /data
46+
47+
# Non-root user.
48+
ARG APP_UID=10001
49+
ARG APP_GID=10001
50+
RUN groupadd -r -g ${APP_GID} app && \
51+
useradd -r -u ${APP_UID} -g app -d /app -s /usr/sbin/nologin app && \
52+
chown -R app:app /data
53+
54+
# Runtime entrypoint auto-adapts to mounted /data ownership.
55+
COPY docker/entrypoint.sh /entrypoint.sh
56+
RUN chmod +x /entrypoint.sh
57+
58+
EXPOSE 8080
59+
60+
# Healthcheck uses the PORT env var.
61+
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
62+
CMD python -c "import os, urllib.request; urllib.request.urlopen(f'http://localhost:{os.getenv(\"PORT\", \"8080\")}/healthz').read()"
63+
64+
# Start with env-driven PORT (Zeabur sets this automatically).
65+
ENTRYPOINT ["/entrypoint.sh"]

0 commit comments

Comments
 (0)