Configuration
Services
A Coherence application is composed of one or more services. Each service has a type (frontend
or backend
), creates its own deployment, and defines its own containers, resources (e.g. database, object storage, or cache), and workers/crons.
Service Types
You can have many instances of each service type, but the name
and url_path
of each one must be unique. The name
of a service is defined by the top-level key in the yml
.
- backend
- frontend
Common config
For all service types, these attributes are used.
repo_path
tells Coherence where in the repo the service is located. It will be used as thedocker build
context for the service's container, and as the relative base for theassets_path
to discover frontend assets after they are compiled.- This value is relative to your repo's root.
url_path
will configure the load balancer for the application to send traffic with this path prefix to the service. Each environment on Coherence get's its own domain, so the path is purely about service routing within an environment, not across environments. The default is/
.
Build glob configuration
This behavior is currently in a closed beta, rolling out soon, but let us know if you want to enable it for you now!
By default, if a repo_path
is configured for a service, when Coherence receives a github webhook for a push (including a merge), it will generate a diff of the files changed in that commit and the last successful pipeline. If none of the files match repo_path/**/*
, the service will be ignored for the pipeline generated by the webhook.
Additionally, you can specify build_config
object for each service with included_paths
and excluded_paths
. These are glob patterns that are attached to the repo_path
of the service and used with the same diff detection (based on filenames) described above. This can be used to control what services are generated from a push, either with multiple services in one app, or multiple apps in one repo.
For example:
service_1:
type: frontend
repo_path: baz
...
build_config:
# for globs, ** = folder, * = file
# appended to repo_path, e.g. the path that will trigger a build is baz/foo/* or baz/foo/**/*
included_paths: ["foo/**/*", "foo/*"]
excluded_paths: ["README.md"]
Build timeouts (AWS only)
For AWS applications, the following build tasks are considered failed if they have not completed within 20 minutes: test
, migrate
, seed
, snapshot
, deploy
Build task | coherence.yml command |
---|---|
test | test |
migrate | migration |
snapshot | snapshot |
seed | seed |
deploy | prod |
If additional time is required for any task it is configurable at the service level in your coherence.yml
. The default timeout (20 mins) can also be overwritten to allow more time for all tasks. e.g.
backend:
build_config:
timeouts:
default: 20
test: 30
migrate: 20
snapshot: 40
seed: 50
deploy: 30
Dockerfiles
Docker behavior
Each service runs in its own docker
container, so you don't need to do anything special to generate a container for each service. By default, each pipeline for a service will build a container using the repo_path
as the build context, and the file Dockerfile
at the root of the repo_path
as the image's definition.
Customizing Dockerfile location
You can use a different filename than Dockerfile
for your service. You can also sepcify different Dockerfile
's for use in dev
(in a Workspace) and in a deployed cloud environment.
To do this, you can specify an attribute dockerfile
along with the command
under the dev
and prod
keys for each service. The paths provided are relative to the repo_path
which will remain the build context. For example:
dev:
command: ["run", "command"]
dockerfile: "Dockerfile.dev"
prod:
command: ["run", "command"]
dockerfile: "prod/Dockerfile.prod"
Defaults
If you do not provide a dev
dockerfile, the file for prod
will be used. If neither is provided, the default of Dockerfile
at the repo_path
will be used.
Customizing Dockerfile target
If your dockerfile utilizes multi stage builds and you'd like to target a stage other than the last stage, that can be added to the dev and/or prod commands as a build_target
. It is equivalent to adding the --target STAGE
argument to the docker build command (see: https://docs.docker.com/build/building/multi-stage/#stop-at-a-specific-build-stage).
dev:
command: ["run", "command"]
dockerfile: "Dockerfile.dev"
build_target: "dev_stage"
prod:
command: ["run", "command"]
dockerfile: "prod/Dockerfile.prod"
build_target: "prod_stage"
Using Nixpacks
If you don't provide a Dockerfile
for a service, we will attempt to build a container for your service using Nixpacks. This works well for many common applications!
Backend Services
Please note that your service should look for a PORT
environment variable, and accept connections from host 0.0.0.0
on that port (this is the standard expectation of Cloud Run and ECS/Fargate).
dev
Will run in your container on a Workspace.
prod
Will run when serving your container in a review or production environment. See details for AWS and GCP
workers
- The service container will be run as a deployment per worker with the command specified.
- You can manually scale replicas per-environment in the Coherence UI (Environment's infra tab).
- AWS will default autoscale at 70% of CPU use.
On Workspaces:
- The special worker named
dev_workspace
will replace all workers on a workspace with the given command (to save resources in dev and listen to multiple queues or run multiple jobs). - If
dev_workspace
worker is not provided, all workers will be run in a workspace. - The special worker named
preview_environment
will replace all workers in a preview environment with the given command (to save resources in dev and listen to multiple queues or run multiple jobs). - If
preview_environment
worker is not provided, all workers will be run in each preview environment.
scheduled_tasks
backend:
scheduled_tasks:
- name: task 1
command: [“sleep”]
schedule: "* * * * *"
See cronjobs#schedule for the schedule element, even on AWS apps. We will normalize the syntax into the ECS configuration if required.
The command provided will be passed to sh -c “command”
, so it will support chaining with e.g. &&
or ;
- On GCP, will share the kubernetes cluster with workers. Coherence will create
CronJob
resources in the cluster at the schedule specified. - On AWS, will share the ECS cluster with the HTTP services in your Coherence application. Each service's scheduled tasks will deploy ECS
scheduled_task
instances with a target of the service. This means that they will use the same container image as the service, albeit with whatever command you specify for the task.
system
backend:
system:
cpu: 2
memory: 2G
dev:
cpu: 4
memory: 3G
preview:
cpu: 1
memory: 1G
health_check: "/health"
platform_settings:
min_scale: 2
max_scale: 6
throttle_cpu: true
workers:
- name: my_example_worker
command: ["python", "worker.py"]
system:
cpu: 4
memory: 3G
preview:
cpu: 3
memory: 2G
scheduled_tasks:
- name: sample cron task
command: ["python", "-u", "cron/do_some_things.py"]
schedule: "*/2 * * * *"
system:
cpu: 4
memory: 3G
preview:
cpu: 3
memory: 2G
- Resources
cpu
andmemory
can be configured in thesystem
block, and will be used in dev, review, and production environments for workers, tasks, and backend web processes.dev
is also available as a nested value inside system, andcpu
andmemory
can be defined seperately for dev use there. These settings apply to workspaces.preview
is available as a nested value inside system, andcpu
andmemory
can be defined seperately for preview use there. These settings apply to all non-static environments.
- Scheduled tasks and workers also accept a
system
configuration. For these resources, onlycpu
andmemory
(incl.preview
cpu/mem) are supported as in the example above. If this config isn't present, cpu and memory are inherited from the service. health_check
: allows you to configure the health check endpoint for your backend service.- For GCP,
min_scale
defaults to 0 (which means "cold start" boot times) and you can set it to a higher value to ensure this many replicas are always running.- You can also change
throttle_cpu
to false to keep cpu always-allocated. - Keep in mind the cost of these decisions.
- You can change runtime generation in Cloud Run between
gen1
andgen2
.
- You can also change
- For AWS,
min_scale
defaults to 1 and it can be increased to ensure more replicas are always running.- You can also optionally set
max_scale
(default: 4) to control the maximum number of replicas. - Autoscaling rules are put in place by default and will manage scaling your service from
min_scale
tomax_scale
based on CPU usage (>70%). - N.B. Values provided for
min_scale
andmax_scale
will only overwrite defaults for production services.
- You can also optionally set
resources
Supported types are database
, cache
, object_storage
, filesystem
and message_queue
which will be used to provision the appropriate cloud resources (e.g. Memorystore/Cloud SQL/GCS on GCP, Elasticache/RDS/S3/SQS on AWS). Multiple resources of each type can be configured, but their names must be distinct.
Note message_queue
and filesystem
only available on AWS. If you would like to use a these on GCP, please get in touch.
backend:
resources:
- name: db1
engine: postgres
version: 13
type: database
adapter: optional_string
snapshot_file_path: "bucket_name/file_name.sql"
- name: redis
engine: redis
version: 4
type: cache
- name: test_bucket
type: object_storage
cors:
- allowed_methods: ["GET", "POST", "PUT", "DELETE"]
allowed_origins: ["www.example.com"]
- allowed_methods: ["GET"]
allowed_origins: ["*"]
- name: test_queue
type: message_queue
fifo: True
- name: vol1
type: filesystem
use_existing:
project_type: review
instance_name: "YOUR_EFS_FILESYSTEM_ID"
Types
- Backend resources support
database
,cache
,object_storage
,filesystem
, andmessage_queue
types. - Under the hood these map to
Cloud SQL
,Memorystore
andCloud Storage
in GCP, or toRDS
,Elasticache
,S3
andSQS
in AWS. - The
engine
andversion
attributes will accept any valid values for those platforms fordatabase
andcache
types.
Object Storage
- The object storage type takes two attributes:
name
and acors
block. Thecors
block consists of pairs ofallowed_methods
andallowed_origins
lists, which will be applied as the Cross-Origin Resource Sharing rules on your bucket. You can add as many CORS pairs to your bucket as needed. name
is for your use and will be used to create the bucket in your cloud provider, with the addition of your environment name and a unique identifier appended.- A
use_existing
block can be configured to add an object storage bucket that is not managed by Coherence that you want to use from your Coherence environments. theproject_type
attribute can bereview
orproduction
:
- name: test_bucket
type: object_storage
use_existing:
project_type: review
instance_name: EXISTING-BUCKET-NAME
Message Queue (AWS Only)
- The message queue type takes two attributes:
name
and afifo
boolean. Thefifo
boolean will control whether your queue is created as an AWS standard queue or first in first out queue. name
is for your use and will be used to create the queue in your cloud provider, with the addition of your environment name and a unique identifier appended.- A
use_existing
block can be configured to add a message queue that is not managed by Coherence that you want to use from your Coherence environments. theproject_type
attribute can bereview
orproduction
:
- name: test_queue
type: message_queue
use_existing:
project_type: review
queue_name: EXISTING-QUEUE-NAME
EFS Filesystem (AWS Only)
for EFS support, create in AWS yourself (outside Coherence) in the same AWS account you set up your application in during onboarding for the relevant collection (review
or production
). If provided, EFS will be mounted in the service's ECS tasks, with containerPath
set to the name of the resource (e.g. vol1
in the example above).
Database configuration
- The default
DATABASE_URL
generated for your app's variables will use a lowercased string of the engine name provided as the adapter. (e.g.adapter://username:password@host:port/db_name
) You may provide a different value by setting theadapter
property of the resource to a string, e.g.postgresql
instead of the defaultpostgres
is a common choice in python programs. - For AWS, there is an optional
use_db_proxy
setting which defaults totrue
. By default, as a best practice applications will connect via an AWS database proxy whenever possible. If for some reason this will not work for your application (e.g. when using RLS), it can be disabled by settinguse_db_proxy
tofalse
:
- name: db1
engine: postgres
version: 13
type: database
use_db_proxy: false
Loading data into databases
- The
migration
andseed
commands for the service will run whatever command you specify inside the service's container, both during Workspace start-up as well as in a CI/CD pipeline for each environment. It's up to you to make yourseed
command idempotent. - Additionally, you can provide a
snapshot_file_path
attribute for eachdatabase
resource. This can be for example a dump of your staging environment. The snapshot file will be automatically downloaded and loaded into the database for a new Workspace or non-production environment (either)- The
snapshot_file_path
should be thebucket_name
andfile_name
as one string. Nested folders in the bucket, e.g.bucket1/folder/file1.sql
are supported. - The bucket must be in the
review
project for your app. Appropriate IAM roles will be assumed by Workspace or CI Pipelines to download the file. - Two types of snapshots are supported,
data
orschema_and_data
. This should be specified withsnapshot_type
at theservice
level of theyml
, not theresource
level.- Migrations will still be run in workspaces and non-production environments if
data
is specified. They will not be run ifschema_and_data
is specified. If defined, migrations always run in production pipelines, regardless of snapshot settings.
- Migrations will still be run in workspaces and non-production environments if
- Snapshot loading in CI Pipelines will be injected until the environment has a pipeline with
success
status, after which it will not be loaded again. - You should export your data using the flags
pg_dump --no-owner --no-privileges
- the username used to access the database will likely differ on Coherence from your current deployment.
- The
N.B. Snapshots are only supported for engine postgres at this time.
Use Existing Databases
If you have an existing database you'd like to use, you can point at it (rather than creating a new one) with yml
like:
- name: db1
engine: postgres
version: 13
type: database
use_existing:
project_type: review
instance_name: EXISTING-INSTANCE-NAME
manage_databases: true
- For GCP, supported
project_types
areproduction
andreview
and correspond to thereview_project_id
andproduction_project_id
configured in the Coherence dashboard for your application. - In this configuration,
manage_databases
determines if Coherence will create and destroy databases on the instance to match the environments in your project. It generally should betrue
forreview
andfalse
forproduction
- since you won't need to madd/remove databases for preview environments in production.
For AWS this configuration is similar, but you'll need to create a secret containing your database username and password. RDS can manage the secret for you automatically during instance creation and manage it for you. The name of that secret should be added to your database configuration:
N.B. For AWS, existing databases are only supported for production environments
- name: db1
engine: postgres
version: 13
type: database
use_existing:
project_type: production
instance_name: EXISTING-DB-INSTANCE-IDENTIFIER
db_password_secret: DB-PASSWORD-SECRET-NAME
db_name: EXISTING-LOGICAL-DATABASE-NAME
db_username: USERNAME-FROM-DB-PW-SECRET
manage_databases: false
- If you are using Aurora, you should set the
instance_name
to the cluster name, and the additional configuration itemcluster_mode
totrue
. - If you are using a multi-AZ cluster for Postgres/MySQL, you should also set
use_db_proxy
tofalse
as they are not supported by AWS db proxy. You will need to add manually-managed variables to your environment to reach the read instance(s).
If you enable secrets rotation for your RDS secret in AWS, Coherence will not update the database connection info for your app until you deploy again. You should disable automatic rotation, or add logic in your app to get updated passwords from secrets manager directly in this case.
local_packages
Defines any paths in your repo that are installed to during container building, and which need to be copied to the host volume when mounting repo files into that container, for example in the cloud IDE.
- The most common use case here is an app that installs to
node_modules
.
Frontend Services
For frontend
services, the container built from the Dockerfile
at the root of repo_path
will be used in Workspaces as the dev server for the service, and in CI Build Pipelines to build static assets to be served by the CDN.
build
Defines the command used to compile assets for serving. If not provided, defaults to yarn build
.
Skip Build Step
If you would like to skip the frontend build
command, you will need to put build: ["echo", "hello"]
or something similar so tha t the default build command, yarn build
will not run.
build_path
This is the path in the repo where the build
command will place compiled assets that we should copy and serve from the CDN. Common values are build
, dist
or public
dev
Defines the command used to run the web server in Workspaces
- The port
3000
is reserved by Coherence for the IDE service. - The ports
80
and8088
are reserved for internal Coherence use.
local_packages
Defines any paths in your repo that are installed to during container building, and which need to be copied to the host volume when mounting repo files into that container, for example in the cloud IDE.
- The most common use case here is an app that installs to
node_modules
.
CORS
You can define additional origins that can request your assets using CORS. See an example below:
cors:
allowed_origins: ["www.example.com"]