18 KiB
📚 Documize Community — Docker Deployment
Self-hosted knowledge management · v5.14.0 · MySQL 8 · Docker Compose
A production-ready Docker Compose stack for Documize Community — an open-source, self-hosted alternative to Confluence, built with Go + EmberJS.
Quick Start · Configuration · Architecture · Operations · Troubleshooting
✨ 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=3andutf8mb4collation as required by Documize - Secret-free Compose file — All credentials live in
.env;docker-compose.ymlcontains 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
# 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 (~30–60 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 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
documize-initstarts → installscurl→ downloads binary toapp_binvolume → exits 0documize-dbstarts → MySQL initialises → healthcheck passes ✅documize-appstarts (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 ⚠️:
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:
# docker-compose.yml
ports:
- "${DOCUMIZE_PORT}:5001" # host:container
# .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_PASSWORDchanged from placeholderMYSQL_ROOT_PASSWORDchanged from placeholderDOCUMIZE_SALTgenerated withopenssl rand -hex 32.envadded to.gitignore.envpermissions set to600(chmod 600 .env)- MySQL
portsmapping removed fromdocker-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:
# 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:
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
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
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
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
docker exec -it documize-db mysql -u documize -p documize
# enter MYSQL_PASSWORD when prompted
💾 Backup & Restore
Backup the Database
docker exec documize-db \
mysqldump -u documize -p"${MYSQL_PASSWORD}" documize \
> documize-backup-$(date +%Y%m%d-%H%M%S).sql
Restore the Database
docker exec -i documize-db \
mysql -u documize -p"${MYSQL_PASSWORD}" documize \
< documize-backup-20240101-120000.sql
Backup the Raw Volume (optional)
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.
# 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
# ── 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 in the upstream repository.
This Docker configuration is provided as-is for self-hosting purposes.
Made with ❤️ for the self-hosting community · Documize upstream · Report an issue