This commit is contained in:
jpmvaz
2026-09-13 20:27:51 +01:00
commit 37b00787b9
23 changed files with 2581 additions and 0 deletions
+443
View File
@@ -0,0 +1,443 @@
<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>