How we used Azure DevOps, Docker Compose, and Bash to create a fully automated deployment pipeline for a cloud-connected Minecraft server.
The Challenge
We needed to deploy and manage a multi-service Minecraft ecosystem that includes:
- A Fabric Minecraft server with custom mods
- A Node.js backend API
- An AI-powered Mineflayer bot
- An Azure Service Bus listener for cloud integration
All of this running on a Raspberry Pi, with zero manual intervention after code commits.
Infrastructure as Code
Docker Compose: The Foundation
Our entire infrastructure is defined in a single docker-compose.yml file. No clicking through portals, no manual container creation—just declarative YAML:

Every service, network, volume, and environment variable is version-controlled. Need to spin up the entire stack? One command:
docker-compose up -d
Environment-Driven Configuration
Secrets and configuration are externalized through environment variables and .env files:

This separation means the same compose file works across development, staging, and production—only the environment changes.
CI/CD Pipeline: Azure DevOps
Our Azure DevOps pipeline automates the entire deployment lifecycle in three stages:

Key automation features in our Bash scripts:
Automatic Backups with Rotation:

Health Checks with Retry Logic:

Stage 3: Verification
Post-deployment verification ensures everything is running correctly:

The Complete Picture

Benefits of This Approach
| Aspect | Traditional | Our Scripted Approach |
|---|---|---|
| Deployment | Manual SSH, copy files | Automatic on git push |
| Rollback | Hope you have a backup | Last 3 backups auto-retained |
| Configuration | Scattered across servers | Version-controlled in git |
| Reproducibility | “Works on my machine” | Identical every time |
| Audit Trail | Who changed what? | Full git history |
Key Takeaways
- Everything is Code: Docker Compose defines infrastructure, YAML defines pipelines, Bash scripts handle orchestration.
- Self-Hosted Agents: Running an Azure DevOps agent on the Raspberry Pi eliminates SSH complexity and firewall issues.
- Defensive Scripting: Every script handles failures gracefully with
continueOnError, retry loops, and fallback options. - Preserve What Matters: The rsync exclusions protect world data, databases, and secrets during deployments.
- Automated Verification: Don’t just deploy—verify. Health checks and resource monitoring catch issues before users do.
With the power of the shell, our entire Minecraft infrastructure deploys itself. Push to main, grab a coffee, and come back to a running server.