Rails 6 production container with Docker

Rails with Docker

The official Rails image on the Docker hub is deprecated [3] for good reason, it doesn’t make sense to have a universal image for Rails as we are likely to customize it for our needs. Here a simple image to create a Rails app with Postgresql.

The Rails Dockerfile

docker build \
--build-arg BUNDLER_VERSION=2.2.14 \
--build-arg RAILS_VERSION=6.1.3 \
--build-arg APP_PATH=/work \
--tag joel/rails:3.0.0 \
.
docker image ls                                                                                                                             REPOSITORY TAG    IMAGE ID       CREATED          SIZE
joel/rails 3.0.0 93e8912fa836 24 minutes ago 649MB
docker build \
--build-arg BUNDLER_VERSION=2.2.14 \
--build-arg RAILS_VERSION=6.1.3 \
--build-arg APP_PATH=/work \
--progress=plain \
--no-cache \
--tag joel/rails:3.0.0 \
.

Create a Rails App

Now we can create the new Rails App.

docker run --rm \
--mount type=bind,source=$PWD,target=/work \
joel/rails:3.0.0 \
rails _6.1.3_ new weblog --database=postgresql
alias r="docker run --rm --mount type=bind,source=$PWD,target=/work joel/rails:3.0.0"

Starting Postgresql

We are using the Docker Postgresql Image.

docker network create weblog-bridge-docker-network
docker network ls                                                                                                                          NETWORK ID     NAME                            DRIVER    SCOPE
f3062d22ce7a weblog-bridge-docker-network bridge local
docker volume create weblog-db-data
docker volume ls                                                                                                                           DRIVER    VOLUME NAME
local weblog-db-data
docker run --rm --detach \
--name weblog-db \
--env POSTGRES_PASSWORD=postgres \
--env POSTGRES_USER=postgres \
--network weblog-bridge-docker-network \
--mount source=weblog-db-data,target=/var/lib/postgresql/data \
postgres:13.2-alpine

Start Redis

Before running our Rails app we need to start a Redis instance as ActionCable use it in production. If we follow along with the DHH weblog example we are going to need it.

docker volume create weblog-redis-data
docker run --rm --detach \
--name weblog-redis \
--network weblog-bridge-docker-network \
--mount source=weblog-redis-data,target=/data \
redis redis-server --save 60 1 --loglevel warning
group :production do
gem "hiredis"
end

Create a Resources

Let’s create something on our app.

r rails generate scaffold Post title:string body:text

Dockerize the Rails App

We are ready to Dockerize our Rails app

docker build --squash \
--tag joel/weblog:latest \
.
cat ~/.docker/daemon.json | jq                                                                                                             
{
"debug": true,
"experimental": true,
"features": {
"buildkit": true
}
}
docker images joel/weblog:latest --format "{{.Repository}}:{{.Tag}} {{.Size}}"

Create the Rails Image

Time to create the Docker image of our Rails App.

docker build --squash \
--tag joel/weblog:latest \
.

Starting the Rails App in Production Mode

Now everything is set up we can start our app.

docker run --rm \
--name weblog-prod-app \
--env RAILS_LOG_TO_STDOUT=true \
--env RAILS_MAX_THREADS=8 \
--env RAILS_MIN_THREADS=1 \
--env WEB_CONCURRENCY=1 \
--env REDIS_URL=redis://weblog-redis:6379/1 \
--env DATABASE_URL="postgres://postgres:postgres@weblog-db:5432/weblog_db_prod?pool=5" \
--network weblog-bridge-docker-network \
--publish 3025:3000 \
-it joel/weblog:latest sh
docker network inspect weblog-bridge-docker-network
docker exec weblog-prod-app sh -c 'rails db:setup'
docker exec weblog-prod-app \
sh -c 'rails server -p 3000 --early-hints -b 0.0.0.0'
docker run --rm \
--name weblog-prod-app \
--env RAILS_LOG_TO_STDOUT=true \
--env RAILS_MAX_THREADS=8 \
--env RAILS_MIN_THREADS=1 \
--env WEB_CONCURRENCY=1 \
--env REDIS_URL=redis://weblog-redis:6379/1 \
--env DATABASE_URL="postgres://postgres:postgres@weblog-db:5432/weblog_db_prod?pool=5" \
--network weblog-bridge-docker-network \
--publish 3025:3000 \
joel/weblog:latest rails server -p 3000 --early-hints -b 0.0.0.0

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store