Tagged releases publish multi-platform images for Linux AMD64 and ARM64 to GitHub Container Registry:
docker pull ghcr.io/tae2089/code-context-graph:0.11.0Each stable release publishes the full semantic version, minor, major, and
latest tags. Prefer a full semantic-version tag for reproducible deployments.
make container-artifacts
docker build --build-arg TARGETARCH="$(go env GOARCH)" -t ccg .make container-artifacts compiles the Linux binaries and Wiki UI once, then
the Dockerfile packages those prepared assets without compiling source. Linux
hosts use the local Go toolchain; other hosts compile the matching Linux
architecture inside golang:1.25-bookworm.
# Set a bearer token for externally bound HTTP transport.
export CCG_HTTP_BEARER_TOKEN=replace-with-a-long-random-token
# For the default local SQLite database (ccg.db), first-run runtime commands
# auto-migrate only when the schema is missing.
# Mount your project, build the graph, and serve over HTTP.
docker run -d -p 8080:8080 \
-e CCG_HTTP_BEARER_TOKEN="$CCG_HTTP_BEARER_TOKEN" \
-v $(pwd):/repo --entrypoint sh ccg \
-c "ccg build /repo && ccg-server --http-addr :8080"The image's default HTTP command binds to :8080, so you must provide
CCG_HTTP_BEARER_TOKEN for normal external access.
If this container is exposed through an ingress, reverse proxy, or load
balancer, keep health and status endpoints internal. /health, /ready, and
/status are intended for trusted operational checks and should not be exposed
to the public internet. See the Operations Guide
for endpoint exposure guidance.
Example reverse-proxy policy:
| Path | Public Internet | Internal Network |
|---|---|---|
/mcp |
Allowed only with bearer auth and network policy | Allowed |
/wiki |
Allowed only when the Wiki UI shell should be public | Allowed |
/wiki/api/* |
Allowed only with bearer auth and network policy | Allowed |
/webhook |
Allowed only with HMAC secret and repo allowlist | Allowed |
/health |
Blocked | Allowed |
/ready |
Blocked | Allowed |
/status |
Blocked | Allowed |
For webhook service mode, use a canonical clone base URL and keep one organization/owner per CCG instance unless the repo names are guaranteed unique:
docker run -d -p 8080:8080 \
-e CCG_HTTP_BEARER_TOKEN="$CCG_HTTP_BEARER_TOKEN" \
-e CCG_DB_DRIVER=postgres \
-e CCG_DB_DSN="$CCG_DB_DSN" \
-e CCG_REPO_ROOT=/data/repos \
-e CCG_WEBHOOK_SECRET \
-v ccg-repos:/data/repos \
--entrypoint ccg-server ccg \
--http-addr :8080 \
--allow-repo "acme/*" \
--repo-clone-base-url https://github.comFor the mounted default local SQLite database, use an explicit migration command when upgrading CCG against an existing schema:
docker run --rm \
-v $(pwd):/repo --entrypoint ccg ccg \
migrateFor PostgreSQL, custom SQLite DSNs, or other non-default runtime setups, pass
the matching database driver and DSN to ccg migrate before starting runtime
commands.
Connect from .mcp.json:
{
"mcpServers": {
"ccg": {
"type": "streamable-http",
"url": "http://localhost:8080/mcp",
"headers": {
"Authorization": "Bearer replace-with-a-long-random-token"
}
}
}
}Docker images include the built Wiki UI at /usr/share/ccg/wiki, and the
default container command enables it with --wiki-dir /usr/share/ccg/wiki.
Standalone binaries do not embed Wiki assets. For binary deployments, download
ccg-wiki-dist.tar.gz from the release page, extract it, and pass the extracted
directory to ccg-server:
ccg-server \
--http-addr :8080 \
--http-bearer-token "$CCG_HTTP_BEARER_TOKEN" \
--wiki-dir ./wikiThe static /wiki app shell is served without request headers so browsers can
open it directly. /wiki/api/* uses the same bearer token as /mcp; the UI
prompts for that token when the API returns 401.
Run ccg build for each served namespace before opening the Wiki so DB-backed
tree navigation, search, and document discovery have graph rows to read. ccg docs --out docs remains useful for generated Markdown and the wiki-index.json
compatibility snapshot. The Wiki Graph tab
reads graph nodes and edges directly from the configured database via
/wiki/api/graph, so it reflects the latest ccg build or webhook sync state.
SQLite is the simplest choice for local, single-user workflows: one repository,
manual ccg build / ccg update, and a database file that can be recreated if
needed.
Use PostgreSQL when CCG is operated as a service:
- Team-shared MCP server or multiple concurrent MCP clients
- Webhook sync enabled for ongoing repository updates
- Multiple repositories or namespaces in one server database
- Operational backup, restore, monitoring, or remote access requirements
- Roughly 50k+ search documents or 100k+ graph nodes
For larger deployments, PostgreSQL should be treated as the default. At around 300k+ graph nodes, multiple always-synced repositories, or frequent webhook updates, SQLite is likely to become an operational bottleneck. See Operations for deployment profiles and scale signals.
# PostgreSQL requires an explicit migration step before runtime commands.
docker run --rm \
-e CCG_DB_DRIVER=postgres \
-e CCG_DB_DSN="host=db user=ccg password=ccg dbname=ccg sslmode=disable" \
--entrypoint ccg ccg \
migrate
docker run -d -p 8080:8080 \
-e CCG_HTTP_BEARER_TOKEN="$CCG_HTTP_BEARER_TOKEN" \
-e CCG_DB_DRIVER=postgres \
-e CCG_DB_DSN="host=db user=ccg password=ccg dbname=ccg sslmode=disable" \
-v $(pwd):/repo --entrypoint sh ccg \
-c "ccg build /repo && ccg-server --http-addr :8080"The one-shot migration command above should be run before build, serve, or other runtime commands.
docker compose up -dThe full-stack pipeline test can also be run with Docker Compose. See the Development Guide for details.
make container-artifacts
CONTAINER_ARCH="$(go env GOARCH)" docker compose -f docker-compose.integration.yml up -d --build
docker compose -f docker-compose.integration.yml down -v