Docker Compose: Running a Complete Industrial System With One Command
Why Docker Compose?
Running a single container is straightforward. But industrial applications rarely work alone. A typical SCADA monitoring system needs an application server, a database, and a visualization dashboard — three separate containers that must communicate, share data, and start in the correct order.
Docker Compose defines all your services in a single YAML file. One command starts everything, connects the networks, and mounts the volumes. One command tears it all down.
For factory deployments, this means reproducing the entire stack on a test server before pushing to production, onboarding new engineers with a single docker compose up, and version-controlling your infrastructure alongside your application code.
The docker-compose.yml File: Basic Structure
Every Compose file follows the same skeleton:
services:
app:
image: factory-monitor:v1
ports:
- "8080:8080"
database:
image: surrealdb/surrealdb:latest
ports:
- "8000:8000"
dashboard:
image: grafana/grafana:latest
ports:
- "3000:3000"
Key Commands
docker compose up -d # Start all services in background
docker compose logs -f # View logs from all services
docker compose down # Stop and remove everything
docker compose up -d --build # Rebuild after code changes
Services: App + Database + Dashboard
Here is a complete Compose file for an industrial monitoring stack:
services:
factory-app:
build: .
ports:
- "8080:8080"
environment:
- DATABASE_URL=ws://surrealdb:8000
- RUST_LOG=info
depends_on:
surrealdb:
condition: service_healthy
restart: unless-stopped
surrealdb:
image: surrealdb/surrealdb:v2.1.4
command: start --user root --pass factory123 surrealkv://data/factory.db
ports:
- "8000:8000"
volumes:
- surreal-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 3
restart: unless-stopped
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=monitor2025
restart: unless-stopped
volumes:
surreal-data:
grafana-data:
The depends_on with condition: service_healthy ensures the application waits until the database is ready.
Networks: Isolating and Connecting Services
By default, Compose creates a single network for all services. For better security, isolate groups:
services:
factory-app:
networks: [frontend, backend]
surrealdb:
networks: [backend]
grafana:
networks: [frontend]
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
With internal: true, the database cannot be reached from outside. Only the application, belonging to both networks, can talk to the database.
Volumes: Persisting Data Across Restarts
Without volumes, all data inside a container is lost when it stops. Use bind mounts for configuration files with :ro for read-only access:
services:
grafana:
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
Managing Volumes
docker volume ls # List all volumes
docker volume inspect factory-monitor_surreal-data # Inspect a volume
docker volume prune # Remove unused volumes
Environment Variables and the .env File
Hard-coding passwords in docker-compose.yml is a security risk. Use a .env file:
SURREAL_USER=root
SURREAL_PASS=secure_factory_password_2025
SURREAL_PORT=8000
APP_PORT=8080
RUST_LOG=info
GF_ADMIN_PASS=dashboard_secure_2025
Referencing in docker-compose.yml
services:
surrealdb:
command: start --user ${SURREAL_USER} --pass ${SURREAL_PASS} surrealkv://data/factory.db
ports:
- "${SURREAL_PORT}:8000"
factory-app:
environment:
- DATABASE_URL=ws://surrealdb:${SURREAL_PORT}
- RUST_LOG=${RUST_LOG}
ports:
- "${APP_PORT}:8080"
Add .env to .gitignore and distribute a .env.example with placeholder values so team members know which variables to set.
Summary
Docker Compose transforms multi-container deployments from a series of manual commands into a single declarative file. Services define what runs, networks control communication boundaries, volumes persist critical data, and environment variables keep secrets out of version control. In the next lesson, you will learn Linux system administration fundamentals needed to manage the servers where these containers run.