Deep-dive on the Next Gen Platform. Join the Webinar!

Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Troubleshooting Node.js Apps
      • Node.js Behavior in Heroku
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Deployment
  • Deploying with Docker
  • Building Docker Images with heroku.yml

Building Docker Images with heroku.yml

English — 日本語に切り替える

Last updated December 03, 2024

Table of Contents

  • Get Started
  • heroku.yml Overview
  • Setup: Define Your App’s Environment
  • Build: Define Your Build
  • Release: Configure Release Phase
  • Run: Define the Processes to Run
  • Review Apps and app.json
  • Known Issues and Limitations

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

  1. Create a heroku.yml file in your application’s root directory. This example heroku.yml specifies the Docker image to build for the app’s web process.

    build:
      docker:
        web: Dockerfile
    run:
      web: bundle exec puma -C config/puma.rb
    

    In this example, heroku.yml and Dockerfile are in the same directory. If the Dockerfile lives in a non-root directory, specify the relative path in the build.docker.web value, such as app/Dockerfile.

    If you don’t include a run section, Heroku uses the CMD specified in the Dockerfile.

  2. Commit the file to your repo.

    $ git add heroku.yml
    $ git commit -m "Add heroku.yml"
    
  3. Set your app’s stack to container.

    $ heroku stack:set container
    
  4. Push 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 provisioning
  • build – Specifies the Dockerfile to build
  • release – Specifies the release phase tasks to execute
  • run – 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 run section in heroku.yml. You must specify the command via the Dockerfile.
  • Private repositories/registries aren’t supported in the FROM line of the Dockerfile.
  • The Docker build context is always set to the directory containing the Dockerfile and can’t be configured independently.
  • The environment where heroku.yml builds 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 encounter Illegal instruction errors 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=generic to the compiler.
  • The known issues and limitations of the underlying container runtime also apply.

Keep reading

  • Deploying with Docker

Feedback

Log in to submit feedback.

Local Development with Docker Compose Container Registry & Runtime (Docker Deploys)

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices