136 lines
7.5 KiB
Markdown
136 lines
7.5 KiB
Markdown
# Docker quick start
|
|
|
|
The fastest way to run BottleCRM locally is Docker Compose. It brings up PostgreSQL, Redis, the
|
|
Django API, two Celery processes and the SvelteKit frontend from one file, using the checked-in
|
|
`.env.docker` for configuration.
|
|
|
|
## Prerequisites
|
|
|
|
- Docker Engine with the Compose v2 plugin (the `docker compose` subcommand, not the standalone
|
|
`docker-compose` binary: `docker-compose.yml` is written for the plugin).
|
|
- A clone of the repository, with `docker-compose.yml` at its root.
|
|
|
|
## Clone and configure
|
|
|
|
All commands below run from the repository root, the directory that contains
|
|
`docker-compose.yml` and `Dockerfile`.
|
|
|
|
`.env.docker` is checked into the repository with working development defaults and is loaded by
|
|
every service in `docker-compose.yml`. You don't need to copy or edit anything to get a working
|
|
stack. If you do want to override a value locally (for example to add Google OAuth credentials),
|
|
create `.env.docker.local` next to it, `docker-compose.yml` loads it as an optional, gitignored
|
|
second `env_file` whose values win over `.env.docker`.
|
|
|
|
The variables `.env.docker` actually defines are:
|
|
|
|
| Variable | Purpose |
|
|
|---|---|
|
|
| `SECRET_KEY` | Django secret key. The shipped value is an insecure dev placeholder. |
|
|
| `DEBUG` | `True` in the dev compose file. This is also what allows `devlogin` to run (see [First sign-in](first-sign-in.md)). |
|
|
| `ENV_TYPE` | `dev`. |
|
|
| `ALLOWED_HOSTS` | `localhost,127.0.0.1,backend`. |
|
|
| `DOMAIN_NAME` | `http://localhost:8000`. |
|
|
| `DBNAME`, `DBUSER`, `DBPASSWORD`, `DBHOST`, `DBPORT` | Connection details the Django `backend` (and Celery) containers use to reach `db`. |
|
|
| `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD` | Used only by the `db` service itself to create the database and its own superuser role. |
|
|
| `CELERY_BROKER_URL`, `CELERY_RESULT_BACKEND` | Both point at the `redis` service, database `0`. |
|
|
| `DEFAULT_FROM_EMAIL`, `ADMIN_EMAIL`, `ADMIN_PASSWORD` | Console email backend (dev), and the credentials used to bootstrap a Django admin superuser. See [What you got](#what-you-got). |
|
|
| `CORS_ALLOW_ALL` | `True` for local development. |
|
|
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | Blank by default; Google sign-in is disabled until both are set. The redirect URI is not a setting: the frontend sends it in the request body on each call. |
|
|
| `PUBLIC_DJANGO_API_URL` | The API origin the frontend's server-side code calls, `http://backend:8000`. It uses the compose service name because `localhost` inside the frontend container is the container itself. Your browser still reaches the API at `http://localhost:8000`. |
|
|
|
|
## Start the stack
|
|
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
This builds and starts six services, defined in `docker-compose.yml`:
|
|
|
|
| Service | Image / build | Host port |
|
|
|---|---|---|
|
|
| `db` | `postgres:16-alpine` | `5432` |
|
|
| `redis` | `redis:7-alpine` | `6379` |
|
|
| `backend` | built from the repo root `Dockerfile` | `8000` |
|
|
| `celery-worker` | same image as `backend`, runs `celery -A crm worker --loglevel=info` |. |
|
|
| `celery-beat` | same image as `backend`, runs `celery -A crm beat --loglevel=info` |, |
|
|
| `frontend` | built from `frontend/Dockerfile` | `5181` |
|
|
|
|
`backend`, `celery-worker` and `celery-beat` all wait for `db` and `redis` to report healthy
|
|
before starting. The `backend` container's entrypoint (`docker/backend/entrypoint.sh`) waits for
|
|
PostgreSQL to accept connections, runs `migrate`, runs `create_default_admin`, collects static
|
|
files, and then starts the Django dev server on `0.0.0.0:8000`.
|
|
|
|
**The database role matters.** `db` starts as the `postgres` superuser (from `POSTGRES_USER`).
|
|
That account exists only so the container can create the `crm_db` database. On first boot,
|
|
`docker/postgres/init-rls-user.sql` runs automatically (via Postgres's
|
|
`/docker-entrypoint-initdb.d/` mechanism) and creates a second, non-superuser role, `crm_user`,
|
|
granting it the privileges it needs on `crm_db`. The Django containers connect as `crm_user`
|
|
(`DBUSER` in `.env.docker`), never as `postgres`. This is required, not incidental: PostgreSQL
|
|
Row-Level Security is bypassed entirely for a superuser connection, so if the app ever connected
|
|
as `postgres`, every RLS policy in the schema would be silently inert and tenant isolation would
|
|
depend on application-level filtering alone.
|
|
|
|
## Migrate and seed
|
|
|
|
`entrypoint.sh` already runs `migrate` on every container start, so the schema is up to date as
|
|
soon as `backend` reports it's serving. To load demo data, run the seeder inside the running
|
|
`backend` container:
|
|
|
|
```bash
|
|
docker compose exec backend python manage.py seed_data --email you@example.com
|
|
```
|
|
|
|
`seed_data` creates an organization named **`MicroPyramid`** (the first organization it creates
|
|
is always named this, specifically so local-dev workflows have a known, stable name to sign in
|
|
against) and an **admin profile** for the user you passed with `--email`, along with a full set
|
|
of demo leads, accounts, contacts, opportunities, cases, tasks, invoices and more. Re-running the
|
|
command reuses the existing `MicroPyramid` org and admin user rather than creating duplicates.
|
|
|
|
You can also run migrations manually, the same way you'd run any other management command against
|
|
the container:
|
|
|
|
```bash
|
|
docker compose exec backend python manage.py migrate
|
|
```
|
|
|
|
## Sign in
|
|
|
|
With `DEBUG=True` (the default in `.env.docker`), the fastest way in is `devlogin`, a
|
|
management command that mints a JWT pair directly, without going through Google OAuth or email.
|
|
Full details, including how it resolves `--org` and what it requires of the target user, are in
|
|
[First sign-in](first-sign-in.md). For the org and user you just seeded:
|
|
|
|
```bash
|
|
docker compose exec backend python manage.py devlogin you@example.com --org MicroPyramid
|
|
```
|
|
|
|
This prints an access token, a refresh token, and the `MicroPyramid` org's UUID, already bound
|
|
into the token. See [First sign-in](first-sign-in.md) for how to use them from the frontend at
|
|
`http://localhost:5181`.
|
|
|
|
## What you got
|
|
|
|
After `docker compose up --build` and one `seed_data` run, you have:
|
|
|
|
- A PostgreSQL 16 database (`crm_db`) with RLS-enforcing policies applied by the migrations.
|
|
- A Django API on `http://localhost:8000`, running under the dev server (not a production WSGI
|
|
server. This compose file is for development).
|
|
- A Celery worker and a Celery beat scheduler, both connected to the `redis` service, running the
|
|
periodic and background tasks registered in `backend/crm/celery.py`.
|
|
- A SvelteKit frontend on `http://localhost:5181`, which reaches the API over the compose network at `PUBLIC_DJANGO_API_URL=http://backend:8000`.
|
|
- A Django admin superuser, created automatically by `create_default_admin` on first boot, using
|
|
`ADMIN_EMAIL` / `ADMIN_PASSWORD` from `.env.docker` (`admin@localhost` / `admin` unless you
|
|
override them). This account can sign in to Django's own `/admin/` site; it does not have a CRM
|
|
organization profile, so it can't sign in to the CRM app itself unless you also give it a
|
|
profile via `seed_data` or the org-creation flow.
|
|
- If you ran `seed_data`, an org named `MicroPyramid` with an admin profile for the email you
|
|
passed, plus a large set of demo records.
|
|
|
|
## Next steps
|
|
|
|
- [First sign-in](first-sign-in.md). The three ways to get a session, including the exact
|
|
`devlogin` invocation and what Google OAuth and magic links need.
|
|
- [Demo data and packs](demo-data.md), what `seed_data` creates in detail, and how vertical packs
|
|
layer industry-specific pipelines and sample records on top of it.
|
|
- If Docker isn't the right fit, [Manual setup](manual-setup.md) covers running the backend,
|
|
database, Redis, Celery and frontend directly on your machine.
|