A declarative deployment CLI that generates all infrastructure config
from a single manifest.yaml and manages the full container lifecycle.
- Docker Desktop with WSL2 integration enabled
- Python 3.12+
- pip packages:
pip install pyyaml jinja2 --break-system-packages
``` swiftdeploy-project/ ├── manifest.yaml ← single source of truth (only file you edit) ├── swiftdeploy ← CLI tool ├── Dockerfile ← builds the API image ├── app/ │ ├── main.py ← Flask API service │ └── requirements.txt ├── templates/ │ ├── nginx.conf.j2 ← Nginx template │ └── docker-compose.yml.j2 └── README.md ```
```bash docker build -t swift-deploy-1-node:latest . ```
```bash ./swiftdeploy deploy ```
```bash curl http://localhost:8080/ curl http://localhost:8080/healthz ```
Parses manifest.yaml and generates nginx.conf + docker-compose.yml
```bash
./swiftdeploy init
```
Runs 5 pre-flight checks before deployment:
- manifest.yaml exists and is valid YAML
- All required fields present and non-empty
- Docker image exists locally
- Nginx port not already bound
- nginx.conf syntax is valid ```bash ./swiftdeploy validate ```
Runs init → validate → starts stack → waits for health (60s timeout) ```bash ./swiftdeploy deploy ```
Switches deployment mode with rolling service restart ```bash ./swiftdeploy promote canary # enables chaos endpoint + X-Mode header ./swiftdeploy promote stable # rolls back to stable ```
Removes all containers, networks, and volumes ```bash ./swiftdeploy teardown # stops stack ./swiftdeploy teardown --clean # also deletes generated configs ```
| Method | Path | Description |
|---|---|---|
| GET | / | Welcome message, mode, version, time |
| GET | /healthz | Status + uptime in seconds |
| POST | /chaos | Inject chaos (canary mode only) |
```bash
curl -X POST http://localhost:8080/chaos
-H "Content-Type: application/json"
-d '{"mode": "slow", "duration": 3}'
curl -X POST http://localhost:8080/chaos
-H "Content-Type: application/json"
-d '{"mode": "error", "rate": 0.5}'
curl -X POST http://localhost:8080/chaos
-H "Content-Type: application/json"
-d '{"mode": "recover"}'
```
- Non-root container — app runs as
appuserwith all capabilities dropped - Image size — 186MB (well under 300MB limit)
- Port isolation — app port 3000 never exposed; all traffic via Nginx on 8080
- Single source of truth — manifest.yaml drives everything; no manual config
- Named volumes — logs persist across container restarts