Files
2026-09-13 20:27:51 +01:00
..
2026-09-13 20:27:51 +01:00
2026-09-13 20:27:51 +01:00
2026-09-13 20:27:51 +01:00

📚 Documize Community — Docker Deployment

Self-hosted knowledge management · v5.14.0 · MySQL 8 · Docker Compose

Documize MySQL Docker License

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=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

# 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 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 ⚠️:

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_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:

# 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