answerLoopsanswerLoops Docs
Self-Hosting

Docker Setup

Running answerLoops with Docker Compose.

Everything here assumes you've already cloned the repo and filled in a real .env.local — see the self-host quickstart if you haven't done that part yet. Docker Compose reads that file; it doesn't generate secrets or register OAuth apps for you.

Run a published image (no build)

Official images are published to the GitHub Container Registry, so you can run answerLoops without building anything:

docker compose -f docker-compose.ghcr.yml up -d

That pulls ghcr.io/answerloops/answerloops:latest and starts both the app and the bot from it. First run takes as long as the download rather than as long as a Next.js build, which on a modest machine is the difference between a minute and quarter of an hour.

Images are built for linux/amd64 and linux/arm64, so Apple Silicon runs natively rather than under emulation.

Pinning a version

latest moves when a new release is published. For anything you rely on staying put, pin a version instead:

ANSWERLOOPS_IMAGE=ghcr.io/answerloops/answerloops:1.4.0 \
  docker compose -f docker-compose.ghcr.yml up -d

Available tags are listed on the package page. Alongside each release there is a main tag built from the tip of the default branch, and a sha-<commit> tag for pinning to an exact commit.

Which file to use

docker-compose.ymllocal development — builds from source, includes Postgres
docker-compose.ghcr.ymlself-hosting — pulls a published image, brings your own Postgres
docker-compose.prod.ymlself-hosting from source — builds locally, brings your own Postgres

The published-image path expects DATABASE_URL in .env to point at a Postgres you run: the compose file deliberately does not start one, because a database inside the same compose project is convenient for development and the wrong default for anything holding real data.

Both services run the same image and differ only in their command, so there is no second image to keep in step.

Start

docker compose up --build

On first run this:

  1. Builds the Next.js app image
  2. Starts Postgres with a named volume (postgres-data) for persistence
  3. Runs Drizzle migrations automatically
  4. Serves the app on http://localhost:3000

Stop (keep data)

docker compose down

Never run docker compose down -v. The -v flag deletes named volumes, which includes your Postgres data. All articles, tickets, and org settings will be lost.

Rebuild after code changes

docker compose up --build

View logs

# All services
docker compose logs -f

# App only
docker compose logs app -f

# Postgres only
docker compose logs postgres -f

Access the database

docker compose exec postgres psql -U community -d community

Common queries:

-- List all tables
\dt

-- Check org onboarding status
SELECT id, name, onboarded_at FROM orgs;

-- Check users
SELECT id, email, provider FROM users;

-- Exit
\q

Named volumes

VolumeContents
postgres-dataAll database data
pnpm-storepnpm package cache (speeds up rebuilds)

Environment variables in Docker

Docker Compose reads from your .env file automatically. Any variable set in .env is available inside the app container.

To verify a variable is loaded:

docker compose exec app printenv OPENAI_API_KEY

On this page