Getting Started

Services

Coherence supports any application that can be containerized and which serves HTTP traffic. Here are some common examples. Be sure to review the documentation on database seeding and loading data from database snopshots, which apply to all Coherence applications.

Redwood.js

You can setup Redwood to deploy on Coherence with AWS or GCP with yarn rw setup deploy coherence. It should "just work" when you go through the onboarding flow at app.withcoherence.com.

A few notes:

  • prerender functionality for the web side is disabled by default. Get in touch with us to discuss how to enable it.
  • The default docker images will be built with nixpacks. The first build will take 15-20 minutes for your app to build and deploy, it should go below 10 mins for future builds (aside from when dependencies or OS base images change). To speed up deployments to an environment even more, you can create web and api specific Dockerfile's and get smaller and more controlled images. You can create the Dockerfile for each side, e.g. Dockerfile.web and then can configure Coherence to use it as the prod.dockerfile for each service. See here for some rough examples.

The default redwood CLI command will setup one coherence.yml file where the web side serves at / and the api side serves from the same domain at /api. The yml looks like:

api:
  type: backend
  url_path: "/api"
  prod:
    command: ["yarn", "rw", "build", "api", "&&", "yarn", "rw", "serve", "api", "--apiRootPath=/api"]
  dev:
    command: ["yarn", "rw", "build", "api", "&&", "yarn", "rw", "dev", "api", "--apiRootPath=/api"]
  local_packages: ["node_modules"]

  system:
    cpu: 2
    memory: 2G
    health_check: "/api/health"

  resources:
    - name: YOURNAME-db
      engine: postgres
      version: 14
      type: database
      adapter: postgresql

  # If you use data migrations, use the following instead:
  # migration: ["yarn", "rw", "prisma", "migrate", "deploy", "&&", "yarn", "rw", "data-migrate", "up"]
  migration: ["yarn", "rw", "prisma", "migrate", "deploy"]

web:
  type: frontend
  assets_path: "web/dist"
  prod:
    command: ["yarn", "rw", "serve", "web"]
  dev:
    command: ["yarn", "rw", "dev", "web", "--fwd=\\"--allowed-hosts all\\""]

  # Heads up: Redwood's prerender doesn't work with Coherence yet.
  # For current status and updates, see https://github.com/redwoodjs/redwood/issues/8333.
  build: ["yarn", "rw", "build", "web", "--no-prerender"]
  local_packages: ["node_modules"]

  system:
    cpu: 2
    memory: 2G

An alternate approach is to setup 2 different coherence.yml files with 2 different apps. If you're migrating from a service where you had a subdomain for each service (e.g. api.yourcompany.com and app.yourcompany.com) you might want to use this approach. Read more about routing in a monorepo here. If you want to set this up, please get in touch so we can configure the yml filenames for your app. The yml in this approach will look like this:

coherence.api.yml (or whatever you want):

api:
  type: backend
  prod:
    command: ["yarn", "rw", "build", "api", "&&", "yarn", "rw", "serve", "api"]
  dev:
    command: ["yarn", "rw", "build", "api", "&&", "yarn", "rw", "dev", "api"]
  local_packages: ["node_modules"]

  system:
    cpu: 2
    memory: 2G
    health_check: "/health"

  resources:
    - name: YOURNAME-db
      engine: postgres
      version: 14
      type: database
      adapter: postgresql

  # If you use data migrations, use the following instead:
  # migration: ["yarn", "rw", "prisma", "migrate", "deploy", "&&", "yarn", "rw", "data-migrate", "up"]
  migration: ["yarn", "rw", "prisma", "migrate", "deploy"]

coherence.app.yml (or whatever you want):

web:
  type: frontend
  assets_path: "web/dist"
  prod:
    command: ["yarn", "rw", "serve", "web"]
  dev:
    command: ["yarn", "rw", "dev", "web", "--fwd=\\"--allowed-hosts all\\""]

  # Heads up: Redwood's prerender doesn't work with Coherence yet.
  # For current status and updates, see https://github.com/redwoodjs/redwood/issues/8333.
  build: ["yarn", "rw", "build", "web", "--no-prerender"]
  local_packages: ["node_modules"]

  system:
    cpu: 2
    memory: 2G

By using build glob configuration you can minimize the duplicated builds across both apps each time you push when configuring more than one app in a repo.

React Exmaple

See a full example repo here.

frontend:
  type: frontend
  assets_path: dist
  local_packages: ["node_modules"]
  build: ["yarn", "build"]
  dev: ["yarn", "dev"]

Django Example

See a full example repo (this repo includes a react frontend and a django backend) here.

Here's an example video of setting up a Django app

A few other things you'd want to do:

  • Install dj-database-url package to easily get the right database configuration. You can add this to your requirements.txt file.
    • If you're using GCP, you also want to set the HOST property of your database configurations to be /cloudsql/INSTANCE_NAME using the _INSTANCE value on the Variables tab of your Coherence environments.
  • Make sure to use COHERENCE_DEV environment variable to set the DEBUG value in your settings.
  • Add the COHERENCE_ENVIRONMENT_DOMAIN and COHERENCE_CUSTOM_DOMAIN to the ALLOWED_HOSTS settings to prevent CORS issues.
  • You can configure the prod command to use another python WSGI server like gunicorn as well by changing the command in the yaml configuration below.

See the Environment Variables docs for more info on the variables mentioned above.

The /opt/venv/bin/activate command is needed due to how nixpacks handles python installs. You can remove that command (including the &&) if you use your own Dockerfile and python packages are available on the PATH by default.

server:
  type: backend
  migration: [".", "/opt/venv/bin/activate", "&&", "python", "manage.py", "migrate"]
  dev: [".", "/opt/venv/bin/activate", "&&", "python", "manage.py", "runserver", "0.0.0.0:$PORT"]
  prod: [".", "/opt/venv/bin/activate", "&&", "python", "manage.py", "runserver", "0.0.0.0:$PORT"]

  resources:
  - name: db1
    engine: postgres
    version: 14
    type: database
    adapter: postgresql

Rails Example

If you use the Nixpacks builder (the Coherence default if you don't define a Dockerfile) than the asset precomile step will be handled for you. If you write a Dockerfile be sure to include it. The /root/.profile command is needed due to how nixpacks handles ruby gem installs. You can remove that command (including the && - meaning just use bundle directly) if you use your own Dockerfile and ruby gems are available on the PATH by default.

See an example of setting up a Ruby on Rails app

rails:
  type: backend
  migration: [".", "/root/.profile", "&&", "bundle", "exec", "rails", "server:migrate"]
  dev: [".", "/root/.profile", "&&", "bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
  prod: [".", "/root/.profile", "&&", "bundle", "exec", "rails", "server", "-e",  "production", "-b", "0.0.0.0"]

  system:
    memory: 2G
    cpu: 2

  resources:
  - name: db1
    engine: postgres
    version: 14
    type: database

You will also want to modify the database.yml (and any other initializers you use, like S3/GCS for storage or redis for cache) to read their config from the appropriate Coherence-supplied environment variables. See the Environment Variables docs for more info on the variables. Here's a simply database.yml example:

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  url: <%= ENV["DATABASE_URL"] %>

test:
  <<: *default
  url: <%= ENV["DATABASE_URL"] %>

production:
  <<: *default
  url: <%= ENV["DATABASE_URL"] %>

You'll also want to edit the application.rb initializer and edit the allowed hosts of your app. You might already have some entries for this in environment settings (e.g. development) so be careful not to break those. These are a bit loose but are intended as an example (but they'll work):

  config.hosts = [
    IPAddr.new("10.0.0.0/8")
  ]
  config.hosts << /.*\.coherencedev\.com\z/
  config.hosts << /.*\.coherencesites\.com\z/

Last, you'll also need to set any relevant environment variables required by your app, for example the SECRET_KEY_BASE variable. You can use the Coherence Variables UI to set these.

flask example

flask is a popular python web framework. This is a simple example, assuming your app does not need a database and that your app.py file runs the flask server on the PORT environment variable provided by Coherence when it is run via python. You can configure the dev or prod commands to use flask run or another python WSGI server like gunicorn as well by changing the commands in the yaml configuration below.

You can also add a database and cache easily, see the other examples on this page including the redwood and Rails examples above for syntax, nothing special needs to be done for flask itself, aside from listening to the appropriate variables to configure your database connections, e.g. DATABASE_URL.

backend:
  type: "backend"
  dev: ["python", "app.py"]
  prod: ["python", "app.py"]

FastAPI example

FastAPI is a popular python web framework. In this example, you've got a postgres database and are using uvicorn to serve the application. You'd change the app:app reference to follow the path to your actual app instance as per the FastAPI docs.

The /opt/venv/bin/activate command is needed due to how nixpacks handles python installs. You can remove that command (including the &&) if you use your own Dockerfile and python packages are available on the PATH by default.

backend:
  type: backend
  prod: [".", "/opt/venv/bin/activate", "&&", "uvicorn", "app:app", "--port=$PORT", "--host=0.0.0.0", "--reload"]
  dev: [".", "/opt/venv/bin/activate", "&&", "uvicorn", "app:app", "--port=$PORT", "--host=0.0.0.0", "--reload"]
  resources:
  - name: db1
    engine: postgres
    version: 15
    type: database

Next.js Example

There are 2 common configurations used for Next.js. One is static export where your site ends up as single page app served from a CDN. The other (more common) configuration is where you run a server process and this configuration supports functionality such as server-side rendering, API routes, and database-backed services. See more in the Next docs.

See an example of setting up a server type

For running a server process, use the backend service type on Coherence. See a full example repo here.

backend:
  type: backend
  local_packages: ["node_modules"]
  dev: ["npm", "run", "dev"]
  prod: ["npm", "run", "start"]

For deploying a single page app, use a frontend service type.

frontend:
  type: frontend
  local_packages: ["node_modules"]
  dev: ["npm", "run", "dev"]
  build: ["npm", "run", "export"]

streamlit example

streamlit is a popular python framework for full-stack, data-driven apps. You'll also want to check the filename in the command below and replace streamlit_app.py with your own app.

For database connection secrets, we recommend to use Coherence Variables and use the values in generating a Connection on streamlit (for most databases this means using the kwargs in the streamlit experimental_connection).

You can see a YouTube walk-though of setting up a streamlit app from scrach

streamlit:
  type: "backend"
  dev: ["streamlit", "run", "streamlit_app.py", "--server.port=$PORT", "--server.address=0.0.0.0", "--server.runOnSave=false"]
  prod: ["streamlit", "run", "streamlit_app.py", "--server.port=$PORT", "--server.address=0.0.0.0"]

You might also want to use a Dockerfile like this (otherwise we will use nixpacks and you need to do the venv commands similar to the Django example above):

FROM python:3.9-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \
    build-essential \
    curl \
    software-properties-common \
    git \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .

Refine

Refine is a meta-framework for react admin apps. For the most part, it should be just like a standard react app as above. You can see a live walk-thru video setting up a refine example app below!

dashboard:
  type: frontend
  assets_path: dist
  local_packages: ["node_modules"]
  build: ["yarn", "build"]
  dev: ["yarn", "start"]
Previous
Migration guide