2025-01-21 12:32:00
impactahead.com
Back to blog
Deploying Rails on Docker: Kamal alternative
Paweł Dąbrowski
Founder / Software Engineer
Recently, Basecamp, the creators of Ruby on Rails, released a solution for deploying it on bare metal servers. Kamal is Capistrano for Containers and is an alternative solution to Capistrano, Kubernetes, and Docker Swarm.
If you want to deploy your Rails application on a bare metal server but do not like how Kamal works, there is a good and more straightforward alternative: Dokku. It’s Heroku, but for your own server.
I’ve been using Dokku for years, and it works perfectly. With support for Sidekiq, ElasticSearch, and other application components, you can prepare the production environment for Rails in minutes. In this article, I will walk you through preparing the server environment and deploying the Rails application. As a bonus, I will show you a tool called Deployless that automates the whole setup for your production and staging environments.
Getting started
The first step is to download and run the Dokku installation script on the server. The solution can be installed on the newest Ubuntu and Debian 11+ distributions.
SSH to your server, download the installation script, and run it:
wget -NP . https://dokku.com/install/v0.35.12/bootstrap.sh
sudo DOKKU_TAG=v0.35.12 bash bootstrap.sh
The installation should take around 5 minutes to complete. Once it’s finished, the next step is to add an SSH key so you can deploy your application using GIT just like it’s possible with Heroku:
echo "public ssh key" | sudo dokku ssh-keys:add admin
In the same way, you can add the next users who can deploy the application. To add access to the server, edit ~/.ssh/authorized_keys
and paste the SSH key of the person you want to authenticate.
Creating new application
Creating a new application is straightforward. All you need to do is to invoke the create command:
dokku apps:create myrailsapp
If you push the application right now, Dokku will detect that you are pushing a Rails application and install the specified Ruby version. However, we can’t do it now because we haven’t determined the correct environment variables yet.
Let’s start with creating a sample Rails application with support for PostgreSQL as a database engine:
rails _8.0.1_ new myrailsapp --skip-kamal —skip-docker --skip-solid --skip-thurster --skip-devcontainer --database=postgresql
We can now return to the server and take care of the database.
High-Performance Active Record
Master the art of database optimization in Rails applications. Learn proven techniques to improve your Ruby on Rails application performance.
Database configuration
We have already done a base configuration of Dokku. Regarding additional components for our application, Dokku uses plugins to handle them easily. The first step is to install the PostgreSQL plugin:
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
The next step is to create the database itself. Because we operate on the containers, we must make the database accessible for our app containers. This process is called linking.
Let’s create the database:
dokku postgres:create myrailsapp-db
Then, let’s link the database container to the application:
dokku postgres:link myrailsapp-db myrailsapp
Thanks to this operation, Dokku automatically configured the DATABASE_URL
environment variable that contains the connection string for our application. Regarding environment variables, let’s add the base variables for the application right now.
Environment variables
Basic Rails application, needs some base environment variables to work correctly. For example, the SECRET_KEY_BASE
value is used to generate various security keys for the environment. You can generate the desired value by running rails secret and then copying the value.
Besides the mentioned environment variable, let’s also add some others to make sure we are running the app in production mode:
dokku config:set myrailsapp SECRET_KEY_BASE=mysecret RAILS_ENV=production RACK_ENV=production RAILS_LOG_TO_STDOUT=enabled RAILS_SERVE_STATIC_FILES=enabled
Once you add the environment variables, Dokku will handle application update, so you don’t have to worry about it. Since we haven’t pushed the application’s source code, the process takes just a second.
Domain and SSL configuration
The easiest way to configure the domain with the Dokku application is to define the A record in DNS settings pointing to the server IP address. I’m going to do this right now, using the myrailsapp.impactahead.com subdomain for the purpose of this article.
I’m using Cloudflare, but the process will be the same for most DNS providers. Copy the server IP address, select A record, define the subdomain (or leave the subdomain field empty if you want to use the domain), and paste the IP record. If you are also using Cloudflare, turn off the proxy status.
Go back to the server; the next step is to clear default domain values and add the domain:
dokku domains:clear-global
dokku domains:clear myrailsapp
dokku domains:add myrailsapp myrailsapp.impactahead.com
The process of configuring the SSL certificates is also simple. Dokku uses the Lets Encrypt plugin to handle all related processes. Let’s install it:
sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git letsencrypt
The last step of the configuration is the information about e-mail to which information about SSL expiration will be delivered:
dokku letsencrypt:set myrailsapp email your-email
We can now enable SSL for our application. The plugin will attempt to configure the certificate and update the server configuration. At this stage, the DNS change should already be propagated; otherwise, the SSL verification will fail. Execute the following command:
dokku letsencrypt:enable myrailsapp
After the SSL is generated, we are done with the server configuration. If you don’t want to renew the SSL certificate manually, you can set up the cron to do it automatically:
dokku letsencrypt:cron-job --add
Rails application preparation for deployment
We need to tell Dokku that we want to use a worker to run our web server. To do this, create Procfile
file in the main directory with the following lines:
web: bundle exec rails server -p $PORT -e $RAILS_ENV
release: bundle exec rails db:migrate
Update Gemfile
with your Ruby version declaration and run bundle install:
The last step is to add GIT remote so we can deploy our application in a Heroku way:
git remote add dokku dokku@ip-address:myrailsapp
We can now push our application:
git add .
git commit -m "Hello world"
git push dokku main
Dokku doesn’t need Dockerfile to correctly install dependencies for the Rails app; specified Ruby version is enough. After the deployment is complete, you can visit the configured domain, but you will see a 404 error. We haven’t specified the root page. You can create a simple HomeController
with an index action that will render “Hello world” and make it a root page. Deploy the app again, and you should see the welcome screen.
Master the art of database optimization in Rails applications. Learn proven techniques to improve your Ruby on Rails application performance.
Bonus: deployment automation with deployless
Usually, deploying the Rails application on Dokku requires the same steps. To make the deployment configuration much faster, I created the Deployless gem, which makes it effortless. While your Dokku configuration is prepared, you can make yourself a coffee.
Start with adding the gem to the development group:
group :development do
gem "deployless"
end
Run bundle install
to install the library. Prepare the IP address of your server and the domain you would like to use for the application. Run the interactive setup:
You need to provide some basic details, such as the server IP address, username, path to your SSH key, and application name. Once you are finished, a .deployless.yml
file is created, and the .gitignore
file is updated to exclude this configuration file from the repository.
You can now trigger the deployment configuration for the production environment by invoking the following command:
The library will connect to the server, install Dokku, and prepare all components for your application. All you have to do is to ensure that a proper DNS record is added to make the domain available for the server – the library will stop the process and ask if this step is ready to finish the domain and SSL configuration.
Once the process is finished, you can add a new GIT remote and push the code to deploy the application. If you inspect .deployless.yml
file, you will also notice the environment variables. Once you update them, you can force the change on the server by running:
dpls production update-env
Connecting to the production Rails console is also effortless as executing the following command:
Keep your files stored safely and securely with the SanDisk 2TB Extreme Portable SSD. With over 69,505 ratings and an impressive 4.6 out of 5 stars, this product has been purchased over 8K+ times in the past month. At only $129.99, this Amazon’s Choice product is a must-have for secure file storage.
Help keep private content private with the included password protection featuring 256-bit AES hardware encryption. Order now for just $129.99 on Amazon!
Support Techcratic
If you find value in Techcratic’s insights and articles, consider supporting us with Bitcoin. Your support helps me, as a solo operator, continue delivering high-quality content while managing all the technical aspects, from server maintenance to blog writing, future updates, and improvements. Support Innovation! Thank you.
Bitcoin Address:
bc1qlszw7elx2qahjwvaryh0tkgg8y68enw30gpvge
Please verify this address before sending funds.
Bitcoin QR Code
Simply scan the QR code below to support Techcratic.
Please read the Privacy and Security Disclaimer on how Techcratic handles your support.
Disclaimer: As an Amazon Associate, Techcratic may earn from qualifying purchases.