Envirobly deploy file .envirobly/deploy.yml
is formatted using YAML.
It allows you to build, configure and deploy one or multiple services that work together within a private subnet and expose some or all of them to the public internet.
It’s loosely based on the Docker Compose file format.
# Top level "services" key is always required
services:
# Alphanumerical name you give to each of your services.
# It identifies them when interacting with your services
# using the CLI tool.
web:
# All services are private by default, unless you make them public.
public: true
# Only route requests to this service if this
# HTTP path responds successfully.
health_check_path: /up
# Command to run before the service is started, during each deploy.
# Guaranteed to run only once, even if you have multiple instances.
release_command: bin/rails db:prepare
# Minimum number of instances that run at all times.
min_instances: 1
# Auto scaling configuration.
# When CPU usage is over 60% for 1 minute,
# continue scaling up to max_instances.
max_instances: 2
# Environment variables that will be supplied to the container
env:
RAILS_ENV: production
# Define a secret and pull it from a local file
RAILS_MASTER_KEY: !secret <%= File.read("config/master.key") %>
DATABASE_URL: $POSTGRES_URL # Pulled from "postgres" service
# Before starting this service, first start the dependencies
depends_on:
- postgres
- valkey
domains:
- example.com
- www.example.com
# Private worker, build using a custom Dockerfile and build context
worker:
# Specify non-default Dockerfile
dockerfile: custom/Dockerfile.sidekiq
# Specify custom build context (instead of project's root directory)
build_context: some/other/directory
# Override image run command
command: bundle exec sidekiq
# Specify bigger compute instance
instance_type: t4g.small
# Postgres database
# Accessible from the outside over TLS with authentication due to `public: true`
postgres:
type: postgres
public: true
# Specify persistent volume size
volume_size: 48 # GB
# Valkey database
# Available on private network only, because there is no `public: true`
valkey:
type: valkey
The services
top level key is required.
It’s a mapping of service names with their configuration attributes.
Blog
and blog
refer to the same thing within Envirobly. You can use them interchangeably.By default, service is always private, reachable only by other services in the environ. To make it public:
services:
blog:
public: true
Type is used to create managed database services. You can choose between two types:
postgres
- PostgreSQL a general purpose relational database.valkey
- Valkey an in-memory key-value store, an open-source fork of Redis.services:
db1:
type: postgres
db2:
type: valkey
Services without type attribute are considered to be a container, either build or if image attribute is present, pulled from a public repository.
To deploy a pre-build image from a public repository, like Docker Hub:
services:
# Pull from Docker Hub
whoami:
image: traefik/whoami
# Pull from AWS ECR
nginx:
image: public.ecr.aws/nginx/nginx:stable
If no image or type attributes are present, Envirobly considers this service buildable and
by default expects a Dockerfile
to be present in the root of your project directory.
You can specify a custom file to build from:
services:
blog:
dockerfile: my/custom/path
Services that are build from a dockerfile, can override the default .
build context:
services:
blog:
build_context: my/custom/directory
Specify the startup command to launch the container with. If not set, image starts with it’s default command.
services:
blog:
command: bin/rails server --some-argument=hello
Specify a command to run during each deployment, exactly once, before the main command.
Useful for things like database migrations or other idempotent bootstrapping tasks.
It is guaranteed to run only on one instance, once during the deployment. If it fails, the deployment will roll back.
services:
blog:
release_command: bin/rails db:prepare
You can supply environment variables for your container as a mapping of name and value.
The value is interpolated and you can insert variables that other services export as well as local secrets.
services:
blog:
env:
PLAIN_VALUE: abcd
SENTENCE: "Hello world!"
IMPORTED_FROM_ANOTHER_SERVICE: $WHOAMI_PUBLIC_HOST
COMPLEX_INTERPOLATION: "https://${WHOAMI_HOST}"
# Passing in a local env var as a secret using embedded Ruby
SOME_PASSWORD: !secret <%= ENV["SOME_PASSWORD"] %>
# Service that exports $WHOAMI_HOST and $WHOAMI_PUBLIC_HOST
whoami:
public: true
To support zero downtime deployments, you can specify a health check path. The requests are routed to a newly started service only once the health check passes.
If your service has multiple instances, if an instance fails a health check, requests won’t be send to it, until it passes the health check again.
services:
blog:
health_check_path: /up
Attaches a persistent data volume to the service and mounts it into the container within the given path.
services:
blog:
volume_mount_path: /rails/storage
Default volume size is 24 GB.
Controls the size of persistent data volume attached with volume_mount_path.
The size must be a multiple of 4, as the volume consists of 4 EBS volumes in RAID 0 configuration, for optimal performance.
When a persistent volume is present, the service can only have a single instance.
Incrementing the volume size is a zero-downtime operation. After a volume size change, there is an AWS enforced cool-down period of 6 hours, during which you can’t change the volume size.
You can’t decrement the volume size. Removing this attribute from the service configuration, removes the volume,
unless the service is of postgres
or valkey
type, which always has a persistent volume attached.
Deployments that change the instance type or container configuration, incur several seconds of downtime, while the volume is detached and then attached to a new instance.
services:
blog:
volume_mount_path: /rails/storage
volume_size: 100
Controls the type of the compute instance. This is how you can control the amount of vCPUs and memory your service has access to.
It defaults to t4g.nano
, which is a 2 vCPU instance with 512 MB of memory. Note that ~140 MB of memory is
taken by the underlying operating system.
services:
blog:
instance_type: t4g.xlarge
To list available instance types and their attributes use the command line:
# List instance types in the `.envirobly/defaults/region` region or
# asks to set the default region
envirobly instance-types
# List instance types in the given region
envirobly instance-types us-east-1
Controls the number of instances that are always running. Defaults to one.
Can only be used if the service doesn’t have a persistent data volume attached.
services:
blog:
min_instances: 2
Set it to a number higher than min_instances to enable auto-scaling.
Once the combined CPU usage is over 60% for over 1 minute, the system will spin up new
service instances, until max_instances
is reached.
If the combined CPU usage is under 30% for at least 2 minutes, the system will start
scaling down, until max_instances
is reached.
services:
blog:
min_instances: 1
max_instances: 3
If your service needs other services to run, before it starts, you can list the names of the services it depends on. The service will only be started once the health checks of the dependent services succeed.
services:
blog:
depends_on:
- db1
- db2
db1:
type: postgres
db2:
type: valkey
You can route custom domains to your service.
You can also put your service behind a reverse proxy, like Cloudflare orange cloud,
in which case set the additional proxy
argument, for that domain, to true
. This means an external service will be handling the
HTTPS certificates and DNS.
services:
blog:
domains:
- example.com
- www.example.com
# Wildcards are supported, on all levels.
- "*.example.com"
- "*.sub.example.com"
# When hiding your deployment behind reverse proxy,
# like Cloudflare orange cloud.
- name: protected.example.com
proxied: true
Once deployed, visit your Envirobly dashboard, navigate to the service and click “Domains” within the service sub-menu. Here you’ll see instructions on how to set up your DNS. Once set up, click the “Validate” button, to complete the process.