202 lines
7.1 KiB
Markdown
202 lines
7.1 KiB
Markdown
# Docker Deployment Guide
|
|
|
|
## Quick Start
|
|
|
|
### Monochrome Only
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Visit `http://localhost:3000`
|
|
|
|
### Development
|
|
|
|
```bash
|
|
docker compose --profile dev up -d
|
|
```
|
|
|
|
Visit `http://localhost:5173` (hot-reload enabled)
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
### Profiles
|
|
|
|
Docker Compose [profiles](https://docs.docker.com/compose/how-tos/profiles/) control which services start. A service with no profile always runs. A service with a profile only runs when that profile is activated.
|
|
|
|
| Command | What starts |
|
|
| --------------------------------------------------------- | ------------------------------------ |
|
|
| `docker compose up -d` | Monochrome |
|
|
| `docker compose --profile pocketbase up -d` | Monochrome + PocketBase |
|
|
| `docker compose --profile dev up -d` | Monochrome + Dev server |
|
|
| `docker compose --profile dev --profile pocketbase up -d` | Monochrome + Dev server + PocketBase |
|
|
|
|
In `docker-compose.yml`, it looks like this:
|
|
|
|
```yaml
|
|
services:
|
|
monochrome: # no profile -- always starts
|
|
|
|
pocketbase:
|
|
profiles: ['pocketbase'] # opt-in
|
|
|
|
monochrome-dev:
|
|
profiles: ['dev'] # opt-in
|
|
```
|
|
|
|
### Override File
|
|
|
|
Docker Compose automatically merges `docker-compose.override.yml` into `docker-compose.yml` if it exists in the same directory. No flags needed.
|
|
|
|
This is useful for forks that need to add custom services or configuration (Traefik labels, extra containers, custom networks) without modifying the base `docker-compose.yml`.
|
|
|
|
The override file does not exist in the upstream repo, don't search it!
|
|
|
|
**Example** -- adding Traefik labels to PocketBase in your fork:
|
|
|
|
```yaml
|
|
# docker-compose.override.yml
|
|
services:
|
|
pocketbase:
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.http.routers.pocketbase.rule=Host(`pocketbase.example.com`)
|
|
- traefik.http.routers.pocketbase.entrypoints=websecure
|
|
- traefik.http.routers.pocketbase.tls.certresolver=letsencrypt
|
|
- traefik.http.services.pocketbase.loadbalancer.server.port=8090
|
|
networks:
|
|
- proxy-network
|
|
|
|
networks:
|
|
proxy-network:
|
|
external: true
|
|
```
|
|
|
|
**Example** -- adding a custom service in your fork:
|
|
|
|
```yaml
|
|
# docker-compose.override.yml
|
|
services:
|
|
my-custom-api:
|
|
image: my-api:latest
|
|
restart: unless-stopped
|
|
ports:
|
|
- '4000:4000'
|
|
networks:
|
|
- monochrome-network
|
|
```
|
|
|
|
Override files can extend existing services (add labels, env vars, networks) and define entirely new services. See the [Docker docs](https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/) for the full merge behavior.
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
The application is configured via environment variables. Copy `.env.example` to `.env` and edit it to match your setup.
|
|
|
|
### Authentication (Appwrite)
|
|
|
|
Monochrome uses Appwrite for user authentication. While it defaults to official instances, you can use your own self-hosted Appwrite instance:
|
|
|
|
1. Create a project in Appwrite.
|
|
2. Enable the **Google** or **Email/Password** providers in the Appwrite Console.
|
|
3. Set these variables in your `.env`:
|
|
- `APPWRITE_ENDPOINT`: Your Appwrite API endpoint (e.g., `https://auth.yourdomain.com/v1`).
|
|
- `APPWRITE_PROJECT_ID`: Your Appwrite project ID (e.g., `auth-for-monochrome`).
|
|
|
|
### Database (PocketBase)
|
|
|
|
Monochrome uses PocketBase to store user data (playlists, favorites, profiles, etc.). You can run it alongside Monochrome using the `pocketbase` profile:
|
|
|
|
```bash
|
|
docker compose --profile pocketbase up -d
|
|
```
|
|
|
|
#### PocketBase Schema Note
|
|
|
|
If you are setting up a new PocketBase collection for user data, ensure it has a field named `firebase_id` (this is a legacy name we use when we first started the accounts system, we used firebase. and im too lazy to change it so yea fuck you).
|
|
|
|
---
|
|
|
|
## Portainer Deployment
|
|
|
|
Portainer can deploy directly from your GitHub fork with auto-updates on push.
|
|
|
|
### Setup
|
|
|
|
1. In Portainer, go to **Stacks > Add Stack > Repository**
|
|
2. Enter your fork URL and branch
|
|
3. Compose path: `docker-compose.yml`
|
|
4. If your fork has a `docker-compose.override.yml`, Portainer loads it automatically
|
|
5. Under **Environment variables**, add:
|
|
- `COMPOSE_PROFILES=pocketbase` (to enable PocketBase -- omit if not needed)
|
|
- `PB_ADMIN_EMAIL=your@email.com`
|
|
- `PB_ADMIN_PASSWORD=your_secure_password`
|
|
- Any other variables from `.env.example`
|
|
6. Enable **GitOps updates** to auto-redeploy on push
|
|
|
|
> **Tip:** `COMPOSE_PROFILES` is a built-in Docker Compose variable. Setting it to `pocketbase` is equivalent to passing `--profile pocketbase` on the command line.
|
|
|
|
> **Warning:** The `dev` profile is for **local development only**. It uses volume mounts to enable hot-reload, which requires the source code to be present on the host machine. Do **not** include `dev` in `COMPOSE_PROFILES` on Portainer deployments from GitHub — it will fail because there's no local source code to mount.
|
|
|
|
### Fork Workflow
|
|
|
|
To add custom services (Traefik, monitoring, etc.) to your fork:
|
|
|
|
1. Create `docker-compose.override.yml` in your fork
|
|
2. Remove the `docker-compose.override.yml` line from `.gitignore`
|
|
3. Commit both changes to your fork
|
|
4. Portainer will auto-load the override file alongside the base compose
|
|
|
|
When pulling updates from upstream (`git pull upstream main`), there are no conflicts -- the upstream repo does not have an override file.
|
|
|
|
---
|
|
|
|
## Common Operations
|
|
|
|
```bash
|
|
# View logs
|
|
docker compose logs -f
|
|
docker compose logs -f pocketbase
|
|
|
|
# Rebuild after code changes
|
|
docker compose up -d --build
|
|
|
|
# Stop everything (include all profiles you started)
|
|
docker compose --profile pocketbase down
|
|
|
|
# Stop and remove volumes (data loss!)
|
|
docker compose --profile pocketbase down -v
|
|
|
|
# Backup PocketBase data
|
|
docker compose exec pocketbase tar czf - /pb_data > backup.tar.gz
|
|
|
|
# Restore PocketBase data
|
|
docker compose exec pocketbase tar xzf - -C / < backup.tar.gz
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Production (Dockerfile)
|
|
|
|
Node.js Alpine image (multi-arch: amd64 + arm64). Installs dependencies, runs `vite build`, then serves the built files with `vite preview` on port 4173.
|
|
|
|
### Development (Dockerfile.dev)
|
|
|
|
Node.js Alpine image with source code mounted as a volume for hot-reload.
|
|
|
|
### Files
|
|
|
|
| File | Purpose | In upstream repo |
|
|
| ----------------------------- | ----------------------------- | :--------------: |
|
|
| `docker-compose.yml` | All services with profiles | Yes |
|
|
| `docker-compose.override.yml` | Fork-specific customizations | No |
|
|
| `.env.example` | Environment variable template | Yes |
|
|
| `.env` | Your local configuration | No |
|
|
| `Dockerfile` | Production build | Yes |
|
|
| `Dockerfile.dev` | Development build | Yes |
|
|
| `.dockerignore` | Build context exclusions | Yes |
|