Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 53 additions & 23 deletions docker/admin.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,65 @@
FROM python:3.11-slim
############################
# Builder stage
############################
FROM python:3.11-alpine AS builder

ARG GIT_COMMIT
ENV GIT_COMMIT=$GIT_COMMIT
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_HOME=/home/app

# This prevents Python from writing out pyc files
ENV PYTHONDONTWRITEBYTECODE=1
# This keeps Python from buffering stdin/stdout
ENV PYTHONUNBUFFERED=1
ENV PIP_ARGS="--progress-bar off --no-cache-dir"

ENV APP_HOME=/home/app
RUN pip install --progress-bar off --no-cache-dir poetry==2.2.1

WORKDIR $APP_HOME

# Install dependencies using poetry
RUN pip install $PIP_ARGS "poetry==2.1.1"
RUN poetry self add poetry-plugin-export
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry export -f requirements.txt --without-hashes | pip install $PIP_ARGS -r /dev/stdin
# Install dependencies first to leverage Docker layer caching
COPY pyproject.toml poetry.lock poetry.toml ./
RUN poetry install --no-interaction --no-ansi --no-cache --no-root \
--no-directory --only main

# Copy source code
# Copy source code and install the project
COPY ./alembic.ini $APP_HOME/alembic.ini
COPY ./statgpt/admin $APP_HOME/statgpt/admin
COPY ./statgpt/common $APP_HOME/statgpt/common
RUN poetry install --no-interaction --no-ansi --no-cache --no-root --only main

############################
# Runtime stage
############################
FROM python:3.11-alpine AS server

# create the app user and chown workdir to the app user
RUN adduser -u 5678 --system --disabled-password --gecos "" app && chown -R app $APP_HOME
USER app
# Security patches (consolidated into single layer)
# CVE-2023-52425 (libexpat), CVE-2025-6965 (sqlite-libs), libcrypto3/libssl3
RUN apk update && apk upgrade --no-cache \
libcrypto3 libssl3 libexpat sqlite-libs \
&& apk add --no-cache ca-certificates \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*

# CVE-2026-23949 (setuptools), CVE-2026-24049 (wheel)
RUN pip install --no-cache-dir setuptools==80.10.2 wheel==0.46.2

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_HOME=/home/app \
WEB_CONCURRENCY=1 \
PYDANTIC_V2=True

WORKDIR $APP_HOME

ENV WEB_CONCURRENCY=1
ENV PYDANTIC_V2=True
# Create non-root user and copy built application
RUN adduser -u 1001 --disabled-password --gecos "" appuser
COPY --chown=appuser --from=builder $APP_HOME .

COPY --chmod=755 ./docker/scripts/admin_docker_entrypoint.sh /docker_entrypoint.sh

EXPOSE 8000

USER appuser

HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=6 \
CMD wget -q --spider -T 3 http://localhost:8000/health || exit 1

ARG GIT_COMMIT
ENV GIT_COMMIT=$GIT_COMMIT

CMD ["sh", "statgpt/admin/admin.sh"]
ENTRYPOINT ["/docker_entrypoint.sh"]
74 changes: 51 additions & 23 deletions docker/chat.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,36 +1,64 @@
FROM python:3.11-slim
############################
# Builder stage
############################
FROM python:3.11-alpine AS builder

ARG GIT_COMMIT
ENV GIT_COMMIT=$GIT_COMMIT
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_HOME=/home/app

# This prevents Python from writing out pyc files
ENV PYTHONDONTWRITEBYTECODE=1
# This keeps Python from buffering stdin/stdout
ENV PYTHONUNBUFFERED=1
ENV PIP_ARGS="--progress-bar off --no-cache-dir"

ENV APP_HOME=/home/app
RUN pip install --progress-bar off --no-cache-dir poetry==2.2.1

WORKDIR $APP_HOME

# Install dependencies using poetry
RUN pip install $PIP_ARGS "poetry==2.1.1"
RUN poetry self add poetry-plugin-export
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry export -f requirements.txt --without-hashes | pip install $PIP_ARGS -r /dev/stdin
# Install dependencies first to leverage Docker layer caching
COPY pyproject.toml poetry.lock poetry.toml ./
RUN poetry install --no-interaction --no-ansi --no-cache --no-root \
--no-directory --only main

# Copy source code
# Copy source code and install the project
COPY ./statgpt/app $APP_HOME/statgpt/app
COPY ./statgpt/common $APP_HOME/statgpt/common
RUN poetry install --no-interaction --no-ansi --no-cache --no-root --only main

############################
# Runtime stage
############################
FROM python:3.11-alpine AS server

# Security patches (consolidated into single layer)
# CVE-2023-52425 (libexpat), CVE-2025-6965 (sqlite-libs), libcrypto3/libssl3
RUN apk update && apk upgrade --no-cache \
libcrypto3 libssl3 libexpat sqlite-libs \
&& apk add --no-cache ca-certificates \
&& update-ca-certificates \
&& rm -rf /var/cache/apk/*

# CVE-2026-23949 (setuptools), CVE-2026-24049 (wheel)
RUN pip install --no-cache-dir setuptools==80.10.2 wheel==0.46.2

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_HOME=/home/app \
WEB_CONCURRENCY=1 \
PYDANTIC_V2=True

# create the app user and chown workdir to the app user
RUN adduser -u 5678 --system --disabled-password --gecos "" app && chown -R app $APP_HOME
USER app
WORKDIR $APP_HOME

# Create non-root user and copy built application
RUN adduser -u 1001 --disabled-password --gecos "" appuser
COPY --chown=appuser --from=builder $APP_HOME .

ENV WEB_CONCURRENCY=1
ENV PYDANTIC_V2=True
COPY --chmod=755 ./docker/scripts/chat_docker_entrypoint.sh /docker_entrypoint.sh

EXPOSE 5000

CMD ["uvicorn", "statgpt.app.app:app", "--host", "0.0.0.0", "--port", "5000", "--lifespan", "on"]
USER appuser

HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=6 \
CMD wget -q --spider -T 3 http://localhost:5000/health || exit 1

ARG GIT_COMMIT
ENV GIT_COMMIT=$GIT_COMMIT

ENTRYPOINT ["/docker_entrypoint.sh"]
13 changes: 13 additions & 0 deletions docker/scripts/admin_docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh
set -eu

export VIRTUAL_ENV="$PWD/.venv"
export PATH="$VIRTUAL_ENV/bin:$PATH"

# If no args passed to `docker run`, then run the admin service
if [ $# -lt 1 ]; then
exec sh statgpt/admin/admin.sh
fi

# Otherwise, run the user's command, for example a `sh` shell to explore the container
exec "$@"
17 changes: 17 additions & 0 deletions docker/scripts/chat_docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh
set -eu

export VIRTUAL_ENV="$PWD/.venv"
export PATH="$VIRTUAL_ENV/bin:$PATH"

# If no args passed to `docker run`, then we assume the user is calling the service
if [ $# -lt 1 ]; then
exec uvicorn statgpt.app.app:app \
--host 0.0.0.0 \
--port 5000 \
--lifespan on \
--timeout-keep-alive "${TIMEOUT_KEEP_ALIVE:-5}"
fi

# Otherwise, we assume the user wants to run his own process, for example a `sh` shell to explore the container
exec "$@"
6 changes: 3 additions & 3 deletions statgpt/admin/admin.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/bin/bash
#!/bin/sh

# IMPORTANT: Do not delete this line!
# These settings make the script fail fast and loud on common errors:
# undefined variables, command failures, and pipeline failures
set -Eeuo pipefail
# undefined variables and command failures
set -eu

echo "ADMIN_MODE = '${ADMIN_MODE:-}'"

Expand Down
Loading