Docker Multi Instance Setup - wiso-forschungslabor/hroot-documentation GitHub Wiki
This guide details how to host multiple independent laboratories or multiple hroot environments (e.g. production, staging, testing) on the same physical or virtual server using a shared reverse proxy and automated SSL management.
Architecture Overview
In a multi-instance deployment:
- Central Shared Proxy: A single central NGINX reverse proxy (
nginxproxy/nginx-proxy) along with an ACME Let's Encrypt companion (nginxproxy/acme-companion) runs on the host's ports80and443. - Shared Docker Network: All web application containers connect to a common Docker bridge network named
proxy-network. - Isolated Instances: Each
hrootinstance runs its own isolated application container (web), background worker (cron), and database (db), defined under a distinct Docker Compose project name. - Dynamic SSL & Routing: When an instance container starts, the central proxy automatically detects
VIRTUAL_HOSTandLETSENCRYPT_HOSTfrom its.env, dynamically configures NGINX routing, and provisions SSL certificates.
[ Internet Traffic (Port 80 / 443) ]
│
▼
┌─────────────────────────────────────┐
│ Central NGINX Proxy + ACME (SSL) │
│ (Network: proxy-network) │
└──────────────────┬──────────────────┘
│
┌──────────────────────────────┼──────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ Instance 1: ECON │ │ Instance 2: PSYCH │ │ Instance 3: MGMT │
│ Domain: econ.lab... │ │ Domain: psych.lab...│ │ Domain: mgmt.lab... │
│ DB: hroot_econ │ │ DB: hroot_psych │ │ DB: hroot_mgmt │
│ (web + cron + db) │ │ (web + cron + db) │ │ (web + cron + db) │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
Step-by-Step Walkthrough: 3 Parallel Instances
In this example, we deploy 3 isolated instances:
- Instance 1: Economics Lab (
econ.lab.example.org) - Instance 2: Psychology Lab (
psych.lab.example.org) - Instance 3: Management Lab (
mgmt.lab.example.org)
Step 1: Create the Shared Docker Network
Create the external Docker bridge network once on the host:
docker network create proxy-network
Step 2: Launch the Central Shared Proxy
- Create a dedicated directory for the proxy service:
sudo mkdir -p /srv/hroot/shared-proxy cd /srv/hroot/shared-proxy - Download or copy the shared proxy compose file (
docker/shared-proxy/docker-compose.yml):curl -sSL https://raw.githubusercontent.com/wiso-forschungslabor/hroot/master/docker/shared-proxy/docker-compose.yml -o docker-compose.yml - Start the central proxy:
docker compose up -d
The proxy will now listen on ports 80 and 443 and automatically handle SSL certificates for all connected instances.
Step 3: Set Up Instance Directories
Create isolated directories for each laboratory instance:
sudo mkdir -p /srv/hroot/instances/{econ,psych,mgmt}
Clone the repository into each instance folder:
git clone https://github.com/wiso-forschungslabor/hroot.git /srv/hroot/instances/econ
git clone https://github.com/wiso-forschungslabor/hroot.git /srv/hroot/instances/psych
git clone https://github.com/wiso-forschungslabor/hroot.git /srv/hroot/instances/mgmt
Step 4: Configure .env for Each Instance
In each instance directory, copy .env.example to .env and set unique parameters:
| Configuration Variable | Instance 1 (econ) |
Instance 2 (psych) |
Instance 3 (mgmt) |
|---|---|---|---|
APP_DOMAIN |
econ.lab.example.org |
psych.lab.example.org |
mgmt.lab.example.org |
CONTACT_EMAIL |
[email protected] |
[email protected] |
[email protected] |
LETSENCRYPT_EMAIL |
[email protected] |
[email protected] |
[email protected] |
DATABASE_NAME |
hroot_econ |
hroot_psych |
hroot_mgmt |
DATABASE_USERNAME |
hroot_econ |
hroot_psych |
hroot_mgmt |
DATABASE_PASSWORD |
(Secret Password 1) | (Secret Password 2) | (Secret Password 3) |
DB_PORT |
33061 (Host binding) |
33062 |
33063 |
APP_PORT |
3001 |
3002 |
3003 |
SECRET_KEY_BASE |
(Unique 64-char Hex) | (Unique 64-char Hex) | (Unique 64-char Hex) |
(Tip: Generate unique secret keys with bundle exec rails secret or openssl rand -hex 64).
Step 5: Start Each Instance
Start each instance using Docker Compose with the shared-proxy.yml override and a distinct project name (-p):
# 1. Economics Lab
cd /srv/hroot/instances/econ
docker compose -p hroot-econ -f docker-compose.yml -f docker/overrides/shared-proxy.yml up -d --build
# 2. Psychology Lab
cd /srv/hroot/instances/psych
docker compose -p hroot-psych -f docker-compose.yml -f docker/overrides/shared-proxy.yml up -d --build
# 3. Management Lab
cd /srv/hroot/instances/mgmt
docker compose -p hroot-mgmt -f docker-compose.yml -f docker/overrides/shared-proxy.yml up -d --build
Step 6: Run Initial Database Setup & Create Admin Account
Execute bin/docker-setup inside each instance container to migrate tables and create the initial administrator:
# Instance 1
cd /srv/hroot/instances/econ
docker compose -p hroot-econ exec web bin/docker-setup
# Instance 2
cd /srv/hroot/instances/psych
docker compose -p hroot-psych exec web bin/docker-setup
# Instance 3
cd /srv/hroot/instances/mgmt
docker compose -p hroot-mgmt exec web bin/docker-setup
Managing Multi-Instance Deployments
Check Running Containers
docker ps
View Logs of a Specific Instance
cd /srv/hroot/instances/econ
docker compose -p hroot-econ logs -f web cron
Updating a Specific Instance
cd /srv/hroot/instances/econ
git pull origin master
docker compose -p hroot-econ -f docker-compose.yml -f docker/overrides/shared-proxy.yml up -d --build
docker compose -p hroot-econ exec web bundle exec rake db:migrate RAILS_ENV=production