mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-07-04 08:51:36 +02:00
Split Docker Compose into base/dev/prod/traefik overrides with multi-instance support
- Split docker-compose.yml into base config + environment overrides - docker-compose.dev.yml: port mappings for local development - docker-compose.prod.yml: external proxy-net network, no exposed ports - docker-compose.traefik.yml: optional Traefik auto-discovery labels - Parameterize container and volume names with COMPOSE_PROJECT_NAME - Default: hub-dev (containers: hub-dev-api, volumes: hub-dev_hub_data) - Override per instance for multi-instance deployments (hub-prod, hub-beta) - Add Makefile with build/up/down/logs/backup/restore targets - Add TRAEFIK_DOMAIN env var for Traefik routing configuration - Update UPGRADING.md with volume migration instructions (rename + copy methods) - Update README.md with multi-instance deployment and backup/restore sections
This commit is contained in:
@@ -29,6 +29,17 @@
|
||||
# =============================================================================
|
||||
# These settings apply to all services
|
||||
|
||||
# Docker Compose project name
|
||||
# Used as a prefix for container names (e.g., hub-dev-api) and volume names
|
||||
# (e.g., hub-dev_hub_data). Change per instance when running multiple deployments
|
||||
# on the same Docker host (e.g., hub-prod, hub-beta, hub-stg).
|
||||
# For multi-instance setups, see the "Multi-Instance Deployment" section in README.md.
|
||||
COMPOSE_PROJECT_NAME=hub-dev
|
||||
|
||||
# Domain name for this instance (only needed for Traefik deployments)
|
||||
# Used by docker-compose.traefik.yml to configure routing rules
|
||||
# TRAEFIK_DOMAIN=meshcore.example.com
|
||||
|
||||
# Docker image version tag to use
|
||||
# Options: latest, main, v1.0.0, etc.
|
||||
IMAGE_VERSION=latest
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
!example/data/
|
||||
/seed/
|
||||
!example/seed/
|
||||
/backup/
|
||||
/content/
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
|
||||
@@ -324,7 +324,11 @@ meshcore-hub/
|
||||
│ └── collector/ # Collector data
|
||||
│ └── meshcore.db # SQLite database
|
||||
├── Dockerfile # Docker build configuration
|
||||
└── docker-compose.yml # Docker Compose services
|
||||
├── docker-compose.yml # Docker Compose base config
|
||||
├── docker-compose.dev.yml # Development overrides (port mappings)
|
||||
├── docker-compose.prod.yml # Production overrides (proxy network)
|
||||
├── docker-compose.traefik.yml # Optional Traefik labels
|
||||
└── SCHEMAS.md
|
||||
```
|
||||
|
||||
## MQTT Topic Structure
|
||||
@@ -585,6 +589,7 @@ meshcore-hub collector
|
||||
See [PLAN.md](PLAN.md#configuration-environment-variables) for complete list.
|
||||
|
||||
Key variables:
|
||||
- `COMPOSE_PROJECT_NAME` - Docker Compose project prefix for containers and volumes (default: `hub-dev`)
|
||||
- `DATA_HOME` - Base directory for runtime data (default: `./data`)
|
||||
- `SEED_HOME` - Directory containing seed data files (default: `./seed`)
|
||||
- `CONTENT_HOME` - Directory containing custom content (pages, media) (default: `./content`)
|
||||
@@ -663,7 +668,7 @@ The database can be seeded with node tags and network members from YAML files in
|
||||
meshcore-hub collector seed
|
||||
|
||||
# With Docker Compose
|
||||
docker compose --profile seed up
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile seed up
|
||||
```
|
||||
|
||||
**Note:** Once the admin UI is enabled (`WEB_ADMIN_ENABLED=true`), tags should be managed through the web interface rather than seed files.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
ifneq (,$(wildcard ./.env))
|
||||
include .env
|
||||
export
|
||||
endif
|
||||
|
||||
PROFILES ?= mqtt core
|
||||
COMPOSE_FILES = -f docker-compose.yml -f docker-compose.dev.yml
|
||||
VOLUMES = $(COMPOSE_PROJECT_NAME)_hub_data $(COMPOSE_PROJECT_NAME)_mqtt_broker_data \
|
||||
$(COMPOSE_PROJECT_NAME)_prometheus_data $(COMPOSE_PROJECT_NAME)_alertmanager_data \
|
||||
$(COMPOSE_PROJECT_NAME)_packetcapture_data
|
||||
|
||||
.PHONY: build up down logs backup restore
|
||||
|
||||
build:
|
||||
docker compose $(COMPOSE_FILES) --profile all build --no-cache
|
||||
|
||||
up:
|
||||
docker compose $(COMPOSE_FILES) $(foreach p,$(PROFILES),--profile $(p)) up -d --force-recreate
|
||||
|
||||
down:
|
||||
docker compose $(COMPOSE_FILES) --profile all down --remove-orphans
|
||||
|
||||
logs:
|
||||
docker compose $(COMPOSE_FILES) --profile all logs -f
|
||||
|
||||
backup:
|
||||
@mkdir -p backup
|
||||
@for vol in $(VOLUMES); do \
|
||||
echo "Backing up $$vol..."; \
|
||||
docker run --rm -v $$vol:/data -v $(PWD)/backup:/backup \
|
||||
alpine tar czf /backup/$$vol-$$(date +%Y%m%d-%H%M%S).tar.gz -C / data; \
|
||||
done
|
||||
@echo "Backups saved to $(PWD)/backup/"
|
||||
|
||||
restore:
|
||||
@if [ -z "$(FILE)" ]; then echo "Usage: make restore FILE=backup/<tarball>"; exit 1; fi
|
||||
@vol=$$(basename $(FILE) | sed 's/-[0-9]\{8\}-[0-9]\{6\}\.tar\.gz//'); \
|
||||
echo "Restoring $$vol from $(FILE)..."; \
|
||||
docker run --rm -v $$vol:/data -v $(PWD)/backup:/backup \
|
||||
alpine sh -c "cd / && tar xzf /backup/$$(basename $(FILE))"
|
||||
@@ -82,12 +82,13 @@ The quickest way to get started is running the entire stack on a single machine
|
||||
|
||||
**Steps:**
|
||||
```bash
|
||||
# Create a directory, download the Docker Compose file and
|
||||
# Create a directory, download the Docker Compose files and
|
||||
# example environment configuration file
|
||||
|
||||
mkdir meshcore-hub
|
||||
cd meshcore-hub
|
||||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/docker-compose.yml
|
||||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/docker-compose.dev.yml
|
||||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/.env.example
|
||||
|
||||
# Copy and configure environment
|
||||
@@ -95,7 +96,7 @@ cp .env.example .env
|
||||
# Edit .env: set MQTT_HOST to your MQTT broker if not using the local one
|
||||
|
||||
# Start the entire stack with local MQTT broker
|
||||
docker compose --profile mqtt --profile core up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile mqtt --profile core up -d
|
||||
|
||||
# View the web dashboard
|
||||
open http://localhost:8080
|
||||
@@ -107,7 +108,29 @@ This starts all services: MQTT broker, collector, API, and web dashboard. MeshCo
|
||||
|
||||
### Docker Compose Profiles
|
||||
|
||||
Docker Compose uses **profiles** to select which services to run:
|
||||
Docker Compose uses **profiles** to select which services to run. The configuration is split across multiple files:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `docker-compose.yml` | Base shared config (services, profiles, healthchecks, environment) |
|
||||
| `docker-compose.dev.yml` | Development overrides (port mappings for direct access) |
|
||||
| `docker-compose.prod.yml` | Production overrides (external proxy network, no exposed ports) |
|
||||
| `docker-compose.traefik.yml` | Optional Traefik auto-discovery labels |
|
||||
|
||||
All `docker compose` commands require explicit file selection with `-f`:
|
||||
|
||||
```bash
|
||||
# Development (default — exposes ports for local access)
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||
|
||||
# Production (generic reverse proxy — nginx, caddy, etc.)
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
|
||||
# Production (Traefik)
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.traefik.yml up -d
|
||||
```
|
||||
|
||||
Service profiles:
|
||||
|
||||
| Profile | Services | Use Case |
|
||||
|---------|----------|----------|
|
||||
@@ -123,27 +146,112 @@ Docker Compose uses **profiles** to select which services to run:
|
||||
|
||||
```bash
|
||||
# Create database schema
|
||||
docker compose --profile migrate run --rm db-migrate
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile migrate run --rm db-migrate
|
||||
|
||||
# Seed the database
|
||||
docker compose --profile seed run --rm seed
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile seed run --rm seed
|
||||
|
||||
# Start core services with local MQTT broker
|
||||
docker compose --profile mqtt --profile core up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile mqtt --profile core up -d
|
||||
|
||||
# Or connect to external MQTT (configure MQTT_HOST in .env)
|
||||
docker compose --profile core up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile core up -d
|
||||
|
||||
# Start everything including packet capture observer
|
||||
docker compose --profile mqtt --profile core --profile receiver up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile mqtt --profile core --profile receiver up -d
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f
|
||||
|
||||
# Stop services
|
||||
docker compose down
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml down
|
||||
```
|
||||
|
||||
### Multi-Instance Deployment
|
||||
|
||||
Multiple MeshCore Hub instances can run on the same Docker host (e.g., production, beta, staging). Each instance uses a unique `COMPOSE_PROJECT_NAME` to isolate containers, volumes, and networking.
|
||||
|
||||
**1. Create a shared proxy network** (once):
|
||||
|
||||
```bash
|
||||
docker network create proxy-net
|
||||
```
|
||||
|
||||
**2. Set up each instance in its own directory:**
|
||||
|
||||
```bash
|
||||
# Production instance
|
||||
mkdir hub-prod && cd hub-prod
|
||||
cp ../docker-compose.yml ../docker-compose.prod.yml ../.env.example .
|
||||
cp .env.example .env
|
||||
# Edit .env: set COMPOSE_PROJECT_NAME=hub-prod
|
||||
```
|
||||
|
||||
```bash
|
||||
# Beta instance
|
||||
mkdir hub-beta && cd hub-beta
|
||||
cp ../docker-compose.yml ../docker-compose.prod.yml ../.env.example .
|
||||
cp .env.example .env
|
||||
# Edit .env: set COMPOSE_PROJECT_NAME=hub-beta
|
||||
```
|
||||
|
||||
**3. Configure your reverse proxy** to route traffic to the container names:
|
||||
|
||||
| Instance | API Container | Web Container |
|
||||
|----------|--------------|---------------|
|
||||
| Production | `hub-prod-api:8000` | `hub-prod-web:8080` |
|
||||
| Beta | `hub-beta-api:8000` | `hub-beta-web:8080` |
|
||||
|
||||
**4. Start each instance:**
|
||||
|
||||
```bash
|
||||
# Production (generic reverse proxy)
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml --profile core up -d
|
||||
|
||||
# Beta (with Traefik)
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.traefik.yml --profile core up -d
|
||||
```
|
||||
|
||||
Containers and volumes are automatically prefixed with the project name — no compose file edits needed per instance.
|
||||
|
||||
### Backup & Restore
|
||||
|
||||
#### Using Makefile
|
||||
|
||||
```bash
|
||||
# Back up all volumes to backup/
|
||||
make backup
|
||||
|
||||
# Restore a specific volume
|
||||
make restore FILE=backup/hub-dev_hub_data-20260414-120000.tar.gz
|
||||
```
|
||||
|
||||
#### Using shell commands
|
||||
|
||||
```bash
|
||||
# Back up all volumes
|
||||
source .env 2>/dev/null || true
|
||||
mkdir -p backup
|
||||
for vol in ${COMPOSE_PROJECT_NAME:-hub-dev}_hub_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_mqtt_broker_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_prometheus_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_alertmanager_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_packetcapture_data; do
|
||||
echo "Backing up $vol..."
|
||||
docker run --rm -v $vol:/data -v $(pwd)/backup:/backup \
|
||||
alpine tar czf /backup/$vol-$(date +%Y%m%d-%H%M%S).tar.gz -C / data
|
||||
done
|
||||
|
||||
# Restore a specific volume (volume name derived from tarball filename)
|
||||
source .env 2>/dev/null || true
|
||||
FILE=backup/${COMPOSE_PROJECT_NAME:-hub-dev}_hub_data-20260414-120000.tar.gz
|
||||
vol=$(basename "$FILE" | sed 's/-[0-9]\{8\}-[0-9]\{6\}\.tar\.gz//')
|
||||
docker run --rm -v $vol:/data -v $(pwd)/backup:/backup \
|
||||
alpine sh -c "cd / && tar xzf /backup/$(basename $FILE)"
|
||||
```
|
||||
|
||||
> **Note:** Replace `hub-dev` with your `COMPOSE_PROJECT_NAME` if using a different instance name.
|
||||
|
||||
### Manual Installation
|
||||
|
||||
```bash
|
||||
@@ -417,8 +525,7 @@ The markdown content is rendered as-is, so include your own `# Heading` if desir
|
||||
Pages automatically appear in the navigation menu and sitemap. With Docker, mount the content directory:
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml (already configured)
|
||||
volumes:
|
||||
# docker-compose.yml (already configured)volumes:
|
||||
- ${CONTENT_HOME:-./content}:/content:ro
|
||||
environment:
|
||||
- CONTENT_HOME=/content
|
||||
@@ -433,7 +540,7 @@ The database can be seeded with node tags and network members from YAML files in
|
||||
Seeding is a separate process and must be run explicitly:
|
||||
|
||||
```bash
|
||||
docker compose --profile seed up
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile seed up
|
||||
```
|
||||
|
||||
This imports data from the following files (if they exist):
|
||||
@@ -646,7 +753,10 @@ meshcore-hub/
|
||||
│ └── images/ # Custom images (logo.svg/png/jpg/jpeg/webp replace default logo)
|
||||
├── data/ # Runtime data directory (DATA_HOME, created at runtime)
|
||||
├── Dockerfile # Docker build configuration
|
||||
├── docker-compose.yml # Docker Compose services
|
||||
├── docker-compose.yml # Docker Compose base config
|
||||
├── docker-compose.dev.yml # Development overrides (port mappings)
|
||||
├── docker-compose.prod.yml # Production overrides (proxy network)
|
||||
├── docker-compose.traefik.yml # Optional Traefik labels
|
||||
├── SCHEMAS.md # Event schema documentation
|
||||
├── UPGRADING.md # Upgrade guide for breaking changes
|
||||
└── AGENTS.md # AI assistant guidelines
|
||||
|
||||
+153
-26
@@ -16,29 +16,39 @@ This guide covers upgrading from a previous MeshCore Hub release to the current
|
||||
| DB table | `event_receivers` | `event_observers` |
|
||||
| API commands | `/api/v1/commands/*` | Removed |
|
||||
| Compose profiles | `receiver`, `sender`, `mock` | `receiver` (packet-capture) |
|
||||
| Compose files | Single `docker-compose.yml` | Base + environment overrides (`.dev.yml`, `.prod.yml`) |
|
||||
| Container names | `meshcore-*` | Parameterized via `COMPOSE_PROJECT_NAME` (default: `hub-dev-*`) |
|
||||
| Volume names | `meshcore_*` | Parameterized via `COMPOSE_PROJECT_NAME` (default: `hub-dev_*`) |
|
||||
|
||||
## Step 1: Backup the Database
|
||||
## Step 1: Backup
|
||||
|
||||
**Do not skip this step.** The database migration renames columns and tables, and while it has been tested, you should always have a backup.
|
||||
**Do not skip this step.** Back up all data volumes before proceeding.
|
||||
|
||||
### Using Makefile
|
||||
|
||||
```bash
|
||||
# Create a timestamped backup of the database volume
|
||||
docker run --rm \
|
||||
-v meshcore_hub_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine tar czf /backup/meshcore-hub-db-$(date +%Y%m%d-%H%M%S).tar.gz -C / data
|
||||
make backup
|
||||
```
|
||||
|
||||
# Verify the backup was created
|
||||
ls -lh meshcore-hub-db-*.tar.gz
|
||||
### Using shell commands
|
||||
|
||||
```bash
|
||||
source .env 2>/dev/null || true
|
||||
mkdir -p backup
|
||||
for vol in ${COMPOSE_PROJECT_NAME:-hub-dev}_hub_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_mqtt_broker_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_prometheus_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_alertmanager_data \
|
||||
${COMPOSE_PROJECT_NAME:-hub-dev}_packetcapture_data; do
|
||||
docker run --rm -v $vol:/data -v $(pwd)/backup:/backup \
|
||||
alpine tar czf /backup/$vol-$(date +%Y%m%d-%H%M%S).tar.gz -C / data
|
||||
done
|
||||
```
|
||||
|
||||
To restore from backup if needed:
|
||||
|
||||
```bash
|
||||
docker run --rm \
|
||||
-v meshcore_hub_data:/data \
|
||||
-v $(pwd):/backup \
|
||||
alpine sh -c "cd / && tar xzf /backup/meshcore-hub-db-YYYYMMDD-HHMMSS.tar.gz"
|
||||
make restore FILE=backup/hub-dev_hub_data-YYYYMMDD-HHMMSS.tar.gz
|
||||
```
|
||||
|
||||
## Step 2: Stop and Remove Containers
|
||||
@@ -51,21 +61,109 @@ docker compose down --remove-orphans
|
||||
|
||||
> **Important:** Do NOT use `--volumes` / `-v`. That would delete your database. The `--remove-orphans` flag cleans up old services (like `interface-receiver`, `interface-sender`) that no longer exist in the new compose file.
|
||||
|
||||
## Step 3: Update Configuration Files
|
||||
## Step 3: Rename Docker Volumes
|
||||
|
||||
Container and volume names are now parameterized via `COMPOSE_PROJECT_NAME`. The default is `hub-dev`, so volumes are renamed from `meshcore_*` to `hub-dev_*`.
|
||||
|
||||
First, check which volumes you have:
|
||||
|
||||
```bash
|
||||
docker volume ls | grep meshcore
|
||||
```
|
||||
|
||||
### Volumes to migrate
|
||||
|
||||
These volumes always need migrating:
|
||||
|
||||
| Old Name | New Name |
|
||||
|----------|----------|
|
||||
| `meshcore_hub_data` | `hub-dev_hub_data` |
|
||||
| `meshcore_prometheus_data` | `hub-dev_prometheus_data` |
|
||||
| `meshcore_alertmanager_data` | `hub-dev_alertmanager_data` |
|
||||
| `meshcore_packetcapture_data` | `hub-dev_packetcapture_data` |
|
||||
|
||||
For the MQTT broker, it depends on your current version:
|
||||
|
||||
| Your Current Broker | Volume to Migrate | Action |
|
||||
|---------------------|-------------------|--------|
|
||||
| `meshcore-mqtt-broker` | `meshcore_mqtt_broker_data` → `hub-dev_mqtt_broker_data` | Rename or copy below |
|
||||
| Mosquitto (older) | `meshcore_mosquitto_data`, `meshcore_mosquitto_log` | **Remove** — no longer used. New volume created automatically on first run. |
|
||||
|
||||
### Option A: Rename (Docker Engine 23.0+)
|
||||
|
||||
> **Note:** `docker volume rename` is not available in all Docker builds (e.g., Docker Desktop). If the command is not found, use Option B instead.
|
||||
|
||||
```bash
|
||||
docker volume rename meshcore_hub_data hub-dev_hub_data
|
||||
docker volume rename meshcore_prometheus_data hub-dev_prometheus_data
|
||||
docker volume rename meshcore_alertmanager_data hub-dev_alertmanager_data
|
||||
docker volume rename meshcore_packetcapture_data hub-dev_packetcapture_data
|
||||
|
||||
# Only if you already have meshcore-mqtt-broker (skip if still on Mosquitto)
|
||||
docker volume rename meshcore_mqtt_broker_data hub-dev_mqtt_broker_data
|
||||
```
|
||||
|
||||
### Option B: Copy (all Docker versions)
|
||||
|
||||
If `docker volume rename` is not available in your Docker build:
|
||||
|
||||
```bash
|
||||
# For each volume: create new, copy data, remove old
|
||||
docker volume create hub-dev_hub_data
|
||||
docker run --rm -v meshcore_hub_data:/from -v hub-dev_hub_data:/to alpine sh -c "cp -a /from/. /to/"
|
||||
|
||||
docker volume create hub-dev_prometheus_data
|
||||
docker run --rm -v meshcore_prometheus_data:/from -v hub-dev_prometheus_data:/to alpine sh -c "cp -a /from/. /to/"
|
||||
|
||||
docker volume create hub-dev_alertmanager_data
|
||||
docker run --rm -v meshcore_alertmanager_data:/from -v hub-dev_alertmanager_data:/to alpine sh -c "cp -a /from/. /to/"
|
||||
|
||||
docker volume create hub-dev_packetcapture_data
|
||||
docker run --rm -v meshcore_packetcapture_data:/from -v hub-dev_packetcapture_data:/to alpine sh -c "cp -a /from/. /to/"
|
||||
|
||||
# Only if you already have meshcore-mqtt-broker (skip if still on Mosquitto)
|
||||
docker volume create hub-dev_mqtt_broker_data
|
||||
docker run --rm -v meshcore_mqtt_broker_data:/from -v hub-dev_mqtt_broker_data:/to alpine sh -c "cp -a /from/. /to/"
|
||||
|
||||
# Verify the new volumes have data, then remove old ones
|
||||
docker volume rm meshcore_hub_data meshcore_prometheus_data meshcore_alertmanager_data meshcore_packetcapture_data
|
||||
|
||||
# Only if you already have meshcore-mqtt-broker
|
||||
docker volume rm meshcore_mqtt_broker_data
|
||||
```
|
||||
|
||||
### Clean up old Mosquitto volumes (if applicable)
|
||||
|
||||
If upgrading from the Mosquitto era, remove the unused volumes:
|
||||
|
||||
```bash
|
||||
# Skip if these don't exist
|
||||
docker volume rm meshcore_mosquitto_data meshcore_mosquitto_log
|
||||
```
|
||||
|
||||
> **Note:** If any volumes show "in use", remove any stopped containers first: `docker rm -f <container_id>`.
|
||||
|
||||
> **Note:** If setting up a multi-instance deployment (e.g., `hub-prod`, `hub-beta`), use that project name instead of `hub-dev`.
|
||||
|
||||
> **Note:** After migrating volumes, you may see warnings like `volume "hub-dev_hub_data" already exists but was not created by Docker Compose. Use \`external: true\` to use an existing volume`. This is safe to ignore — it appears because the volumes were created manually during migration rather than by Docker Compose. Fresh deployments will not see this warning.
|
||||
|
||||
## Step 4: Update Configuration Files
|
||||
|
||||
Download the latest configuration files:
|
||||
|
||||
```bash
|
||||
# Download the new docker-compose.yml
|
||||
# Download the base compose file and environment overrides
|
||||
wget -O docker-compose.yml https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/main/docker-compose.yml
|
||||
wget -O docker-compose.dev.yml https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/main/docker-compose.dev.yml
|
||||
wget -O docker-compose.prod.yml https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/main/docker-compose.prod.yml
|
||||
|
||||
# Download the new .env.example for reference
|
||||
wget -O .env.example https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/main/.env.example
|
||||
```
|
||||
|
||||
Then compare your existing `.env` against the new `.env.example` and update it (see Step 4).
|
||||
Then compare your existing `.env` against the new `.env.example` and update it (see Step 5).
|
||||
|
||||
## Step 4: Migrate Your `.env` File
|
||||
## Step 5: Migrate Your `.env` File
|
||||
|
||||
### Variables to Remove
|
||||
|
||||
@@ -110,6 +208,9 @@ MQTT_WS_PORT=9001
|
||||
### Variables to Add
|
||||
|
||||
```bash
|
||||
# Docker Compose project name (container and volume prefix)
|
||||
COMPOSE_PROJECT_NAME=hub-dev
|
||||
|
||||
# MQTT subscriber authentication for the collector
|
||||
# The collector connects as a subscriber to read all published topics
|
||||
# including /internal. Set these to match your broker's SUBSCRIBER_1 config.
|
||||
@@ -131,47 +232,47 @@ PACKETCAPTURE_IATA=LOC
|
||||
|
||||
All other `PACKETCAPTURE_*` variables have sensible defaults in `docker-compose.yml` and only need to be set in `.env` if you want to override them. See `.env.example` for the full list.
|
||||
|
||||
## Step 5: Run Database Migration
|
||||
## Step 6: Run Database Migration
|
||||
|
||||
The migration renames `receiver_node_id` → `observer_node_id` across all event tables and `event_receivers` → `event_observers`:
|
||||
|
||||
```bash
|
||||
docker compose --profile core run --rm db-migrate
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile core run --rm db-migrate
|
||||
```
|
||||
|
||||
This runs automatically as part of the `core` profile, but can also be run standalone with the `migrate` profile:
|
||||
|
||||
```bash
|
||||
docker compose --profile migrate run --rm db-migrate
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile migrate run --rm db-migrate
|
||||
```
|
||||
|
||||
## Step 6: Start Services
|
||||
## Step 7: Start Services
|
||||
|
||||
### With local MQTT broker (single-host deployment)
|
||||
|
||||
```bash
|
||||
# Start everything including the MQTT broker
|
||||
docker compose --profile mqtt --profile core up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile mqtt --profile core up -d
|
||||
|
||||
# Or include packet capture on the same host
|
||||
docker compose --profile mqtt --profile core --profile receiver up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile mqtt --profile core --profile receiver up -d
|
||||
```
|
||||
|
||||
### With external MQTT broker
|
||||
|
||||
```bash
|
||||
# Start core services only (broker runs elsewhere)
|
||||
docker compose --profile core up -d
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile core up -d
|
||||
```
|
||||
|
||||
### Verify
|
||||
|
||||
```bash
|
||||
# Check all containers are running
|
||||
docker compose ps
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml ps
|
||||
|
||||
# Check collector connected to MQTT
|
||||
docker compose logs collector | grep -i "connected to mqtt"
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml logs collector | grep -i "connected to mqtt"
|
||||
|
||||
# Check the web dashboard
|
||||
open http://localhost:8080
|
||||
@@ -235,6 +336,32 @@ The following Docker Compose services have been removed:
|
||||
|
||||
The `packet-capture` service uses the [meshcore-packet-capture](https://github.com/agessaman/meshcore-packet-capture) image and is included in `docker-compose.yml` under the `receiver` profile for an easy transition.
|
||||
|
||||
### New Docker Compose File Structure
|
||||
|
||||
The Docker Compose configuration is now split into multiple files:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `docker-compose.yml` | Base shared config (services, profiles, healthchecks, environment) |
|
||||
| `docker-compose.dev.yml` | Development overrides (port mappings for direct access) |
|
||||
| `docker-compose.prod.yml` | Production overrides (external proxy network, no exposed ports) |
|
||||
| `docker-compose.traefik.yml` | Optional Traefik auto-discovery labels |
|
||||
|
||||
All `docker compose` commands now require explicit file selection:
|
||||
|
||||
```bash
|
||||
# Development (exposes ports for local access)
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||
|
||||
# Production (connects to reverse proxy network)
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
|
||||
# Production with Traefik
|
||||
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.traefik.yml up -d
|
||||
```
|
||||
|
||||
Container and volume names are parameterized via `COMPOSE_PROJECT_NAME` in `.env`. This enables multiple instances (e.g., `hub-prod`, `hub-beta`) on the same Docker host.
|
||||
|
||||
### Removed API Endpoints
|
||||
|
||||
The command dispatch API endpoints have been removed:
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# MeshCore Hub - Development Docker Compose Override
|
||||
#
|
||||
# Exposes service ports for local development and testing.
|
||||
# NOT intended for production use — use docker-compose.prod.yml instead.
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||
|
||||
services:
|
||||
mqtt:
|
||||
ports:
|
||||
- "${MQTT_PORT:-1883}:${MQTT_PORT:-1883}"
|
||||
|
||||
api:
|
||||
ports:
|
||||
- "${API_PORT:-8000}:8000"
|
||||
|
||||
web:
|
||||
ports:
|
||||
- "${WEB_PORT:-8080}:8080"
|
||||
|
||||
prometheus:
|
||||
ports:
|
||||
- "${PROMETHEUS_PORT:-9090}:9090"
|
||||
|
||||
alertmanager:
|
||||
ports:
|
||||
- "${ALERTMANAGER_PORT:-9093}:9093"
|
||||
@@ -0,0 +1,29 @@
|
||||
# MeshCore Hub - Production Docker Compose Override
|
||||
#
|
||||
# Connects api and web services to an external proxy network for
|
||||
# reverse proxy access (Traefik, Nginx, Caddy, etc.).
|
||||
# No ports are exposed directly — all traffic goes through the reverse proxy.
|
||||
#
|
||||
# Prerequisites:
|
||||
# docker network create proxy-net
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
||||
#
|
||||
# With Traefik:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.traefik.yml up -d
|
||||
|
||||
services:
|
||||
api:
|
||||
networks:
|
||||
- default
|
||||
- proxy-net
|
||||
|
||||
web:
|
||||
networks:
|
||||
- default
|
||||
- proxy-net
|
||||
|
||||
networks:
|
||||
proxy-net:
|
||||
external: true
|
||||
@@ -0,0 +1,33 @@
|
||||
# MeshCore Hub - Traefik Docker Compose Override
|
||||
#
|
||||
# Adds Traefik auto-discovery labels to api and web services.
|
||||
# Requires docker-compose.prod.yml (for the proxy-net network).
|
||||
#
|
||||
# Set DOMAIN in your .env file to the hostname for this instance.
|
||||
#
|
||||
# Prerequisites:
|
||||
# - Traefik configured with Docker provider and attached to proxy-net
|
||||
# - TRAEFIK_DOMAIN set in .env (e.g., TRAEFIK_DOMAIN=meshcore.example.com)
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.traefik.yml up -d
|
||||
|
||||
services:
|
||||
api:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.${COMPOSE_PROJECT_NAME:-hub-dev}-api.loadbalancer.server.port=8000"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-api.rule=Host(`${TRAEFIK_DOMAIN}`) && (PathPrefix(`/api`) || PathPrefix(`/metrics`) || PathPrefix(`/health`))"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-api.entrypoints=websecure"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-api.tls=true"
|
||||
- "traefik.docker.network=proxy-net"
|
||||
|
||||
web:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.${COMPOSE_PROJECT_NAME:-hub-dev}-web.loadbalancer.server.port=8080"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-web.rule=Host(`${TRAEFIK_DOMAIN}`)"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-web.entrypoints=websecure"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-web.tls=true"
|
||||
- "traefik.http.routers.${COMPOSE_PROJECT_NAME:-hub-dev}-web.priority=1"
|
||||
- "traefik.docker.network=proxy-net"
|
||||
+14
-24
@@ -7,13 +7,11 @@ services:
|
||||
# ==========================================================================
|
||||
mqtt:
|
||||
image: ghcr.io/ipnet-mesh/meshcore-mqtt-broker:latest
|
||||
container_name: meshcore-mqtt
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-mqtt
|
||||
profiles:
|
||||
- all
|
||||
- mqtt
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${MQTT_PORT:-1883}:${MQTT_PORT:-1883}"
|
||||
volumes:
|
||||
- mqtt_broker_data:/data
|
||||
environment:
|
||||
@@ -64,7 +62,7 @@ services:
|
||||
# ==========================================================================
|
||||
packet-capture:
|
||||
image: ghcr.io/agessaman/meshcore-packet-capture:${PACKETCAPTURE_IMAGE_VERSION:-latest}
|
||||
container_name: meshcore-packet-capture
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-packet-capture
|
||||
profiles:
|
||||
- all
|
||||
- receiver
|
||||
@@ -136,7 +134,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: meshcore-collector
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-collector
|
||||
profiles:
|
||||
- all
|
||||
- core
|
||||
@@ -196,7 +194,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: meshcore-api
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-api
|
||||
profiles:
|
||||
- all
|
||||
- core
|
||||
@@ -206,8 +204,6 @@ services:
|
||||
condition: service_completed_successfully
|
||||
collector:
|
||||
condition: service_started
|
||||
ports:
|
||||
- "${API_PORT:-8000}:8000"
|
||||
volumes:
|
||||
- hub_data:/data
|
||||
environment:
|
||||
@@ -249,7 +245,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: meshcore-web
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-web
|
||||
profiles:
|
||||
- all
|
||||
- core
|
||||
@@ -257,8 +253,6 @@ services:
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "${WEB_PORT:-8080}:8080"
|
||||
volumes:
|
||||
- ${CONTENT_HOME:-./content}:/content:ro
|
||||
environment:
|
||||
@@ -315,7 +309,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: meshcore-db-migrate
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-db-migrate
|
||||
profiles:
|
||||
- all
|
||||
- core
|
||||
@@ -338,7 +332,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: meshcore-seed
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-seed
|
||||
profiles:
|
||||
- seed
|
||||
restart: "no"
|
||||
@@ -357,7 +351,7 @@ services:
|
||||
# ==========================================================================
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: meshcore-prometheus
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-prometheus
|
||||
profiles:
|
||||
- all
|
||||
- metrics
|
||||
@@ -365,8 +359,6 @@ services:
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "${PROMETHEUS_PORT:-9090}:9090"
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
- "--storage.tsdb.retention.time=30d"
|
||||
@@ -380,13 +372,11 @@ services:
|
||||
# ==========================================================================
|
||||
alertmanager:
|
||||
image: prom/alertmanager:latest
|
||||
container_name: meshcore-alertmanager
|
||||
container_name: ${COMPOSE_PROJECT_NAME:-hub-dev}-alertmanager
|
||||
profiles:
|
||||
- all
|
||||
- metrics
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${ALERTMANAGER_PORT:-9093}:9093"
|
||||
volumes:
|
||||
- ./etc/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
|
||||
- alertmanager_data:/alertmanager
|
||||
@@ -399,12 +389,12 @@ services:
|
||||
# ==========================================================================
|
||||
volumes:
|
||||
hub_data:
|
||||
name: meshcore_hub_data
|
||||
name: ${COMPOSE_PROJECT_NAME:-hub-dev}_hub_data
|
||||
mqtt_broker_data:
|
||||
name: meshcore_mqtt_broker_data
|
||||
name: ${COMPOSE_PROJECT_NAME:-hub-dev}_mqtt_broker_data
|
||||
prometheus_data:
|
||||
name: meshcore_prometheus_data
|
||||
name: ${COMPOSE_PROJECT_NAME:-hub-dev}_prometheus_data
|
||||
alertmanager_data:
|
||||
name: meshcore_alertmanager_data
|
||||
name: ${COMPOSE_PROJECT_NAME:-hub-dev}_alertmanager_data
|
||||
packetcapture_data:
|
||||
name: meshcore_packetcapture_data
|
||||
name: ${COMPOSE_PROJECT_NAME:-hub-dev}_packetcapture_data
|
||||
|
||||
Reference in New Issue
Block a user