fix(docker): serialize Coolify builds and harden web/worker image inputs
Avoid Coolify OOM crashes by documenting and scripting sequential service builds, and make Docker builds resilient to local-only .env symlinks and missing .cursor agent paths. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
e8074dc5fc
commit
b513b3b04f
7 changed files with 101 additions and 7 deletions
50
.dockerignore
Normal file
50
.dockerignore
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Docker build context is the repo root (see docker/docker-compose.coolify.yml).
|
||||
# Keep in sync with docker/.dockerignore.
|
||||
|
||||
# Dependencies & build outputs
|
||||
**/node_modules
|
||||
**/.pnpm-store
|
||||
**/.next
|
||||
**/dist
|
||||
**/.turbo
|
||||
|
||||
# Git & IDE (worker image copies .cursor; keep context lean via explicit COPY paths in Dockerfile)
|
||||
.git
|
||||
.gitignore
|
||||
.idea
|
||||
.vscode
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Env & secrets (compose should inject at runtime)
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
apps/web/.env
|
||||
|
||||
# Logs & caches
|
||||
logs
|
||||
**/*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
.turbo
|
||||
.cache
|
||||
|
||||
# Tests & misc
|
||||
coverage
|
||||
**/__tests__
|
||||
**/*.test.ts
|
||||
**/*.test.tsx
|
||||
**/*.spec.ts
|
||||
**/*.spec.tsx
|
||||
|
||||
# Docs (not needed in image)
|
||||
**/*.md
|
||||
LICENSE
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Docker (avoid nested contexts)
|
||||
docker/**/*.md
|
||||
|
|
@ -112,6 +112,14 @@ NVIDIA_API_KEY=""
|
|||
# ----- MCP Server -----
|
||||
MCP_SERVER_PORT=3001
|
||||
|
||||
# =====================================================================
|
||||
# Coolify Docker Compose build (8 GB hosts)
|
||||
# =====================================================================
|
||||
# Serialize image builds to avoid kernel OOM (exit 255) during export.
|
||||
# Coolify (8 GB host): set Custom Build Command to `bash scripts/build-coolify.sh`
|
||||
# so compose builds collab → mcp → orchestrator → worker → web sequentially.
|
||||
# COMPOSE_PARALLEL_LIMIT is documented for reference but the script is required.
|
||||
|
||||
# =====================================================================
|
||||
# Local Docker Compose only (docker/docker-compose.yml)
|
||||
# Not needed for Coolify (Coolify uses CT 102's shared Postgres/Redis).
|
||||
|
|
|
|||
|
|
@ -8,9 +8,6 @@
|
|||
# Git & IDE
|
||||
.git
|
||||
.gitignore
|
||||
.cursor
|
||||
!.cursor/agents
|
||||
!.cursor/agents/**
|
||||
.idea
|
||||
.vscode
|
||||
*.swp
|
||||
|
|
@ -20,6 +17,7 @@
|
|||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
apps/web/.env
|
||||
|
||||
# Logs & caches
|
||||
**/*.log
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@ ENV NODE_ENV=production
|
|||
# tsup workers still have breathing room. Below ~3 GB the compile spirals
|
||||
# into GC churn and gets oom-killed (exit 255 with no Docker error).
|
||||
ENV NODE_OPTIONS=--max-old-space-size=5120
|
||||
# Local dev uses a gitignored apps/web/.env symlink; drop it so Next.js does not
|
||||
# follow a broken link inside the container.
|
||||
RUN rm -f apps/web/.env apps/web/.env.local apps/web/.env.production apps/web/.env.development
|
||||
RUN pnpm exec turbo build --filter=@tasks/web
|
||||
|
||||
|
||||
|
|
@ -272,7 +275,9 @@ COPY --from=worker-build --chown=worker:nodejs /app/apps/worker/node_modules ./a
|
|||
COPY --chown=worker:nodejs apps ./repo/apps
|
||||
COPY --chown=worker:nodejs packages ./repo/packages
|
||||
COPY --chown=worker:nodejs plans ./repo/plans
|
||||
COPY --chown=worker:nodejs .cursor ./repo/.cursor
|
||||
COPY --chown=worker:nodejs .cursor/mcp.json ./repo/.cursor/mcp.json
|
||||
COPY --chown=worker:nodejs .cursor/rules ./repo/.cursor/rules
|
||||
RUN mkdir -p /app/repo/.cursor/agents
|
||||
COPY --chown=worker:nodejs pnpm-workspace.yaml package.json turbo.json tsconfig.json ./repo/
|
||||
|
||||
# Minimal git repo so worktrees + allowlisted git commands work on the deploy snapshot.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@
|
|||
# compile. The `depends_on` below only orders runtime startup, NOT image
|
||||
# builds — that was a misconception from an earlier iteration of this
|
||||
# file.
|
||||
#
|
||||
# Runtime image export still builds five targets in parallel by default,
|
||||
# which OOMs 8 GB Coolify hosts (exit 255, no Docker error). Required:
|
||||
# Coolify → Advanced → Custom Build Command: bash scripts/build-coolify.sh
|
||||
# (COMPOSE_PARALLEL_LIMIT alone is not reliable across Compose versions.)
|
||||
# Local verify: pnpm docker:build:coolify
|
||||
|
||||
services:
|
||||
web:
|
||||
|
|
@ -156,7 +162,7 @@ services:
|
|||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- "pgrep -f 'node.*dist/index\\.mjs' > /dev/null || exit 1"
|
||||
- "pgrep -f 'node.*dist/index\\.js' > /dev/null || exit 1"
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
|
@ -187,7 +193,7 @@ services:
|
|||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- "pgrep -f 'node.*dist/index\\.mjs' > /dev/null || exit 1"
|
||||
- "pgrep -f 'node.*dist/index\\.js' > /dev/null || exit 1"
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
"db:generate": "turbo db:generate --filter=@tasks/database",
|
||||
"db:migrate": "turbo db:migrate --filter=@tasks/database",
|
||||
"db:push": "turbo db:push --filter=@tasks/database",
|
||||
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,css,md}\""
|
||||
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,css,md}\"",
|
||||
"docker:build:coolify": "bash scripts/build-coolify.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitest/coverage-v8": "^2",
|
||||
|
|
|
|||
26
scripts/build-coolify.sh
Executable file
26
scripts/build-coolify.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
# Coolify custom build command for docker-compose.coolify.yml.
|
||||
#
|
||||
# Set in Coolify → Resource → Advanced → Custom Build Command:
|
||||
# bash scripts/build-coolify.sh
|
||||
#
|
||||
# Coolify auto-injects -f and --env-file; this script only serializes builds so
|
||||
# an 8 GB host does not OOM (exit 255) while exporting five runtime images.
|
||||
set -euo pipefail
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$repo_root"
|
||||
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
compose() {
|
||||
docker compose --project-directory "$repo_root" \
|
||||
-f docker/docker-compose.coolify.yml \
|
||||
"$@"
|
||||
}
|
||||
|
||||
# Build one service at a time so an 8 GB host does not OOM during export
|
||||
# (Coolify default runs all five targets in parallel → exit 255).
|
||||
for service in collab mcp orchestrator worker web; do
|
||||
compose build --pull "$service"
|
||||
done
|
||||
Loading…
Reference in a new issue