Last updated December 03, 2024
The heroku.yml file is a manifest used to:
- Build Docker images on Heroku
- Specify add-ons and config vars to create during app provisioning
- Take advantage of Review Apps when deploying Docker-based applications
The Heroku container stack is intended for advanced use cases only. Unless you have a specific need for custom
Docker images, we recommend using Heroku’s default buildpack-powered build system. It
offers automatic base image security updates and language-specific optimizations. It also avoids the need to maintain a Dockerfile.
This article is only applicable to Cedar-generation apps.
Get Started
Create a
heroku.ymlfile in your application’s root directory. This exampleheroku.ymlspecifies the Docker image to build for the app’swebprocess.build: docker: web: Dockerfile run: web: bundle exec puma -C config/puma.rbIn this example,
heroku.ymlandDockerfileare in the same directory. If theDockerfilelives in a non-root directory, specify the relative path in thebuild.docker.webvalue, such asapp/Dockerfile.If you don’t include a
runsection, Heroku uses theCMDspecified in theDockerfile.Commit the file to your repo.
$ git add heroku.yml $ git commit -m "Add heroku.yml"Set your app’s stack to
container.$ heroku stack:set containerPush your app to Heroku.
$ git push heroku main
After building your application, Heroku uses the run command provided in heroku.yml instead of your Procfile.
heroku.yml Overview
A heroku.yml manifest has four top-level sections.
setup– Specifies the add-ons and config vars to create during app provisioningbuild– Specifies theDockerfileto buildrelease– Specifies the release phase tasks to executerun– Specifies process types and the commands to run for each type
Here’s an example that illustrates using a heroku.yml manifest to build Docker images.
setup:
addons:
- plan: heroku-postgresql
as: DATABASE
config:
S3_BUCKET: my-example-bucket
build:
docker:
web: Dockerfile
worker: worker/Dockerfile
config:
RAILS_ENV: development
FOO: bar
release:
command:
- ./deployment-tasks.sh
image: worker
run:
web: bundle exec puma -C config/puma.rb
worker: python myworker.py
asset-syncer:
command:
- python asset-syncer.py
image: worker
Setup: Define Your App’s Environment
Configure Add-Ons
heroku.yml supports creating add-ons at app provisioning time. To provision an add-on, add it to the setup.addons section.
setup:
addons:
- plan: heroku-postgresql
as: DATABASE
With the as option, you can attach multiple instances of the same add-on provider with different names.
Set Config Vars
heroku.yml supports setting config vars at app provisioning time. To set a config var, add it to the setup.config section.
setup:
config:
S3_BUCKET: my-example-bucket
Build: Define Your Build
Specify Dockerfile using paths relative to heroku.yml.
build:
docker:
web: Dockerfile
worker: worker/Dockerfile
The Docker build context is set to the directory containing the Dockerfile.
If you don’t specify a run section, the CMD specified in the Dockerfile is used.
Set Build Time Environment Variables
With the config field of the build section, you can set environment variables available to the build environment. Variables set in this section don’t create runtime config vars. Also runtime config vars, such as those config vars set with heroku config:set, aren’t available at build time.
build:
config:
RAILS_ENV: development
FOO: bar
Each build time environment variable must match an ARG line in your Dockerfile.
ARG RAILS_ENV=production
ARG FOO
Target a Stage from a Multi-Stage Build
With a multi-stage Docker build, you can manage build and production images for your application in a single Dockerfile. For example, you want to have specific packages or database migration scripts only available at build and release time, but not in your final production image.
Here’s an example of a multi-stage Dockerfile. The builder stage includes database migration scripts, and the production stage only has the app code and dependencies required to run the app.
FROM heroku/heroku:22-build AS builder
...
FROM heroku/heroku:22 AS production
...
Here’s an example heroku.yml that specifies only using the output of the builder stage as the release image.
build:
docker:
release:
dockerfile: Dockerfile
target: builder
web: Dockerfile
Release: Configure Release Phase
With release phase, you can run tasks before a new release deploys to production. For example, sending CSS/JS/assets to a CDN, priming cache stores, or running database schema migrations.
To define a release phase command, specify a release section with a command in your heroku.yml manifest and the image that you want to use.
build:
docker:
web: Dockerfile
worker: worker/Dockerfile
release:
image: worker
command:
- ./deployment-tasks.sh
Runtime config vars, such as a database connection URL, are available during the release phase.
If you want to see streaming logs as the release phase executes, your Docker image must have curl. If your Docker image doesn’t include curl, release phase logs are available in your application logs. If you’re using a Heroku stack as your base image, curl is included.
Run: Define the Processes to Run
In the run section, you can define the process that you want Heroku to run when your application starts. If your project also includes a Procfile, it’s ignored and usesrun instead.
run:
web: bundle exec puma -C config/puma.rb
To use a specific Docker image for multiple processes, specify it with image.
build:
docker:
web: Dockerfile
run:
web: bundle exec puma -C config/puma.rb
worker:
command:
- python myworker.py
image: web
If you don’t include a run section in your heroku.yml manifest, the Dockerfile CMD is used.
To learn more about the runtime requirements for Docker images, review the Container Registry and Runtime documentation.
Review Apps and app.json
An app.json file is still required when using Review Apps with the heroku.yml manifest. Be sure to set the stack value in your app.json file to container.
Apps using Docker images can’t use pr-predestroy scripts. These scripts get ignored if included in your app.json file.
Known Issues and Limitations
- Caching of Docker image layers isn’t supported.
- Private Spaces don’t honor the
runsection inheroku.yml. You must specify the command via the Dockerfile. - Private repositories/registries aren’t supported in the
FROMline of the Dockerfile. - The Docker build context is always set to the directory containing the
Dockerfileand can’t be configured independently. - The environment where
heroku.ymlbuilds occur can use a slightly different CPU generation at runtime, depending on the choice of runtime environment and dyno size. As a result, it’s possible that binary executables compiled for a specific CPU instruction set don’t work at runtime. If you encounterIllegal instructionerrors at runtime, try adjusting the build time compilation options to disable CPU-specific optimizations. When using GCC, disable them by passing-march=x86-64 -mtune=genericto the compiler. - The known issues and limitations of the underlying container runtime also apply.