speed up docker deploy builds

This commit is contained in:
dirtydishes 2026-05-16 17:54:00 -04:00
parent 2abdd24e2c
commit 23ed3809cc
7 changed files with 349 additions and 22 deletions

View file

@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1.7
FROM oven/bun:1.3.11
WORKDIR /app
@ -9,15 +11,39 @@ ENV PATH="${VIRTUAL_ENV}/bin:${PATH}"
COPY --from=workspace package.json ./package.json
COPY --from=workspace bun.lock ./bun.lock
COPY --from=workspace tsconfig.base.json ./tsconfig.base.json
COPY --from=services . ./services
COPY --from=packages . ./packages
COPY --from=apps . ./apps
RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 python3-pip python3-venv \
&& rm -rf /var/lib/apt/lists/* \
&& python3 -m venv "${VIRTUAL_ENV}" \
&& "${VIRTUAL_ENV}/bin/pip" install --no-cache-dir -r services/ingest-options/py/requirements.txt \
&& bun install --frozen-lockfile
&& python3 -m venv "${VIRTUAL_ENV}"
COPY --from=apps desktop/package.json ./apps/desktop/package.json
COPY --from=apps web/package.json ./apps/web/package.json
COPY --from=packages bus/package.json ./packages/bus/package.json
COPY --from=packages config/package.json ./packages/config/package.json
COPY --from=packages observability/package.json ./packages/observability/package.json
COPY --from=packages storage/package.json ./packages/storage/package.json
COPY --from=packages types/package.json ./packages/types/package.json
COPY --from=services api/package.json ./services/api/package.json
COPY --from=services candles/package.json ./services/candles/package.json
COPY --from=services compute/package.json ./services/compute/package.json
COPY --from=services eod-enricher/package.json ./services/eod-enricher/package.json
COPY --from=services ingest-equities/package.json ./services/ingest-equities/package.json
COPY --from=services ingest-options/package.json ./services/ingest-options/package.json
COPY --from=services ingest-options/py/requirements.txt ./services/ingest-options/py/requirements.txt
COPY --from=services refdata/package.json ./services/refdata/package.json
COPY --from=services replay/package.json ./services/replay/package.json
RUN --mount=type=cache,target=/root/.cache/pip \
"${VIRTUAL_ENV}/bin/pip" install -r services/ingest-options/py/requirements.txt
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --frozen-lockfile
COPY --from=services . ./services
COPY --from=packages . ./packages
COPY --from=apps . ./apps
ENTRYPOINT ["bun"]

View file

@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1.7
FROM oven/bun:1.3.11
WORKDIR /app
@ -7,10 +9,30 @@ ENV NODE_ENV=production
COPY --from=workspace package.json ./package.json
COPY --from=workspace bun.lock ./bun.lock
COPY --from=workspace tsconfig.base.json ./tsconfig.base.json
COPY --from=apps desktop/package.json ./apps/desktop/package.json
COPY --from=apps web/package.json ./apps/web/package.json
COPY --from=packages bus/package.json ./packages/bus/package.json
COPY --from=packages config/package.json ./packages/config/package.json
COPY --from=packages observability/package.json ./packages/observability/package.json
COPY --from=packages storage/package.json ./packages/storage/package.json
COPY --from=packages types/package.json ./packages/types/package.json
COPY --from=services api/package.json ./services/api/package.json
COPY --from=services candles/package.json ./services/candles/package.json
COPY --from=services compute/package.json ./services/compute/package.json
COPY --from=services eod-enricher/package.json ./services/eod-enricher/package.json
COPY --from=services ingest-equities/package.json ./services/ingest-equities/package.json
COPY --from=services ingest-options/package.json ./services/ingest-options/package.json
COPY --from=services refdata/package.json ./services/refdata/package.json
COPY --from=services replay/package.json ./services/replay/package.json
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --frozen-lockfile
COPY --from=services . ./services
COPY --from=packages . ./packages
COPY --from=apps . ./apps
RUN bun install --frozen-lockfile
ENTRYPOINT ["bun"]

View file

@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1.7
FROM oven/bun:1.3.11 AS build
WORKDIR /app
@ -13,11 +15,32 @@ ENV NEXT_PUBLIC_NBBO_MAX_AGE_MS=${NEXT_PUBLIC_NBBO_MAX_AGE_MS}
COPY --from=workspace package.json ./package.json
COPY --from=workspace bun.lock ./bun.lock
COPY --from=workspace tsconfig.base.json ./tsconfig.base.json
COPY --from=apps desktop/package.json ./apps/desktop/package.json
COPY --from=apps web/package.json ./apps/web/package.json
COPY --from=packages bus/package.json ./packages/bus/package.json
COPY --from=packages config/package.json ./packages/config/package.json
COPY --from=packages observability/package.json ./packages/observability/package.json
COPY --from=packages storage/package.json ./packages/storage/package.json
COPY --from=packages types/package.json ./packages/types/package.json
COPY --from=services api/package.json ./services/api/package.json
COPY --from=services candles/package.json ./services/candles/package.json
COPY --from=services compute/package.json ./services/compute/package.json
COPY --from=services eod-enricher/package.json ./services/eod-enricher/package.json
COPY --from=services ingest-equities/package.json ./services/ingest-equities/package.json
COPY --from=services ingest-options/package.json ./services/ingest-options/package.json
COPY --from=services refdata/package.json ./services/refdata/package.json
COPY --from=services replay/package.json ./services/replay/package.json
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --frozen-lockfile
COPY --from=services . ./services
COPY --from=packages . ./packages
COPY --from=apps . ./apps
RUN bun install --frozen-lockfile
RUN bun run --cwd apps/web build
FROM oven/bun:1.3.11 AS runtime

View file

@ -65,14 +65,16 @@ Important defaults:
3. Build and start the stack:
```bash
docker compose up -d --build
docker compose build api web compute candles ingest-options ingest-equities
docker compose up -d
```
If you are updating an existing deployment that already has failing `api` restart loops, do a full recreate so the ClickHouse config mount and dependency changes are applied cleanly:
```bash
docker compose down
docker compose up -d --build --force-recreate
docker compose build api web compute candles ingest-options ingest-equities
docker compose up -d --force-recreate
```
4. Confirm the containers are healthy:
@ -190,6 +192,19 @@ cd deployment/docker
docker compose build web
```
### Faster Docker builds
The app images are structured so dependency installation is isolated from source code changes:
- Docker first copies `package.json`, `bun.lock`, `tsconfig.base.json`, and workspace `package.json` files.
- `bun install --frozen-lockfile` runs in a cacheable layer with a BuildKit Bun cache mount.
- Source from `apps`, `services`, and `packages` is copied only after dependencies are installed.
- `ingest-options` also installs its Python sidecar dependencies from `services/ingest-options/py/requirements.txt` before source copy, using a BuildKit pip cache mount.
That means normal TypeScript edits should reuse dependency layers. The first build after a fresh server checkout, Docker cache cleanup, dependency change, or Python requirement change can still be slow; later deploys should spend their time on changed source and the specific service images being rolled out.
BuildKit cache mounts require a modern Docker Engine with Dockerfile frontend support. Docker Compose v2 on the VPS path enables this by default.
## Safe rollouts on `152.53.80.229`
The current live VPS uses Nginx Proxy Manager on the shared Docker network and routes public traffic to the Docker `web` and `api` containers by container name. Because of that, this Docker path remains the operationally correct default for the live server today.
@ -218,7 +233,7 @@ This flow:
- checks the server checkout before switching anything
- stops if the server has tracked local modifications
- allows the known untracked tarball at `deployment/docker/signal-cli-0.14.3-Linux-native.tar.gz`
- runs `git switch main`, `git pull --ff-only origin main`, and `docker compose up -d --build`
- runs `git switch main`, `git pull --ff-only origin main`, `docker compose build api web compute candles ingest-options ingest-equities`, and `docker compose up -d`
- verifies the stack with `docker compose ps`, recent service logs, container-local health checks, and public HTTPS checks
### Deploy the current local branch
@ -253,6 +268,14 @@ Examples:
./deploy main --runtime docker --web-only --no-build
```
Scoped Docker deploys now build only the selected image set and then restart only those services:
- `--web-only`: `docker compose build web`, then `docker compose up -d web`
- `--api-only`: `docker compose build api`, then `docker compose up -d api`
- `--services-only`: builds and restarts `api`, `compute`, `candles`, `ingest-options`, and `ingest-equities`
Use `--no-build` only when the image is already correct and you need Compose to recreate or restart containers, such as after changing server-side environment values that do not affect a Next.js build-time variable. Do not use `--no-build` for dependency changes, application source changes, or `NEXT_PUBLIC_*` changes.
### Escalation path
Use force recreate only when a normal refresh does not update the services cleanly:
@ -299,7 +322,8 @@ git switch main
git pull --ff-only origin main
cd /home/delta/islandflow/deployment/docker
docker compose up -d --build
docker compose build api web compute candles ingest-options ingest-equities
docker compose up -d
```
Deploy the current branch manually:
@ -314,7 +338,8 @@ git switch <current-branch> || git switch -c <current-branch> --track origin/<cu
git pull --ff-only origin <current-branch>
cd /home/delta/islandflow/deployment/docker
docker compose up -d --build
docker compose build api web compute candles ingest-options ingest-equities
docker compose up -d
```
If you changed only env values for the Bun services on the server: