tina4 3.8.69

Tina4 — Unified CLI for Python, PHP, Ruby, and Node.js frameworks
# Tina4 Python — production Docker image. Generated by `tina4 deploy docker`.
# Slim two-stage build: install deps with uv into a virtualenv, copy the
# resolved tree into a runtime image. No SCSS watcher, no dev tooling.
# The tina4 CLI is installed in EVERY Tina4 image and is the launcher: one
# `tina4 serve --production` across all four languages instead of four
# different per-language entry points. It is a single static musl binary
# copied from a published image -- a layer copy, no toolchain, no compile,
# no network fetch at build time. Override with
# --build-arg TINA4_CLI_IMAGE=... to pin or test a different CLI.
ARG TINA4_CLI_IMAGE=ghcr.io/tina4stack/tina4-cli:v3.8.63
FROM ${TINA4_CLI_IMAGE} AS tina4cli

FROM python:3.12-slim AS deps
WORKDIR /app
RUN pip install --no-cache-dir uv
COPY pyproject.toml uv.lock* ./
# uvicorn at BUILD time. `tina4 serve --production` checks for it and, if it is
# missing, runs `uv add uvicorn` AT CONTAINER START -- a network install on every
# boot, which fails outright in an air-gapped or offline deploy. Pre-installing
# makes the production check a no-op.
RUN uv sync --frozen --no-dev && uv pip install uvicorn

FROM python:3.12-slim
WORKDIR /app
COPY --from=tina4cli /usr/local/bin/tina4 /usr/local/bin/tina4
ENV PATH="/app/.venv/bin:$PATH" \
    TINA4_OVERRIDE_CLIENT=true \
    TINA4_DEBUG=false
COPY --from=deps /app/.venv /app/.venv
COPY . /app
EXPOSE 7146

# One launcher for all four languages. --host defaults to 0.0.0.0, which is
# required: a server bound to 127.0.0.1 inside a container is unreachable
# through `docker run -p`. --no-browser because there is no browser here.
CMD ["tina4", "serve", "--production", "--no-browser"]