用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/lukemcqueen/hermes-cortex --skill docker-compose-bringup命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Cross-server agent health monitoring using binary status vectors — deploy health endpoints on each agent, poll from orchestrator, alert on state transitions.
Wire a self-hosted Langfuse instance to Hermes Agent — generate API keys, configure env vars, enable the bundled plugin, install SDK, and verify traces flow.
Use before enforcement code changes or shared-repo commits.
正在显示 SKILL.md
| name | docker-compose-bringup |
| description | Fix a compose stack on a shared host that 500s/404s. |
| version | 1.0.0 |
| category | devops |
| author | Hermes Cortex |
| platforms | ["linux","macos"] |
Making a compose stack actually work (login → authenticated request succeeds through the web origin) is different from "containers start". This skill captures the collision and bring-up failure modes that make ./run up look healthy while every real request fails. Verified on a FastAPI + Next.js stack living on a host that also runs another project's plain postgres/redis.
./run up / docker compose up starts containers but the app 500s, 404s, or can't reach its DB.Container names and host ports BOTH collide across projects on a shared host. The default ports (5432 postgres, 6379 redis, 8000 api, 3000 web) are the highest-risk. A native host service (e.g. Homebrew postgres on 5432) also blocks a container bind — check with lsof -i :PORT and identify the owner (docker inspect -f '{{index .Config.Labels "com.docker.compose.project"}}' <name> for containers).
Fix — unique names + ports, centralized in .env:
# docker-compose.yml
services:
api:
container_name: example-api
ports:
- "127.0.0.1:${EXAMPLE_API_PORT:-18000}:8000" # host 18000 -> container 8000
postgres:
container_name: example-postgres
ports:
- "127.0.0.1:${EXAMPLE_POSTGRES_PORT:-15443}:5432"
.env in the project dir for ${VAR:-default} interpolation.api:8000, postgres:5432) so depends_on and internal DATABASE_URL/REDIS_URL (service-name hosts) are untouched. Only the host-published side changes..env.example (the real .env is gitignored). .env secret-file edits are security-blocked → update via a small Python script that appends deduplicated lines.Keep every config surface in sync when you relabel ports (a single stale one silently lies):
config.py/settings defaults (e.g. database_url host port, ALLOWED_ORIGINS web port)./run status port checks (lsof -i :3012 goes stale when web moves to 13012)baseURL, CI lighthouse urlsfetch('http://localhost:<port>') and Next API-route proxiesEach makes containers start clean yet every request fail:
2a. DB-URL driver must match the app's engine. If the app's SQLAlchemy layer is SYNC (create_engine(...)) but compose sets DATABASE_URL=postgresql+asyncpg://..., every DB query 500s with sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called. Fix: use the matching sync URL postgresql://user:pass@service:5432/db (psycopg2). Check the app's engine before copying an async URL. Also: create_engine fails lazily — the API can boot fine and only crash on the first query, so health checks pass while register/login 500.
2b. Fresh volume has no tables. A brand-new named volume starts empty; unless migrations run, every table query fails. Robust fix: run migrations at API start and make Alembic honor the runtime URL:
Dockerfile CMD: ["sh","-c","uv run alembic upgrade head && exec uv run uvicorn ..."] (alembic is idempotent so restarting is safe).migrations/env.py: in run_migrations_online, db_url = os.environ.get("DATABASE_URL") and config.set_main_option("sqlalchemy.url", db_url) — NEVER bake a host into alembic.ini (its localhost:5432 is wrong inside the container).alembic is in PROD deps (a uv sync --no-dev build drops it if it's dev-only).2c. Frontend /api/v1 prefix vs backend with no such prefix. Pages may call /api/v1/auth/* while FastAPI mounts at /auth, /evangelist (no /api/v1). Without a proxy every browser call 404s. Fix: a Next rewrite forwarding /api/v1/:path* → FastAPI /:path*, with the target from an env var baked at BUILD time (so it survives in Docker where localhost:8000 isn't the API):
// next.config.mjs
async rewrites() {
const api = process.env.EXAMPLE_API_INTERNAL_URL || 'http://localhost:8000';
return [{ source: '/api/v1/:path*', destination: `${api}/:path*` }];
}
Web Dockerfile: ARG EXAMPLE_API_INTERNAL_URL=http://localhost:8000 + ENV before npm run build; compose passes args: EXAMPLE_API_INTERNAL_URL: http://api:8000. Server-side Next API routes can read the same env at runtime. Client components should use the relative /api/v1/... path (through the proxy) instead of hardcoding localhost:<port>. Grep the whole frontend for hardcoded localhost:8000 / nonexistent route strings (e.g. an AuthForm posting to /api/auth that no route serves).
2d. Stale Docker image after a Dockerfile edit. docker compose up may serve an image built with the OLD CMD/RUN — symptom: your new alembic upgrade head CMD doesn't run, logs go straight to uvicorn. Fix: force a rebuild (docker compose build --no-cache <svc>, or rebuild explicitly after editing a Dockerfile) and confirm BEHAVIOR (check logs show the new step), not just that the container restarted.
"Containers up / healthy" is not done. Drive the deployed path:
./run status or docker compose ps → all healthyhttp://127.0.0.1:<WEB_PORT>/api/v1/auth/login), then an authenticated request (/api/v1/auth/me) through the proxybrowser_exec tool drives the actual UI; verify a full flow (login → list → create → mutation → read-back).references/shared-host-case-study.md — the concrete Example walkthrough: the 5 real breakages found, the port set chosen, and how the stack was verified.