Skip to content

Commit 6fce4e4

Browse files
authored
Merge pull request #8 from IBM/add-compose
Docker Compose scripts and docs
2 parents f66a5e9 + 18fbcaa commit 6fce4e4

File tree

6 files changed

+793
-1
lines changed

6 files changed

+793
-1
lines changed

Makefile

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,8 @@ publish: verify ## Verify, then upload to PyPI
733733
# =============================================================================
734734
# help: 🦭 PODMAN CONTAINER BUILD & RUN
735735
# help: podman-dev - Build development container image
736-
# help: podman - Build production container image
736+
# help: podman - Build container image
737+
# help: podman-prod - Build production container image (using ubi-micro → scratch). Not supported on macOS.
737738
# help: podman-run - Run the container on HTTP (port 4444)
738739
# help: podman-run-shell - Run the container on HTTP (port 4444) and start a shell
739740
# help: podman-run-ssl - Run the container on HTTPS (port 4444, self-signed)
@@ -873,6 +874,7 @@ podman-shell:
873874
# help: 🐋 DOCKER BUILD & RUN
874875
# help: docker-dev - Build development Docker image
875876
# help: docker - Build production Docker image
877+
# help: docker-prod - Build production container image (using ubi-micro → scratch). Not supported on macOS.
876878
# help: docker-run - Run the container on HTTP (port 4444)
877879
# help: docker-run-ssl - Run the container on HTTPS (port 4444, self-signed)
878880
# help: docker-stop - Stop & remove the container
@@ -892,6 +894,16 @@ docker:
892894
@echo "🐋 Building production Docker image…"
893895
docker build --platform=linux/amd64 -t $(IMG_DOCKER_PROD) -f Containerfile .
894896

897+
docker-prod:
898+
@echo "🦭 Building production container from Containerfile.lite (ubi-micro → scratch)…"
899+
docker build --ssh default \
900+
--platform=linux/amd64 \
901+
--squash \
902+
-f Containerfile.lite \
903+
-t $(IMG_PROD) \
904+
.
905+
docker images $(IMG_PROD)
906+
895907
## -------------------- R U N (HTTP) ---------------------------------------
896908
docker-run:
897909
@echo "🚀 Starting Docker container (HTTP)…"
@@ -958,6 +970,86 @@ docker-shell:
958970
@echo "🔧 Opening shell in Docker container…"
959971
@docker exec -it $(PROJECT_NAME) bash || docker exec -it $(PROJECT_NAME) /bin/sh
960972

973+
974+
# =============================================================================
975+
# 🛠️ COMPOSE STACK (Docker Compose v2, podman compose or podman-compose)
976+
# =============================================================================
977+
# help: 🛠️ COMPOSE STACK - Build / start / stop the multi-service stack
978+
# help: compose-up - Bring the whole stack up (detached)
979+
# help: compose-restart - Recreate changed containers, pulling / building as needed
980+
# help: compose-build - Build (or rebuild) images defined in the compose file
981+
# help: compose-pull - Pull the latest images only
982+
# help: compose-logs - Tail logs from all services (Ctrl-C to exit)
983+
# help: compose-ps - Show container status table
984+
# help: compose-shell - Open an interactive shell in the “gateway” container
985+
# help: compose-stop - Gracefully stop the stack (keep containers)
986+
# help: compose-down - Stop & remove containers (keep named volumes)
987+
# help: compose-rm - Remove *stopped* containers
988+
# help: compose-clean - ✨ Down **and** delete named volumes (data-loss ⚠)
989+
990+
# ─────────────────────────────────────────────────────────────────────────────
991+
# You may **force** a specific binary by exporting COMPOSE_CMD, e.g.:
992+
# export COMPOSE_CMD=podman-compose # classic wrapper
993+
# export COMPOSE_CMD="podman compose" # Podman v4/v5 built-in
994+
# export COMPOSE_CMD="docker compose" # Docker CLI plugin (v2)
995+
#
996+
# If COMPOSE_CMD is empty, we autodetect in this order:
997+
# 1. podman-compose 2. podman compose 3. docker compose
998+
# ─────────────────────────────────────────────────────────────────────────────
999+
COMPOSE_CMD ?=
1000+
ifeq ($(strip $(COMPOSE_CMD)),)
1001+
COMPOSE_CMD := $(shell \
1002+
command -v podman-compose >/dev/null 2>&1 && echo podman-compose || \
1003+
command -v "podman compose" >/dev/null 2>&1 && echo "podman compose" || \
1004+
echo "docker compose" )
1005+
endif
1006+
COMPOSE_FILE ?= podman-compose-mcpgateway.yaml
1007+
1008+
define COMPOSE
1009+
$(COMPOSE_CMD) -f $(COMPOSE_FILE)
1010+
endef
1011+
1012+
.PHONY: compose-up compose-restart compose-build compose-pull \
1013+
compose-logs compose-ps compose-shell compose-stop compose-down \
1014+
compose-rm compose-clean
1015+
1016+
compose-up:
1017+
@echo "🚀 Using $(COMPOSE_CMD); starting stack..."
1018+
$(COMPOSE) up -d
1019+
1020+
compose-restart:
1021+
@echo "🔄 Restarting stack (build + pull if needed)…"
1022+
$(COMPOSE) up -d --pull=missing --build
1023+
1024+
compose-build:
1025+
$(COMPOSE) build
1026+
1027+
compose-pull:
1028+
$(COMPOSE) pull
1029+
1030+
compose-logs:
1031+
$(COMPOSE) logs -f
1032+
1033+
compose-ps:
1034+
$(COMPOSE) ps
1035+
1036+
compose-shell:
1037+
$(COMPOSE) exec gateway /bin/sh
1038+
1039+
compose-stop:
1040+
$(COMPOSE) stop
1041+
1042+
compose-down:
1043+
$(COMPOSE) down
1044+
1045+
compose-rm:
1046+
$(COMPOSE) rm -f
1047+
1048+
# Removes **containers + named volumes** – irreversible!
1049+
compose-clean:
1050+
$(COMPOSE) down -v
1051+
1052+
9611053
# =============================================================================
9621054
# ☁️ IBM CLOUD CODE ENGINE
9631055
# =============================================================================
@@ -1120,3 +1212,4 @@ ibmcloud-ce-status:
11201212
ibmcloud-ce-rm:
11211213
@echo "🗑️ Deleting Code Engine app: $(IBMCLOUD_CODE_ENGINE_APP)"
11221214
@ibmcloud ce application delete --name $(IBMCLOUD_CODE_ENGINE_APP) -f
1215+

docs/docs/deployment/.pages

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ nav:
33
- index.md
44
- local.md
55
- container.md
6+
- compose.md
67
- kubernetes.md
8+
- openshift.md
9+
- minikube.md
710
- ibm-code-engine.md
811
- aws.md
912
- azure.md

docs/docs/deployment/compose.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# 🚀 Docker Compose
2+
3+
Running **MCP Gateway** with **Compose** spins up a full stack (Gateway, Postgres, Redis, optional MPC servers) behind a single YAML file.
4+
The Makefile detects Podman or Docker automatically, and you can override it with `COMPOSE_ENGINE=`.
5+
Health-checks (`service_healthy`) gate the Gateway until the database is ready, preventing race conditions.
6+
7+
---
8+
9+
## 🐳/🦭 Build the images
10+
11+
### Using Make (preferred)
12+
13+
| Target | Image | Dockerfile | Notes |
14+
| ------------------ | ----------------------- | ---------------------- | ----------------------------- |
15+
| `make podman` | `mcpgateway:latest` | **Containerfile** | Rootless Podman, dev-oriented |
16+
| `make podman-prod` | `mcpgateway:latest` | **Containerfile.lite** | Ultra-slim UBI 9-micro build |
17+
| `make docker` | `mcpgateway:latest` | **Containerfile** | Docker Desktop / CI runners |
18+
| `make docker-prod` | `mcpgateway:latest` | **Containerfile.lite** | Same multi-stage "lite" build |
19+
20+
### Manual equivalents
21+
22+
```bash
23+
# Podman (dev image)
24+
podman build -t mcpgateway-dev:latest -f Containerfile .
25+
26+
# Podman (prod image, AMD64, squash layers)
27+
podman build --platform=linux/amd64 --squash \
28+
-t mcpgateway:latest -f Containerfile.lite .
29+
30+
# Docker (dev image)
31+
docker build -t mcpgateway-dev:latest -f Containerfile .
32+
33+
# Docker (prod image)
34+
docker build -t mcpgateway:latest -f Containerfile.lite .
35+
```
36+
37+
> **Apple Silicon caveat**
38+
> `Containerfile.lite` derives from **ubi9-micro**. Running it via QEMU emulation on M-series Macs often fails with a `glibc x86-64-v2` error.
39+
> Use the *regular* image or build a native `linux/arm64` variant on Mac.
40+
41+
---
42+
43+
## 🏃 Start the Compose stack
44+
45+
### With Make
46+
47+
```bash
48+
make compose-up # auto-detects engine
49+
COMPOSE_ENGINE=docker make compose-up # force Docker
50+
COMPOSE_ENGINE=podman make compose-up # force Podman
51+
```
52+
53+
### Without Make
54+
55+
| Make target | Docker CLI | Podman built-in | podman-compose |
56+
| ----------------- | --------------------------------------------- | -------------------------------------------- | -------------------------------------------- |
57+
| `compose-up` | `docker compose -f podman-compose.yml up -d` | `podman compose -f podman-compose.yml up -d` | `podman-compose -f podman-compose.yml up -d` |
58+
| `compose-restart` | `docker compose up -d --pull=missing --build` | idem | idem |
59+
| `compose-logs` | `docker compose logs -f` | `podman compose logs -f` | `podman-compose logs -f` |
60+
| `compose-ps` | `docker compose ps` | `podman compose ps` | `podman-compose ps` |
61+
| `compose-stop` | `docker compose stop` | `podman compose stop` | `podman-compose stop` |
62+
| `compose-down` | `docker compose down` | `podman compose down` | `podman-compose down` |
63+
| `compose-clean` | `docker compose down -v` (removes volumes) | `podman compose down -v` | `podman-compose down -v` |
64+
65+
---
66+
67+
## 🌐 Access and verify
68+
69+
* **Gateway URL:** [http://localhost:4444](http://localhost:4444)
70+
(Bound to `0.0.0.0` inside the container so port-forwarding works.)
71+
72+
```bash
73+
curl http://localhost:4444/health # {"status":"ok"}
74+
```
75+
76+
* **Logs:** `make compose-logs` or raw `docker compose logs -f gateway`.
77+
78+
---
79+
80+
## 🗄 Selecting a database
81+
82+
Uncomment one service block in `podman-compose.yml` and align `DATABASE_URL`:
83+
84+
| Service block | Connection string |
85+
| --------------------- | --------------------------------------------- |
86+
| `postgres:` (default) | `postgresql://postgres:...@postgres:5432/mcp` |
87+
| `mariadb:` | `mysql+pymysql://admin:...@mariadb:3306/mcp` |
88+
| `mysql:` | `mysql+pymysql://mysql:...@mysql:3306/mcp` |
89+
| `mongodb:` | `mongodb://admin:...@mongodb:27017/mcp` |
90+
91+
Named volumes (`pgdata`, `mariadbdata`, `mysqldata`, `mongodata`) isolate persistent data.
92+
93+
---
94+
95+
## 🔄 Lifecycle cheatsheet
96+
97+
| Task | Make | Manual (engine-agnostic) |
98+
| ------------------ | ---------------------- | ----------------------------------------------- |
99+
| Start / create | `make compose-up` | `<engine> compose up -d` |
100+
| Re-create changed | `make compose-restart` | `<engine> compose up -d --pull=missing --build` |
101+
| Tail logs | `make compose-logs` | `<engine> compose logs -f` |
102+
| Shell into gateway | `make compose-shell` | `<engine> compose exec gateway /bin/sh` |
103+
| Stop | `make compose-stop` | `<engine> compose stop` |
104+
| Remove containers | `make compose-down` | `<engine> compose down` |
105+
| **Nuke volumes** | `make compose-clean` | `<engine> compose down -v` |
106+
107+
`<engine>` = `docker`, `podman`, or `podman-compose` as shown earlier.
108+
109+
---
110+
111+
## 📚 References
112+
113+
* Docker Compose CLI (`up`, `logs`, `down`) – official docs
114+
* Podman’s integrated **compose** wrapper – man page
115+
* `podman-compose` rootless implementation – GitHub project
116+
* Health-check gating with `depends_on: condition: service_healthy`
117+
* [UBI9 runtime on Apple Silicon limitations (`x86_64-v2` glibc)](https://github.com/containers/podman/issues/15456)
118+
* General Containerfile build guidance (Fedora/Red Hat)

0 commit comments

Comments
 (0)