Skip to content

Docker Compose

If you are using Docker Compose based deployments, you need to understand how Docker Compose works with Coolify.

In all cases the Docker Compose (docker-compose.y[a]ml) file is the single source of truth.

Defining environment variables

Coolify will notice the environment variables you mention in your compose file and will display it in its UI.

services:
myservice:
environment:
- SOME_HARDCODED_VALUE=hello # Gets passed to the container but will not be visible in Coolify's UI
- SOME_VARIABLE=${SOME_VARIABLE_IN_COOLIFY_UI} # Creates an uninitialized environment variable editable in Coolify's UI
- SOME_DEFAULT_VARIABLE=${OTHER_NAME_IN_COOLIFY:-hello} # Creates an environment variable of value "hello" editable in Coolify's UI

Coolify's UI for environment variables

Coolify’s magic environment variables

Additionally, Coolify can generate some dynamic environment variables for you. The syntax is SERVICE_<TYPE>_<IDENTIFIER>. Type may be one of:

  • FQDN: This will generate an FQDN for the service. The example below shows how you can add paths and ports.
  • URL: Generates an URL based on the FQDN you have defined.
  • USER: Generates a random string using Str::random(16). You might want to use it as a username in your service.
  • PASSWORD: Generates a password using Str::password(symbols: false). Use PASSWORD_64 to generate a 64 bit long password with Str::password(length: 64, symbols: false).
  • BASE64: Generates a random string using Str::random(32). For longer strings, use BASE64_64 or BASE64_128.
  • REALBASE64: Encodes a randomly generated string using base64_encode(Str::random(32)). For longer strings, use REALBASE64_64 or REALBASE64_128.

Every generated variable can be reused and will always have the same value for every service. All generated variables are displayed in Coolify’s UI for environment variables and can be edited there (except FQDN and URl).

As an example, imagine an application with UUID vgsco4o (generated by Coolify on creation). It uses a compose file deploying Appwrite on the wildcard domain http://example.com .

services:
appwrite:
environment:
# http://appwrite-vgsco4o.example.com/v1/realtime
- SERVICE_FQDN_APPWRITE=/v1/realtime
# _APP_URL will have the FQDN because SERVICE_FQDN_APPWRITE is just a simple environment variable
- _APP_URL=$SERVICE_FQDN_APPWRITE
# http://appwrite-vgsco4o.example.com/ will be proxied to port 3000
- SERVICE_FQDN_APPWRITE_3000
# http://api-vgsco4o.example.com/api will be proxied to port 2000
- SERVICE_FQDN_API_2000=/api
# Coolify generates password and injects it as SERVICE_SPECIFIC_PASSWORD into the container
- SERVICE_SPECIFIC_PASSWORD=${SERVICE_PASSWORD_APPWRITE}
not-appwrite:
environment:
# Same value as in Appwrite service
- APPWRITE_PASSWORD=${SERVICE_PASSWORD_APPWRITE}
# As SERVICE_FQDN_API is not the same as SERVICE_FQDN_APPWRITE
# Coolify will generate a new FQDN
# http://not-appwrite-vgsco4o.example.com/api
- SERVICE_FQDN_API=/api

Storage

You can predefine storage normally in your compose file, but there are a few extra options that you can set to tell Coolify what to do with the storage.

Create an empty directory

# Predefine directories with host binding
services:
filebrowser:
image: filebrowser/filebrowser:latest
volumes:
- type: bind
source: ./srv
target: /srv
is_directory: true # This will tell Coolify to create the directory (this is not available in a normal docker-compose)

Create a file with content

Here you can see how to add a file with content and a dynamic value that is coming from an environment variable.

services:
filebrowser:
image: filebrowser/filebrowser:latest
environment:
- POSTGRES_PASSWORD=password
volumes:
- type: bind
source: ./srv/99-roles.sql
target: /docker-entrypoint-initdb.d/init-scripts/99-roles.sql
content: |
-- NOTE: change to your own passwords for production environments
\set pgpass `echo "$POSTGRES_PASSWORD"`
ALTER USER authenticator WITH PASSWORD :'pgpass';
ALTER USER pgbouncer WITH PASSWORD :'pgpass';

Exclude from healthchecks

If you have a service that you do not want to be part of your overall healthchecks, you can exclude it from the healthchecks by setting the exclude_from_hc option to true.

services:
some-service:
exclude_from_hc: true
...

Connect to Predefined Networks

By default, each compose stack is deployed to a separate network, with the name of your resource uuid. This will allow to each service in your stack to communicate with each other.

But in some cases, you would like to communicate with other resources in your account. For example, you would like to connect your application to a database, which is deployed in another stack.

To do this you need to enable Connect to Predefined Network option on your Service Stack page, but this will make the internal Docker DNS not work as expected.

Here is an example. You have a stack with a postgres database and a laravel application. Coolify will rename your postgres stack to postgres-<uuid> and your laravel stack to laravel-<uuid> to prevent name collisions.

If you set Connect to Predefined Network option on your laravel stack, your laravel application will be able to connect to your postgres database, but you need to use the postgres-<uuid> as your database host.

Raw Docker Compose Deployment

You can set with docker compose build pack to deploy your compose file directly without most of Coolify’s magic. It is called Raw Compose Deployment.

Labels

Coolify will still add the following labels (if they are not set) to your application:

labels:
- coolify.managed=true
- coolify.applicationId=5
- coolify.type=application

To use Coolify’s Proxy (Traefik), you need to set the following labels to your application:

labels:
- traefik.enable=true
- "traefik.http.routers.<unique_router_name>.rule=Host(`coolify.io`) && PathPrefix(`/`)"
- traefik.http.routers.<unique_router_name>.entryPoints=http