Skip to main content

Example Stack Files

With a single file in git repo, you can orchestrate an entire application, from the containers to the infrastructure.

To create a stack, you'll first need to add a JSON file with the name cycle.json to the root of your git repository. When you import your stack into Cycle, it will read this file and generate a build, containing all images and configurations needed to deploy your application. By committing this file to your repo, it becomes version tracked, giving you a history of all changes.

Hand Written Stacks

These stack examples are maintained by hand, where the stack spec and the rest of the stack documentation is auto generated off the spec. If you do find a discrepancy please let us know via Slack!

Example Stack

We've prepared this repo with a demonstration stack file.

The repo has a README with some information on how to use the services.

The stack defines two services:

  1. A node api that serves a few endpoints related to a todo application.
  2. A Redis service that acts as the data store.

The application is meant to be run as a stateless set, so restarting the containers will reset the data on the Redis volume.

{
"version": "1.0",
"about": {
"description": "A demonstration stack with a simple CRUD API connected to redis.",
"version": "1.0.0"
},
"containers": {
"api": {
"name": "api",
"stateful": false,
"image": {
"name": "api",
"origin": {
"type": "docker-file",
"details": {
"build_file": "/Dockerfile",
"context_dir": "/"
}
}
},
"config": {
"network": {
"hostname": "api",
"ports": ["80:5000", "443:5000"],
"public": "enable"
},
"deploy": {
"instances": 1,
"strategy": "first-available",
"health_check": {
"command": "./health-check.sh",
"delay": "15s",
"interval": "15s",
"retries": 3,
"restart": true,
"timeout": "30s"
}
}
}
},
"redis": {
"name": "redis",
"stateful": false,
"image": {
"name": "redis",
"origin": {
"type": "docker-hub",
"details": {
"target": "redis:latest"
}
}
},
"config": {
"network": {
"hostname": "redis",
"ports": ["6379:6379"],
"public": "disable"
},
"deploy": {
"instances": 1
}
}
}
}
}

Scoped Variables

Click to Open
{
"version": "1.0",
"scoped_variables": [
{
"identifier": "encrypted",
"scope": {
"containers": {
"global": true
}
},
"access": {
"env_variable": {
"key": "ENCRYPTED"
},
"internal_api": {},
"file": {}
},
"source": {
"type": "raw",
"details": {
"value": "4a2e78b5403700d9cdfb5510f6361bc4ddb4a4af111e6fe3a5b70a9d9875ba33a82c5b890fe131465a1a3cb38b99b8eb",
"secret": {
"iv": "u4L2w6Qcm3On3duuA4U+gA==",
"hint": "e8e56823f631edf06d98499e1fd8cb5eedf028344d38d7087550ae917bd79fb3"
},
"blob": false
}
}
},
{
"identifier": "stackone",
"scope": {
"containers": {
"global": true
}
},
"access": {
"env_variable": {
"key": "STACKONE"
},
"internal_api": {},
"file": {}
},
"source": {
"type": "raw",
"details": {
"value": "STACKONEVALUE",
"secret": null,
"blob": false
}
}
},
{
"identifier": "urltype",
"scope": {
"containers": {
"global": true
}
},
"access": {
"internal_api": {
"duration": "15m"
},
"file": {
"path": "/somepath/urltype.json",
"decode": false
}
},
"source": {
"type": "url",
"details": {
"url": "https://someurl.com/config",
"headers": { "X-Custom-Test-Header": "SOMEVALUE" },
"auth_token_url": "https://someurl.com/auth"
}
}
}
],
"containers": {
"demo": {
"name": "demo",
"image": {
"name": "simplews",
"origin": {
"type": "docker-file",
"details": {
"context_dir": "/",
"build_file": "/Dockerfile"
}
}
},
"config": {
"network": {
"public": "enable",
"hostname": "simplews",
"ports": ["80:80"]
},
"deploy": {
"instances": 1
}
}
},
"remote": {
"name": "remote",
"image": {
"name": "simplews-external",
"origin": {
"type": "docker-file",
"details": {
"repo": {
"url": "https://github.com/username/repo.git"
},
"context_dir": "/",
"build_file": "/Dockerfile"
}
}
},
"config": {
"network": {
"public": "enable",
"hostname": "simplews",
"ports": ["80:80"]
},
"deploy": {
"instances": 1
}
}
}
}
}

Example Services Struct with V1 LB

Click to Open
{
"version": "1.0",
"services": {
"discovery": {
"service": {
"high_availability": true,
"auto_update": true,
"enable": true
},
"config": {
"hosts": {
"somehost": {
"ipv4": ["193.23.52.1"],
"ipv6": []
}
}
}
},
"loadbalancer": {
"service": {
"high_availability": true,
"auto_update": true,
"enable": true
},
"config": {
"type": "v1",
"ipv4": true,
"ipv6": true,
"details": {
"controllers": {
"1194": {
"identifier": "default-1194",
"transport": {
"mode": "tcp",
"config": {
"performance": false,
"ingress": {
"port": 1194,
"tls": null
},
"timeouts": {
"idle": "15m"
}
},
"routers": [
{
"match": {
"domains": null,
"internal_port": null
},
"mode": "round-robin",
"config": {
"sticky_sessions": true,
"destination_retries": 3,
"timeouts": {
"destination_connection": "3s"
}
}
}
]
}
},
"443": {
"identifier": "default-443",
"transport": {
"mode": "http",
"config": {
"performance": false,
"ingress": {
"port": 443,
"tls": {
"enable": true,
"server_name": null,
"allow_insecure": null,
"client_auth": null
}
},
"timeouts": {
"idle": "60s"
},
"extension": {
"type": "http",
"details": {
"connections": {
"max_idle_conns_per_connection": 5
}
}
}
},
"routers": [
{
"match": {
"domains": null,
"internal_port": null
},
"mode": "round-robin",
"config": {
"sticky_sessions": true,
"destination_retries": 3,
"timeouts": {
"destination_connection": "3s"
},
"extension": {
"type": "http",
"details": {
"redirect": null,
"forward": {
"scheme": "http"
}
}
}
}
},
{
"match": {
"domains": null,
"internal_port": [443, 8443]
},
"mode": "round-robin",
"config": {
"sticky_sessions": true,
"destination_retries": 3,
"timeouts": {
"destination_connection": "3s"
},
"extension": {
"type": "http",
"details": {
"redirect": null,
"forward": {
"scheme": "https"
}
}
}
}
}
]
}
},
"80": {
"identifier": "default-80",
"transport": {
"mode": "http",
"config": {
"performance": false,
"ingress": {
"port": 80,
"tls": null
},
"timeouts": {
"idle": "60s"
},
"extension": {
"type": "http",
"details": {
"connections": {
"max_idle_conns_per_connection": 5
}
}
}
},
"routers": [
{
"match": {
"domains": null,
"internal_port": [80]
},
"mode": "round-robin",
"config": {
"sticky_sessions": true,
"destination_retries": 3,
"timeouts": {
"destination_connection": "3s"
},
"extension": {
"type": "http",
"details": {
"redirect": {
"auto_https_redirect": true,
"port": null,
"scheme": null,
"url": null
},
"forward": {
"scheme": "http"
}
}
}
}
},
{
"match": {
"domains": null,
"internal_port": [443, 8443]
},
"mode": "round-robin",
"config": {
"sticky_sessions": true,
"destination_retries": 3,
"timeouts": {
"destination_connection": "3s"
},
"extension": {
"type": "http",
"details": {
"redirect": null,
"forward": {
"scheme": "https"
}
}
}
}
}
]
}
},
"8812": {
"identifier": "default-8812",
"transport": {
"mode": "tcp",
"config": {
"performance": false,
"ingress": {
"port": 8812,
"tls": null
},
"timeouts": {
"idle": "20s"
}
},
"routers": [
{
"match": {
"domains": null,
"internal_port": null
},
"mode": "round-robin",
"config": {
"sticky_sessions": false,
"destination_retries": 3,
"timeouts": {
"destination_connection": "3s"
}
}
}
]
}
}
}
}
}
},
"scheduler": {
"config": {
"access_keys": [
{ "ips": [], "name": "somekey", "secret": "supersecretkeyphrase" }
],
"public": false
},
"service": {
"auto_update": true,
"enable": true,
"high_availability": true
}
},
"vpn": {
"config": {
"allow_internet": true,
"auth": {
"cycle_accounts": true,
"vpn_accounts": true,
"webhook": "https://someendpoint.com/auth"
}
},
"service": {
"enable": true,
"auto_update": true,
"high_availability": false
}
}
},
"containers": {}
}