Files
MISC_DOCKER_COMPOSE_FILES/Documize/README.md
T
2026-09-13 20:27:51 +01:00

444 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
# 📚 Documize Community — Docker Deployment
**Self-hosted knowledge management · v5.14.0 · MySQL 8 · Docker Compose**
[![Documize](https://img.shields.io/badge/Documize-v5.14.0-2563EB?style=for-the-badge&logo=gitbook&logoColor=white)](https://github.com/documize/community)
[![MySQL](https://img.shields.io/badge/MySQL-8.0-4479A1?style=for-the-badge&logo=mysql&logoColor=white)](https://hub.docker.com/_/mysql)
[![Docker](https://img.shields.io/badge/Docker-Compose-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://docs.docker.com/compose/)
[![License](https://img.shields.io/badge/License-GNU_AGPL_v3-22C55E?style=for-the-badge)](https://www.gnu.org/licenses/agpl-3.0.en.html)
A production-ready Docker Compose stack for [Documize Community](https://github.com/documize/community) — an open-source, self-hosted alternative to Confluence, built with Go + EmberJS.
[Quick Start](#-quick-start) · [Configuration](#-configuration) · [Architecture](#-architecture) · [Operations](#-day-to-day-operations) · [Troubleshooting](#-troubleshooting)
</div>
---
## ✨ Features
- **Single binary deployment** — Documize ships as one statically-linked Go binary; no runtime dependencies beyond a database
- **Zero reboot-loop risk** — Init-container pattern separates the one-time binary download from the always-running app container
- **Full-text search** — MySQL configured with `ft-min-word-len=3` and `utf8mb4` collation as required by Documize
- **Secret-free Compose file** — All credentials live in `.env`; `docker-compose.yml` contains no plaintext passwords
- **Named volume persistence** — Both database data and the app binary survive container restarts and upgrades
- **SMTP support** — Optional email notifications configured entirely via environment variables
---
## 📋 Prerequisites
| Requirement | Minimum version |
|---|---|
| Docker Engine | 24.0+ |
| Docker Compose | v2.20+ (included with Docker Desktop) |
| Available port | TCP `5001` (configurable) |
| RAM | 512 MB free (1 GB recommended) |
| Disk | 2 GB free |
| Internet | Required on first start to download the Documize binary (~25 MB) |
---
## 🚀 Quick Start
```bash
# 1. Clone or download this repository
git clone https://github.com/your-org/documize-docker.git
cd documize-docker
# 2. Create your environment file from the template
cp .env.template .env
# 3. Generate and set your secrets
echo "MYSQL_PASSWORD=$(openssl rand -base64 24)"
echo "MYSQL_ROOT_PASSWORD=$(openssl rand -base64 24)"
echo "DOCUMIZE_SALT=$(openssl rand -hex 32)"
# Paste each value into .env
# 4. Protect the file and add to .gitignore
chmod 600 .env
echo ".env" >> .gitignore
# 5. Start the stack
docker compose up -d
# 6. Watch the logs until Documize is ready (~3060 s)
docker compose logs -f
# 7. Open the setup wizard
open http://localhost:5001
```
> **Activation key** — The Community edition requires a free activation key. Register your email at [documize.com/community/get-started](https://www.documize.com/community/get-started) to receive one instantly.
---
## 🏗 Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Docker Host │
│ │
│ ┌──────────────┐ exits 0 ┌─────────────────────────┐ │
│ │ documize-init│ ──────────► │ app_bin volume │ │
│ │ (alpine:3.19)│ downloads │ /app/bin/documize │ │
│ │ restart: no │ binary once └──────────┬──────────────┘ │
│ └──────────────┘ │ mounts │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ documize-app (alpine:3.19) │ │
│ │ restart: unless-stopped │ │
│ │ exec /app/bin/documize │◄───┼── :5001
│ └────────────────────────┬────────────────────────────┘ │
│ │ TCP 3306 (internal only) │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ documize-db (mysql:8) │ │
│ │ restart: unless-stopped │ │
│ │ healthcheck: mysqladmin ping │ │
│ └────────────────────────┬────────────────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ db_data │ │
│ │ volume │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
### Startup Sequence
1. `documize-init` starts → installs `curl` → downloads binary to `app_bin` volume → **exits 0**
2. `documize-db` starts → MySQL initialises → healthcheck passes ✅
3. `documize-app` starts (only after both conditions above are met) → exec's binary → serves on `:5001`
### Why the Init-Container Pattern?
Downloading a binary inside the main container's command creates a reboot loop: any failure causes Docker to restart the container, which retriggers the download. Separating the download into a `restart: "no"` init container means the main app container only ever does one thing — run the binary — with no network calls or failure modes on restart.
---
## ⚙️ Configuration
### File Layout
```
documize-docker/
├── docker-compose.yml # Stack definition — references ${VARS} from .env
├── .env.template # Template — copy to .env and fill in secrets
├── .env # Your secrets — NEVER commit this file
└── README.md # This file
```
### Step 1 — Set up your `.env` file
Copy the template and fill in all values marked ⚠️:
```bash
cp .env.template .env
```
### Step 2 — Environment Variable Reference
#### 🗄️ MySQL Database
| Variable | Default | Required | Description |
|---|---|---|---|
| `MYSQL_DATABASE` | `documize` | Pre-filled | Database name created on first start |
| `MYSQL_USER` | `documize` | Pre-filled | MySQL user Documize connects as |
| `MYSQL_PASSWORD` | — | ⚠️ **Change** | Password for the `documize` MySQL user. Must match the DSN in `DOCUMIZEDB`. Generate: `openssl rand -base64 24` |
| `MYSQL_ROOT_PASSWORD` | — | ⚠️ **Change** | MySQL root password for admin access. Not used by Documize. Generate: `openssl rand -base64 24` |
#### 🚀 Documize Application
| Variable | Default | Required | Description |
|---|---|---|---|
| `DOCUMIZE_PORT` | `5001` | Pre-filled | Host port Documize is exposed on. Change the left side of the `ports` mapping. |
| `DOCUMIZE_SALT` | — | ⚠️ **Change** | Password hashing salt. Must be ≥ 32 random characters. Generate: `openssl rand -hex 32`. **Set once — never change after first run.** |
#### 📧 SMTP Email (Optional)
All five SMTP variables must be set to enable email. Leave `SMTP_HOST` blank to disable.
| Variable | Default | Description |
|---|---|---|
| `SMTP_HOST` | _(blank)_ | SMTP server hostname (e.g. `smtp.gmail.com`) |
| `SMTP_PORT` | `587` | SMTP port — `587` for STARTTLS, `465` for SSL/TLS |
| `SMTP_USER` | _(blank)_ | SMTP authentication username |
| `SMTP_PASSWORD` | _(blank)_ | SMTP authentication password or app-specific password |
| `SMTP_SENDER` | `documize@example.com` | From address on outgoing emails |
---
### MySQL Startup Flags
These flags are passed to MySQL 8 via the `command` key in `docker-compose.yml` and are **required** for Documize to function correctly. Do not remove them.
| Flag | Value | Purpose |
|---|---|---|
| `--character-set-server` | `utf8mb4` | Full Unicode support including emoji |
| `--collation-server` | `utf8mb4_unicode_ci` | Case-insensitive Unicode collation |
| `--ft-min-word-len` | `3` | Minimum word length for full-text search index — Documize requires exactly `3` |
| `--innodb-file-per-table` | `1` | Each table in its own `.ibd` file — improves storage reclaim |
| `--max-allowed-packet` | `256M` | Maximum packet size for large document imports |
---
### Changing the Host Port
Edit the `ports` mapping in `docker-compose.yml` **and** the `DOCUMIZE_PORT` value in `.env`:
```yaml
# docker-compose.yml
ports:
- "${DOCUMIZE_PORT}:5001" # host:container
```
```bash
# .env
DOCUMIZE_PORT=8080
```
---
### Named Volumes
| Volume | Mount path | Purpose |
|---|---|---|
| `db_data` | `/var/lib/mysql` | All MySQL data — content, users, settings. Never delete unless wiping everything. |
| `app_bin` | `/app/bin` | The Documize binary. Safe to delete to force a re-download on next start. |
---
## 🔒 Security
### Checklist
- [ ] `MYSQL_PASSWORD` changed from placeholder
- [ ] `MYSQL_ROOT_PASSWORD` changed from placeholder
- [ ] `DOCUMIZE_SALT` generated with `openssl rand -hex 32`
- [ ] `.env` added to `.gitignore`
- [ ] `.env` permissions set to `600` (`chmod 600 .env`)
- [ ] MySQL `ports` mapping removed from `docker-compose.yml` (production only)
- [ ] Documize placed behind a reverse proxy with TLS (production only)
### Remove the Database Port Mapping (Production)
The `db` service does not expose a port by default — MySQL is only reachable within the `documize_net` Docker network. If you added a port for local debugging, remove it before deploying:
```yaml
# db service — remove or comment out for production:
# ports:
# - "3306:3306"
```
### Reverse Proxy with TLS
Documize serves plain HTTP. In production, terminate TLS at a reverse proxy. Example **Caddy** config:
```
docs.example.com {
reverse_proxy localhost:5001
}
```
Example **Nginx** config:
```nginx
server {
listen 443 ssl;
server_name docs.example.com;
ssl_certificate /etc/ssl/certs/docs.crt;
ssl_certificate_key /etc/ssl/private/docs.key;
location / {
proxy_pass http://localhost:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
---
## 📅 Day-to-Day Operations
### Start / Stop / Restart
```bash
docker compose up -d # start all services (detached)
docker compose stop # graceful stop — data preserved
docker compose start # resume after stop
docker compose restart # restart all services
docker compose down # stop and remove containers (volumes kept)
docker compose down -v # ⚠️ DESTRUCTIVE — removes containers AND volumes
```
### View Logs
```bash
docker compose logs -f # all services, follow
docker compose logs -f app # Documize app only
docker compose logs -f db # MySQL only
docker compose logs --tail=100 app # last 100 lines
```
### Check Status
```bash
docker compose ps
```
Expected healthy state:
```
NAME IMAGE STATUS
documize-init alpine:3.19 Exited (0) ← correct: one-shot
documize-db mysql:8 healthy
documize-app alpine:3.19 running
```
### Open a MySQL Shell
```bash
docker exec -it documize-db mysql -u documize -p documize
# enter MYSQL_PASSWORD when prompted
```
---
## 💾 Backup & Restore
### Backup the Database
```bash
docker exec documize-db \
mysqldump -u documize -p"${MYSQL_PASSWORD}" documize \
> documize-backup-$(date +%Y%m%d-%H%M%S).sql
```
### Restore the Database
```bash
docker exec -i documize-db \
mysql -u documize -p"${MYSQL_PASSWORD}" documize \
< documize-backup-20240101-120000.sql
```
### Backup the Raw Volume (optional)
```bash
docker run --rm \
-v documize_db_data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/db_data-$(date +%Y%m%d).tar.gz -C /data .
```
---
## ⬆️ Upgrading Documize
> ⚠️ **Always back up the database before upgrading.**
```bash
# 1. Back up
docker exec documize-db mysqldump -u documize -p"${MYSQL_PASSWORD}" documize > pre-upgrade-backup.sql
# 2. Stop the stack
docker compose down
# 3. Remove the cached binary to force re-download of the new version
docker volume rm documize_app_bin
# 4. Update the download URL in docker-compose.yml (app-init command) to the new version
# 5. Start and watch for successful migration messages
docker compose up -d
docker compose logs -f app
```
Documize runs database schema migrations automatically on startup.
---
## 🐛 Troubleshooting
| Symptom | Cause | Resolution |
|---|---|---|
| `app-init` exits with code `127` | `curl` not found — `apk` failed | Check internet connectivity and retry: `docker compose down -v && docker compose up -d` |
| `app-init` exits with code `22` or `28` | Binary download failed | Check outbound HTTPS access to `community-downloads.s3.us-east-2.amazonaws.com` |
| `documize-app` keeps restarting | MySQL not healthy or DSN mismatch | Run `docker compose logs db`. Verify `MYSQL_PASSWORD` in `.env` matches the password in `DOCUMIZEDB` |
| Setup wizard shows DB connection error | DSN credentials mismatch | Ensure `MYSQL_PASSWORD` in `.env` is identical to the password in the `DOCUMIZEDB` connection string |
| Port `5001` already in use | Port conflict on host | Change `DOCUMIZE_PORT` in `.env` and restart |
| `app-init` exits with code `0` but binary won't run | Wrong CPU architecture | The default binary is `linux-amd64`. On ARM (e.g. Raspberry Pi, Apple Silicon Linux), replace the download URL with the `linux-arm64` binary |
| Full-text search returns no results | MySQL FTS config missing | Confirm `--ft-min-word-len=3` is present in the `db` `command` block |
| Lost `DOCUMIZE_SALT` — users locked out | Salt cannot be recovered | Restore from a database backup taken before the salt was changed |
| Docker Compose variable not substituted | `.env` file missing or wrong path | Ensure `.env` is in the **same directory** as `docker-compose.yml` |
---
## 📁 File Reference
```
.
├── docker-compose.yml # Stack definition — edit to change ports and resource limits
├── .env.template # Commit this — safe template with no real secrets
├── .env # Do NOT commit — your actual secrets
└── README.md # This file
```
| Docker resource | Type | Purpose |
|---|---|---|
| `documize-db` | Container | MySQL 8 database |
| `documize-init` | Container | One-shot binary downloader |
| `documize-app` | Container | Documize application |
| `documize_net` | Network | Private bridge — only `app` can reach `db` |
| `db_data` | Volume | MySQL data directory |
| `app_bin` | Volume | Documize binary cache |
---
## 🆘 Quick-Reference Commands
```bash
# ── Setup ──────────────────────────────────────────────────────────────────────
cp .env.template .env && chmod 600 .env # create secrets file
openssl rand -hex 32 # generate DOCUMIZE_SALT
openssl rand -base64 24 # generate a password
# ── Stack lifecycle ────────────────────────────────────────────────────────────
docker compose up -d # start
docker compose down # stop (data kept)
docker compose down -v # ⚠️ wipe everything
docker compose logs -f # live logs
docker compose ps # status
# ── Database ───────────────────────────────────────────────────────────────────
docker exec -it documize-db mysql -u documize -p documize # MySQL shell
docker exec documize-db mysqldump -u documize -p"<pw>" documize > backup.sql
# ── Upgrades ───────────────────────────────────────────────────────────────────
docker compose down && docker volume rm documize_app_bin && docker compose up -d
```
---
## 📄 License
Documize Community edition is licensed under the **GNU Affero General Public License v3 (AGPL-3.0)**.
See [LICENSE](https://github.com/documize/community/blob/master/LICENSE) in the upstream repository.
This Docker configuration is provided as-is for self-hosting purposes.
---
<div align="center">
Made with ❤️ for the self-hosting community · [Documize upstream](https://github.com/documize/community) · [Report an issue](https://github.com/your-org/documize-docker/issues)
</div>