FerryDocs
Guides

Environments

Run staging next to production on one server, with the same names, each on its own private network.

Edit on GitHub

An is a group of services and datastores with its own . Each server has the environment production. Create staging next to it, and test each change there before it goes to production. Staging uses the same names and the same settings as production. A service of staging cannot reach production by name.

Terminal
ferry environments create staging

Create an environment

Terminal
ferry environments create staging
Output
Created environment 'staging' (env-3f9a0c1b2d4e5f60718a)
Its web services are served at https://<service>.staging.example.com

Create this DNS record where the DNS of example.com is managed, for *.staging.example.com:
TYPE   NAME        VALUE
A      *.staging   203.0.113.10

ferry environments lists the environments. ferry environments show staging shows its services, its datastores and its DNS record.

A name has 1 to 40 lowercase letters, digits or -, and starts with a letter. You cannot change the name later.

Add services and datastores

Give --environment when you create a service or a datastore:

Terminal
ferry db create shop-db --environment staging
ferry create shop --image nginx:alpine --environment staging
ferry up shop --environment staging

Without --environment, Ferry puts the service or the datastore in production. You cannot move it to another environment later. In the dashboard, the form of a new service and the dialog of a new datastore have the field Environment.

To see the services of one environment, run ferry services --environment staging. ferry db ls --environment staging does the same for datastores.

Use the same names

Each environment can use the names of the other environments. Thus staging can have web, api and db, with the same settings as production. Then the change that you test in staging is the change that goes to production.

Terminal
ferry create api --image ghcr.io/acme/api:2.4 --environment staging
ferry env set web --environment staging DATABASE_URL='${{datastore.db.connectionString}}'
ferry deploy api --environment staging

A name is unique in its environment. If staging has api, Ferry refuses a second api in staging:

Terminal
error: name 'api' is already in use in environment 'staging' (conflict)

When a name is in more than one environment, tell Ferry which one you mean:

WhereHowWithout it
CLI--environment staging on each command that takes a service or a datastore nameproduction
API?environment=staging on each route of one service or datastoreproduction
DashboardThe URL has the name of the environment: /services/api.staging/services/api is the service of production

Thus a script that runs ferry deploy api continues to deploy the api of production. A service id works in all environments. When a name is only in another environment, the error tells you which one:

Terminal
error: service 'shop' not found in environment 'production' (environment 'staging' has one): name its environment, e.g. --environment staging in the CLI or ?environment=staging in the API (not_found)

Two services with the same name never share a container, an image, a volume or a URL. Outside production, a Docker name has the name of the environment after the name of the service or datastore. For example, the datastore db of staging has the container ferry-ds-db.staging and the volume ferry-ds-db.staging-data. Production keeps its Docker names.

A service of production cannot have the name of another environment. An environment cannot have the name of a service of production. The DNS record of the environment hides the URL of that service. For the same reason, an environment cannot have the first part of the address of the dashboard, for example ferry for ferry.example.com.

The URL of a service

A or a outside production gets the name of its environment in its URL:

EnvironmentServiceURL
productionwebhttps://web.example.com
stagingwebhttps://web.staging.example.com

Production keeps the URLs that it had before environments. Custom domains work in each environment.

Each environment needs one DNS record for each domain of the server: *.staging.example.com, with the address of the server. ferry environments create and the dashboard show the record. A local domain needs no record: http://shop.staging.localhost:8080 works immediately.

What a service reaches

Each container joins the network of its environment only. A run joins the network of its service.

From a container of staging, toResult
A service or a datastore of staging, by nameIt connects. http://api:8080 is the api of staging.
A service or a datastore of production, by nameThe name does not resolve.
A container of production, by its IP addressNo connection, except to a port that Ferry publishes (see below).
The public URL of a production serviceIt connects, through the proxy.

A finds the datastores and the services of the same environment only. When web has DATABASE_URL=${{datastore.db.connectionString}} in both environments, each web gets the db of its environment. If a variable of a staging service refers to a datastore that is only in production, the deploy fails before the build:

Deploy log
cannot resolve environment variables: env var DATABASE_URL: datastore 'db' is not in environment 'staging' (it is in 'production'): a service only reaches the datastores and services of its own environment

ferry env set gives a warning for this variable before it saves.

Env groups belong to the whole server, and you can link one group to services of different environments. A reference in a group finds the datastores and the services of the environment of each service. An env group shows a service of another environment as api.staging.

Blueprints apply to production only. A blueprint does not change the services of staging that have the same names. See the blueprint reference.

Delete an environment

Terminal
ferry environments rm staging

Ferry refuses while the environment has services or datastores. Delete them first, for example with ferry delete api --environment staging:

Terminal
error: environment 'staging' still holds service 'shop', datastore 'shop-db': delete them first (conflict)

Ferry then removes the network of the environment. You cannot delete production.

On this page