Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
85ba3d1
Speed up deploy.sh via lockfile-hash npm ci guard, IAM policy cache, …
christophervoelpel Sep 23, 2026
d087d17
Drop IAM cache, use cmp -s lockfile guard, overlap UI build, and surf…
christophervoelpel Sep 23, 2026
0745f18
perf(deploy): use E2_HIGHCPU_8 machineType in cloudbuild.yaml
christophervoelpel Sep 23, 2026
dab530f
perf(deploy): keep cloudbuild.yaml on default pre-warmed worker pool
christophervoelpel Sep 23, 2026
8c4b265
perf(deploy): use e2-highcpu-8 only on cold Cloud Builds and merge main
christophervoelpel Sep 23, 2026
aa64949
perf(deploy): single-stage slim Dockerfile, single-read IAM snapshot,…
christophervoelpel Sep 23, 2026
69279f8
perf(docker): parallel BuildKit stages with mirror.gcr.io, force-unsa…
christophervoelpel Sep 23, 2026
cf4fcb9
perf(deploy): use E2_HIGHCPU_8 on cold builds and pre-warmed worker p…
christophervoelpel Sep 23, 2026
803fa6f
sec(docker): digest-pin uv:0.6.6 and enforce --only-binary :all: with…
christophervoelpel Sep 23, 2026
afc1a58
style(test): remove trailing blank line at EOF in test_deploy_safety.py
christophervoelpel Sep 23, 2026
5907cff
fix(deploy): remove duplicate env.ts/config.json write during backgro…
christophervoelpel Sep 23, 2026
ed61ed6
Address PR #206 review: retry Cloud Build on IAM propagation, add EXI…
christophervoelpel Sep 23, 2026
a9aeb77
Tighten Cloud Build retry regex, use deterministic WORKER_URL across …
christophervoelpel Sep 23, 2026
4cd63be
Fix PR206 rollout ordering and cached deployment safety
christophervoelpel Sep 23, 2026
033808b
Address final PR206 deployment review comments
christophervoelpel Sep 23, 2026
3675f2d
Validate --skip-ui-build early, guard IAM cache on error, and harden …
christophervoelpel Sep 25, 2026
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
66 changes: 37 additions & 29 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# syntax=docker/dockerfile:1
Comment thread
christophervoelpel marked this conversation as resolved.
Outdated
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -12,45 +13,52 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# --- Build stage -------------------------------------------------------------
# The full python:3.13 image carries the compilers/headers that a dependency
# without a prebuilt cp313 wheel would need. Install everything into a
# relocatable prefix (/install) that the slim runtime can drop in as-is, so the
# build can never fail for lack of a compiler on the slim base.
FROM python:3.13@sha256:e72bfff2ccf413e3c329074d643fac616d7e1dfe85ac57e527f1d13cd8e0ee6c AS builder
# ==============================================================================
# Stage 1: OS Runtime + FFmpeg (Runs concurrently with Stage 2 under BuildKit!)
# ==============================================================================
FROM mirror.gcr.io/library/python:3.13-slim@sha256:c33f0bc4364a6881bed1ec0cc2665e6c53c87a43e774aaeab88e6f17af105e4f AS runtime-base

ENV PYTHONUNBUFFERED=1

COPY requirements.txt .
RUN pip install --no-cache-dir --require-hashes --prefix=/install -r requirements.txt
# Speed up dpkg on Cloud Build disks by disabling per-file fsync() during unpack
# and strictly excluding Debian recommended GUI/X11/Mesa bloat.
RUN echo "force-unsafe-io" > /etc/dpkg/dpkg.cfg.d/docker-apt-speedup \
&& apt-get update \
&& apt-get install -y --no-install-recommends ffmpeg \
&& rm -rf /var/lib/apt/lists/* \
&& useradd --create-home --uid 10001 --shell /usr/sbin/nologin appuser \
&& mkdir -p /app \
&& chown appuser:appuser /app

# --- Runtime stage -----------------------------------------------------------
# python:3.13-slim is ~850 MB smaller than the full image: faster to push to the
# registry and faster to cold-start. It carries only ffmpeg, the dependencies
# built above, and the app — no compilers or build cruft.
FROM python:3.13-slim@sha256:c33f0bc4364a6881bed1ec0cc2665e6c53c87a43e774aaeab88e6f17af105e4f
# ==============================================================================
# Stage 2: Python Dependency Builder via official Astral uv
# (Executes in ~3-6s *while* Stage 1 is still running apt-get!)
# ==============================================================================
FROM mirror.gcr.io/library/python:3.13-slim@sha256:c33f0bc4364a6881bed1ec0cc2665e6c53c87a43e774aaeab88e6f17af105e4f AS venv-builder

ENV PYTHONUNBUFFERED=1
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
ENV UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
VIRTUAL_ENV=/opt/venv \
PATH="/opt/venv/bin:$PATH"

# ffmpeg is required by the worker's video actions (combine/convert). One layer,
# no recommended extras, apt lists dropped to keep the image small.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ffmpeg \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN uv venv /opt/venv \
&& uv pip install --no-cache --require-hashes -r requirements.txt

# Run as a non-root user with a real home, and give it a writable app dir it
# owns. The worker's video actions write temp files using bare relative names
# into the process CWD (== WORKDIR), so WORKDIR must be owned by this user.
RUN useradd --create-home --uid 10001 --shell /usr/sbin/nologin appuser \
&& mkdir -p /app \
&& chown appuser:appuser /app
# ==============================================================================
# Stage 3: Final Image Assembly (< 1 second merge)
# ==============================================================================
FROM runtime-base AS final

ENV VIRTUAL_ENV=/opt/venv \
PATH="/opt/venv/bin:$PATH" \
PYTHONUNBUFFERED=1

WORKDIR /app
COPY --from=venv-builder /opt/venv /opt/venv

# Drop in the dependencies built in the full image (same python 3.13, so the
# installed packages and gunicorn entry point land on /usr/local and PATH).
# Left root-owned and world-readable — import/exec only need read access.
COPY --from=builder /install /usr/local

# Runtime files only (not the whole repo): explicit copies keep docs, examples,
# tests, deploy scripts, and .git out of the image. Root-owned but world-readable
Expand Down
1 change: 1 addition & 0 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ images:
- '${_IMAGE}'
options:
logging: CLOUD_LOGGING_ONLY
machineType: 'E2_HIGHCPU_8'
Loading
Loading