Rails 7.1 and later ship a production-ready Dockerfile in every new app. Hangar builds that file directly, so there is nothing to translate: the image you would build locally is the image that runs.
Before you start
- A Rails app in a Git repository, with the generated
Dockerfileandbin/docker-entrypoint. For an app created before Rails 7.1, runbin/rails app:updateor use the automatic builder. - The contents of
config/master.key. - A Hangar account.
1. Create the database
In a new project, add a PostgreSQL service and pick a region. Open it and copy the internal connection URL.
2. Create the Rails service
Add a service from your repository in the same region. In its Settings → Source choose Dockerfile; the default path, Dockerfile, is the one Rails generates.
3. Set the variables
RAILS_MASTER_KEY=<contents of config/master.key>
DATABASE_URL=<the internal connection URL>
Rails reads DATABASE_URL on its own and merges it over config/database.yml.
4. Trust the proxy
Hangar terminates TLS and forwards requests to your app over HTTP. Tell Rails so it does not redirect in a loop:
# config/environments/production.rb
config.assume_ssl = true
config.force_ssl = true
5. Deploy and add a domain
Deploy the service. The generated entrypoint runs db:prepare, which creates the schema on the first deploy and migrates it on later ones.
In Settings → Networking, add your hostname, turn HTTPS on and set the container port to the port in your Dockerfile's EXPOSE line: 80 for the Rails 8 Dockerfile, which starts the app behind Thruster, and 3000 for Rails 7.1 and 7.2.
Background jobs
Run Sidekiq, Solid Queue or another worker as a second service from the same repository, with the same variables and a different start command:
bundle exec sidekiq
Sidekiq needs Redis: add a Redis database to the project and set REDIS_URL. Share DATABASE_URL and REDIS_URL as environment variables referenced by both services, as described in Environment variables.
Uploaded files
A container's filesystem is replaced on every deploy. Store Active Storage uploads in S3-compatible object storage, or attach a volume to the service if you keep them on disk.
Troubleshooting
Missing secret_key_baseorActiveSupport::MessageEncryptor::InvalidMessage:RAILS_MASTER_KEYis missing or does not match the credentials file.- Too many redirects:
config.assume_sslis not set. - 502 on the domain: the container port does not match the
EXPOSEline of the Dockerfile.