Guide for Developers: Configuring All Deployment Types in Simple Container
Simple Container supports three deployment types:
| Deployment Type | Use Case | Example Platforms |
|---|---|---|
cloud-compose |
Multi-container microservices | Kubernetes, ECS Fargate |
single-image |
Single-container applications | AWS Lambda, Cloud Run |
static |
Static websites | AWS S3, GCP Cloud Storage |
This guide explains how to configure each deployment type using client.yaml.
cloud-compose: Multi-Container Microservices
Use cloud-compose for microservices that require multiple containers, databases, message queues, or networking.
Requires a Dockerfile and a docker-compose.yaml file.
Works with Kubernetes, ECS Fargate, Cloud Run, etc.
Example client.yaml for cloud-compose
---
# File: "myproject/.sc/stacks/myservice/client.yaml"
schemaVersion: 1.0
stacks:
staging:
type: cloud-compose
parent: myproject/devops
config:
domain: staging-myservice.myproject.com
dockerComposeFile: ./docker-compose.yaml
uses:
- mongodb # Uses a MongoDB database from `server.yaml`
runs:
- myservice # Deploys the "myservice" container
size:
cpu: 512 # 0.5 vCPU
memory: 1024 # 1GB RAM
scale:
min: 1
max: 5
policy:
cpu:
max: 70 # Scale up if CPU usage exceeds 70%
env:
DATABASE_HOST: "${resource:mongodb.host}"
DATABASE_NAME: "${resource:mongodb.database}"
DATABASE_USER: "${resource:mongodb.user}"
secrets:
DATABASE_PASSWORD: "${resource:mongodb.password}"
Required Files
Dockerfile→ Defines how the service is built.docker-compose.yaml→ Defines how the service runs.
Example docker-compose.yaml
version: '3.8'
services:
myservice:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
NODE_ENV: production
DATABASE_URL: ${DATABASE_HOST}
Exposing UDP ports (e.g. WebRTC / LiveKit)
By default a cloud-compose service is created as a ClusterIP Service and
exposed through the shared Caddy ingress, which reverse-proxies HTTP/TCP
traffic only. Protocols that Caddy cannot proxy — most notably UDP — must be
exposed directly by turning the service's own Kubernetes Service into a
LoadBalancer.
Two things are required:
- Declare the UDP port in
docker-compose.yamlusing the compose/udpsuffix. The port protocol is now preserved end-to-end and emitted on both the container port and the Service port. Ports without a suffix stayTCP, exactly as before. - Set
serviceType: LoadBalancerundercloudExtras. This makes the service's own Service aLoadBalancerwith its own external IP, instead of the defaultClusterIPfronted by Caddy.
# docker-compose.yaml — a LiveKit SFU media server
services:
livekit:
image: livekit/livekit-server:latest
ports:
- "7880:7880" # signaling (wss) → TCP
- "7881:7881" # ICE/TCP → TCP
- "7882:7882/udp" # RTC media → UDP
# client.yaml
stacks:
production:
type: cloud-compose
parent: myproject/devops
config:
dockerComposeFile: ./docker-compose.yaml
runs:
- livekit
cloudExtras:
serviceType: LoadBalancer
Mixed TCP + UDP on one Service. When a service exposes both TCP and UDP
ports, sc emits a single mixed-protocol LoadBalancer Service carrying all
ports (rather than splitting into separate TCP and UDP Services). This keeps a
single external IP for the whole service, which is what UDP media servers need
in order to advertise one address to clients. Mixed-protocol Services are GA in
Kubernetes since 1.26 (the MixedProtocolLBService feature) and are supported
by recent GKE — your cluster must be on a version that supports them.
Announcing the external IP is the application's job.
scprovisions theLoadBalancerand the UDP port, but a media server such as LiveKit must be told its public address to put into ICE candidates (e.g. LiveKit'srtc.use_external_ip/rtc.node_ip). Wiring that address into your app's configuration is out of scope forsc.
Deploying to Staging
single-image: Single-Container Applications
Use single-image for single-container services like AWS Lambda or Cloud Run.
Only requires a Dockerfile (no docker-compose.yaml needed).
Supports cloud-specific configurations like AWS Lambda settings.
Example client.yaml for single-image
---
# File: "myproject/.sc/stacks/myservice/client.yaml"
schemaVersion: 1.0
stacks:
staging:
type: single-image
template: lambda-eu # AWS Lambda deployment
parent: myproject/devops
config:
domain: staging-myservice.myproject.com
image:
dockerfile: ${git:root}/Dockerfile
timeout: 180 # AWS Lambda execution timeout
maxMemory: 2048 # 2GB RAM
staticEgressIP: true # Ensures outbound requests use a static IP
cloudExtras:
lambdaRoutingType: function-url
lambdaInvokeMode: RESPONSE_STREAM
uses:
- mongodb
env:
NODE_ENV: production
secrets:
MONGO_URI: "${resource:mongodb.uri}"
Required Files
Dockerfile→ Defines how the service is packaged into a container.
Example Dockerfile
Deploying to AWS Lambda
static: Deploying Static Websites
Use static for deploying static websites (e.g., React, Vue, Angular).
Requires a pre-built directory with static files.
Supports public cloud storage, CDN caching, and custom domains.
Example client.yaml for static Deployment
---
# File: "myproject/.sc/stacks/landing-page/client.yaml"
schemaVersion: 1.0
stacks:
prod:
type: static
parent: myproject/devops
config:
bundleDir: ${git:root}/public # Directory containing built static files
domain: simple-container.com # Public domain
indexDocument: index.html # Default page served
errorDocument: index.html # Handles client-side routing (React, Vue.js)
location: EUROPE-CENTRAL2
Required Files
- A built directory (
public/) → Containsindex.html,assets/, etc.
Building a Static Site (Example for React)
This creates apublic/ directory.
Deploying the Static Site
Summary
| Deployment Type | Use Case | Required Files | Example Platforms |
|---|---|---|---|
cloud-compose |
Multi-container microservices | Dockerfile, docker-compose.yaml |
Kubernetes, ECS Fargate |
single-image |
Single-container applications | Dockerfile |
AWS Lambda, Cloud Run |
static |
Static websites | bundleDir with HTML/CSS/JS |
AWS S3, GCP Cloud Storage |