deploy: static binary and a compose project name that does not collide
Two failures from the first real deploy, both repo-side: 1. The container logged "exec /usr/bin/resume-server: no such file or directory" and restarted until the health gate failed. The build host has cgo enabled, so the binary carried the nix glibc interpreter, and the distroless/static image has no dynamic loader. Every SQLite path already uses pure-Go modernc.org/sqlite, so build with CGO_ENABLED=0 and ship a static binary. 2. Compose warned about orphan containers ai-resume-backend-1 and ai-resume-db-1: /home/sam/deployment/ai-resume on .13 already owns the `ai-resume` compose project (on the ai-mesh network). Sharing the name makes each stack visible as orphans to the other, so a `compose down --remove-orphans` in either could stop the other. Run the site as project `ai-resume-site`; the image tag stays ai-resume:local and the port binding, mem_limit and memswap_limit are untouched.
This commit is contained in:
51
Makefile
51
Makefile
@@ -12,10 +12,18 @@ VALIDATOR := $(PYTHON) tools/validate_content.py
|
||||
GO ?= go
|
||||
TEMPL ?= templ
|
||||
|
||||
# The runtime image is distroless/static (deploy/Dockerfile): no libc, no
|
||||
# dynamic loader. Everything the server needs is pure Go (modernc.org/sqlite),
|
||||
# so a static binary is buildable and is what the container can actually exec.
|
||||
# Without this the build host's cgo links the nix glibc loader and the container
|
||||
# fails with "exec /usr/bin/resume-server: no such file or directory".
|
||||
CGO_ENABLED ?= 0
|
||||
|
||||
BIN := bin
|
||||
DIST := dist
|
||||
|
||||
.PHONY: build dist generate dev test validate validate-self-test fmt vet clean help
|
||||
.PHONY: build dist generate dev test validate validate-self-test fmt vet clean help \
|
||||
corpus corpus-sync corpus-rebuild corpus-audit corpus-verify corpus-demo corpus-test
|
||||
|
||||
help:
|
||||
@echo "make build templ generate, compile bin/, no dist"
|
||||
@@ -26,11 +34,19 @@ help:
|
||||
@echo "make validate validate content/** front-matter against the frozen schema"
|
||||
@echo "make fmt vet gofmt / go vet over cmd and internal"
|
||||
@echo "make clean remove bin/ and dist/"
|
||||
@echo ""
|
||||
@echo "corpus (Phase 4, python3 -m corpus.cli):"
|
||||
@echo "make corpus rebuild the corpus from content/ (drops the collection)"
|
||||
@echo "make corpus-sync incremental update; only changed documents are re-embedded"
|
||||
@echo "make corpus-audit freshness + drift audit (exit 1 on findings)"
|
||||
@echo "make corpus-verify check the index against content/ and Qdrant"
|
||||
@echo "make corpus-demo same query with and without an area filter"
|
||||
@echo "make corpus-test corpus unit tests (no container, no network)"
|
||||
|
||||
build: generate
|
||||
@mkdir -p $(BIN)
|
||||
$(GO) build -trimpath -buildvcs=false -o $(BIN)/resume-build ./cmd/build
|
||||
$(GO) build -trimpath -buildvcs=false -o $(BIN)/resume-server ./cmd/server
|
||||
CGO_ENABLED=$(CGO_ENABLED) $(GO) build -trimpath -buildvcs=false -o $(BIN)/resume-build ./cmd/build
|
||||
CGO_ENABLED=$(CGO_ENABLED) $(GO) build -trimpath -buildvcs=false -o $(BIN)/resume-server ./cmd/server
|
||||
|
||||
dist: build
|
||||
@$(BIN)/resume-build --dist $(DIST)
|
||||
@@ -57,5 +73,34 @@ fmt:
|
||||
vet:
|
||||
@$(GO) vet ./...
|
||||
|
||||
# -- corpus (Phase 4, docs/phase-4-corpus.md) --------------------------------
|
||||
#
|
||||
# The corpus is data, not a build artefact: it lives in data/corpus/ (gitignored)
|
||||
# and in Qdrant. RESUME_QDRANT_URL defaults to http://127.0.0.1:6333 and
|
||||
# RESUME_EMBED_PROVIDER defaults to local-hashing; production sets both in the
|
||||
# environment, never in this file.
|
||||
|
||||
CORPUS := $(PYTHON) -m corpus.cli
|
||||
|
||||
corpus: corpus-rebuild
|
||||
|
||||
corpus-rebuild:
|
||||
@$(CORPUS) rebuild
|
||||
|
||||
corpus-sync:
|
||||
@$(CORPUS) sync
|
||||
|
||||
corpus-audit:
|
||||
@$(CORPUS) audit --fail-on-findings
|
||||
|
||||
corpus-verify:
|
||||
@$(CORPUS) verify
|
||||
|
||||
corpus-demo:
|
||||
@$(CORPUS) demo-filter --query "distributed audio endpoints" --area edge
|
||||
|
||||
corpus-test:
|
||||
@$(PYTHON) -m unittest discover -s corpus/tests -t .
|
||||
|
||||
clean:
|
||||
@rm -rf $(BIN) $(DIST)
|
||||
|
||||
@@ -12,7 +12,14 @@
|
||||
#
|
||||
# `curl http://127.0.0.1:8096/healthz` must answer with static ready.
|
||||
|
||||
name: ai-resume
|
||||
# The compose project name is deliberately not `ai-resume`: /home/sam/deployment/
|
||||
# ai-resume on .13 already runs a compose project by that name (backend + db on
|
||||
# the ai-mesh network). Sharing the name would make this site's containers show
|
||||
# up as orphans in that project and vice versa, so anything running `compose
|
||||
# down --remove-orphans` under either project could stop the other. The image
|
||||
# tag stays ai-resume:local (Phase 3 fixes it); only the project namespace is
|
||||
# distinct.
|
||||
name: ai-resume-site
|
||||
|
||||
services:
|
||||
resume:
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
APP=ai-resume
|
||||
APP=ai-resume # image tag (fixed by Phase 3 §3.2)
|
||||
PROJECT=ai-resume-site # compose project; distinct from the older
|
||||
# /home/sam/deployment/ai-resume project on .13
|
||||
PORT=8096
|
||||
HEALTH_PATH=/healthz
|
||||
|
||||
@@ -92,7 +94,7 @@ done
|
||||
|
||||
# ---------------------------------------------------------------- helpers ---
|
||||
|
||||
compose() { docker compose -f "$COMPOSE" -p "$APP" "$@"; }
|
||||
compose() { docker compose -f "$COMPOSE" -p "$PROJECT" "$@"; }
|
||||
|
||||
current_target() { readlink -- "$CURRENT" 2>/dev/null || true; }
|
||||
previous_target() { readlink -- "$PREVIOUS" 2>/dev/null || true; }
|
||||
|
||||
Reference in New Issue
Block a user