A self-service sandbox platform for short-lived Docker environments. Users can create isolated demo app environments, route to them through Nginx, monitor health, simulate outages, read logs, and destroy the environments manually or automatically after their TTL expires.
Developer / Reviewer
|
| make / curl API
v
+-----------------------------+
| Host Linux VM |
| |
| Makefile |
| platform/*.sh |
| platform/api.py :5000 |
| cleanup_daemon.sh |
| monitor/health_poller.py |
| |
| Docker |
| sandbox-nginx :8080 |
| | |
| +-- env-abc-net ------ env-abc-app :8000
| +-- env-def-net ------ env-def-app :8000
| |
| envs/*.json |
| logs/<env-id>/ |
+-----------------------------+
- One Linux VM
- Docker Engine
- Docker Compose plugin
- Python 3 with
venvsupport - Bash, Make, curl
From a fresh VM:
git clone https://github.com/Adeolu1024/devops-sandbox.git devops-sandbox
cd devops-sandbox
cp .env.example .env
make up
make createWhen make create asks for values, enter a name like demo and a TTL like 900.
The script prints a URL like:
http://env-xxxxxxxx.localhost:8080/
If your VM does not resolve *.localhost, test with curl by forcing the Host header:
curl -H "Host: env-xxxxxxxx.localhost" http://localhost:8080/
curl -H "Host: env-xxxxxxxx.localhost" http://localhost:8080/healthThe current demo VM is reachable at:
http://98.82.168.197:8080
Environment routes are selected by Nginx using the Host header. Replace <env-id> with the active environment ID shown by make create or GET /envs:
curl -H "Host: <env-id>.localhost" http://98.82.168.197:8080/
curl -H "Host: <env-id>.localhost" http://98.82.168.197:8080/health
curl http://98.82.168.197:5000/envs- Start the platform:
make up- Create a sandbox environment:
make createUse demo as the name and 300 as the TTL for a five-minute environment.
- Check the running environment:
curl -H "Host: <env-id>.localhost" http://localhost:8080/
curl -H "Host: <env-id>.localhost" http://localhost:8080/health- Watch logs:
make logs ENV=<env-id>- Show health status:
make health- Simulate an outage:
make simulate ENV=<env-id> MODE=crashWithin 90 seconds, the health poller records failures and marks the environment as degraded.
- Recover:
make simulate ENV=<env-id> MODE=recover- Destroy manually:
make destroy ENV=<env-id>If you do not destroy manually, cleanup_daemon.sh destroys the environment automatically when the TTL expires.
Start everything with:
make upCreate an environment:
curl -X POST http://localhost:5000/envs \
-H "Content-Type: application/json" \
-d '{"name":"api-demo","ttl":600}'List environments:
curl http://localhost:5000/envsDestroy an environment:
curl -X DELETE http://localhost:5000/envs/<env-id>Read the last 100 app log lines:
curl http://localhost:5000/envs/<env-id>/logsRead the last 10 health checks:
curl http://localhost:5000/envs/<env-id>/healthTrigger outage simulation:
curl -X POST http://localhost:5000/envs/<env-id>/outage \
-H "Content-Type: application/json" \
-d '{"mode":"crash"}'Nginx runs as a persistent Docker container named sandbox-nginx. Each sandbox environment gets a dedicated Docker network and one app container. During creation, the platform connects sandbox-nginx to that environment network and writes nginx/conf.d/<env-id>.conf.
The generated Nginx config proxies:
<env-id>.localhost -> <env-id>-app:8000
During destruction, the config is removed, Nginx is reloaded, the app container is removed, and the dedicated Docker network is deleted.
This project uses Approach A from the task brief. During environment creation, the platform starts:
docker logs -f <container-id> >> logs/<env-id>/app.log &The log shipper PID is saved in envs/<env-id>.json. During destruction, that PID is killed so zombie log processes are not left behind. Logs are queryable with:
make logs ENV=<env-id>On destroy, logs are archived to:
logs/archived/<env-id>/
Environment state lives in envs/<env-id>.json and includes:
- ID
- name
- creation timestamp
- TTL
- status
- container ID/name
- network name
- log shipper PID
- outage mode
State files are written atomically by writing a temporary file first and then moving it into place.
make up
make down
make create
make destroy ENV=<env-id>
make logs ENV=<env-id>
make health
make simulate ENV=<env-id> MODE=crash
make clean- This is designed for a single Linux VM, not a multi-node cluster.
- The API runs as a local Python process started by
nohup, not as a production systemd service. crashrecovery restarts the same stopped container; it does not recreate the container from scratch.- Optional
stressoutage mode is not implemented; supported modes arecrash,pause,network, andrecover. - Wildcard DNS for
<env-id>.localhostmay vary by environment, so the README shows a reliablecurl -H "Host: ..."fallback. - Prometheus and Grafana are not included; health is stored in per-environment log files.
GitHub Actions validates Python syntax, Bash syntax, and the demo app Docker build on every push and pull request.