docker-rails-example: a Rails app where Docker Compose is the only way to run it
A production ready example Rails app that's using Docker and Docker Compose.
At a glance
- What is it?
- nickjj's docker-rails-example is a production ready Rails 8.1 app that runs under Docker Compose with PostgreSQL, Redis, Sidekiq and a standalone Action Cable, and it is deliberately opinionated about the parts that matter in containers: logging to STDOUT, secrets from an .env file, and no credentials file. The run script is the interface, and everything runs through it.
- Who is it for?
- docker-rails-example suits a developer who wants a Rails deployment that works identically on a laptop, in CI and on a server, or who is Dockerizing an existing Rails application and wants a worked example of the decisions rather than a starting scaffold.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 38 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What it is: a worked example, not a scaffold
The repository is described as a production ready example Rails app using Docker and Docker Compose, and the README frames the choice of use explicitly. You could use this example app as a base for your new project, or as a guide to Dockerize your existing Rails app. The second framing is the more interesting one, because the author describes the example as minimal but wiring up a number of things you might use in a real world Rails app, while at the same time not being loaded up with a million personal opinions. The Docker bits are described as an accumulation of Docker best practices based on building and deploying dozens of assorted Dockerized web apps since late 2014. The app is using Rails 8.1.3.1 and Ruby 4.0.6, and the version numbers in the screenshot are placeholders because they get updated regularly.
The stack, and the removals that are the actual content
The back end is PostgreSQL, Redis, Sidekiq for background work through Active Job, a standalone Action Cable process and ERB for views. The front end is esbuild, Hotwire Turbo, StimulusJS, TailwindCSS and Heroicons. The notable opinions section is the part worth reading, because the removals are as informative as the additions. The solid_* adapters are removed for now, and so are Kamal and Thruster, for now, which tells you this is a container-first project that does not assume a deployment tool. The generated code around PWA and service workers is removed, Brakeman is removed, and Procfile.dev has been removed since Docker Compose handles this. On the additions, there is a pages controller with a home page, an up controller with two health check related actions, and custom 502.html and maintenance.html pages. The route for Sidekiq's dashboard is ready to be used but commented out for safety.
Configuration decisions: STDOUT logging and secrets from an .env file
Three configuration changes are the reason a Dockerised Rails app usually works at all. The application logs to STDOUT so that Docker can consume and deal with log output, rather than writing to log files inside the container that nobody collects. Credentials are removed, with secrets loaded in with an .env file, which is the piece that changes how you think about deployment, since there is no credentials file to keep out of version control. And a bunch of configuration settings are extracted into environment variables, with config/database.yml rewritten to use environment variables. There are also two initializers worth naming, one enabling YJIT and one enabling a rack mini profiler for profiling Hotwire Turbo Drive. And a .yarnc sets a custom node_modules/ directory, so the JavaScript dependencies live somewhere deliberate inside the container rather than wherever the base image put them.
The compose file: profiles, a two stage image and an assets service
The compose file is the centre of the project and its structure is worth reading. There are two extension templates, x-app and x-assets, both anchored on the same set of build args, an env_file pointing at .env, a restart policy defaulting to unless-stopped, a three second stop_grace_period and a tty. The app template's depends_on uses condition service_started with required false for postgres and redis, which is a Docker Compose v2 feature and the reason the README states the project uses features that only work with Docker Compose v2 2.20.2 and newer. The app service mounts a volume for the public directory, while the assets service mounts the whole project and runs under the assets profile. The services are postgres, redis, web, worker and cable, and the .env.example decides which of them start by setting COMPOSE_PROFILES, defaulting to postgres,redis,assets,web,worker,cable in development.
postgres:
image: "postgres:18.6-trixie"
profiles: ["postgres"]
restart: "${DOCKER_RESTART_POLICY:-unless-stopped}"
stop_grace_period: "3s"
volumes:
- "postgres:/var/lib/postgresql"
redis:
image: "redis:8.10.1-trixie"
profiles: ["redis"]
volumes:
- "redis:/data"The Dockerfile, and why it builds twice
The Dockerfile has an assets stage and an app stage, and the assets stage is where the front end is built. It starts from ruby:4.0.6-slim-trixie, installs build-essential, curl, git, libpq-dev and libyaml-dev, then adds the NodeSource apt repository and installs Node 24, enables corepack, and cleans the apt lists and the documentation directories to keep the layer small. It creates a ruby group and user with the APP_UID and APP_GID build args, defaulting to 1000, and makes a /node_modules directory owned by that user, so the container never runs the app as root and the node modules are writable. It copies the Gemfile and runs bundle install, then copies package.json and the yarn files and runs yarn install, then copies the application. Assets are precompiled only when the environment is not development, using a SECRET_KEY_BASE_DUMMY value. The app stage is a much slimmer image with the same base but only curl and libpq-dev.
FROM ruby:4.0.6-slim-trixie AS assets
LABEL maintainer="Nick Janetakis <[email protected]>"
WORKDIR /app
ARG APP_UID=1000
ARG APP_GID=1000
COPY --chown=ruby:ruby Gemfile* ./
RUN bundle install
COPY --chown=ruby:ruby package.json *yarn* ./
RUN yarn installRunning it: clone, copy the env file, build, and set up the database
The running instructions are short. You need Docker installed, and on Docker Desktop you need Compose v2 enabled, while on native Linux you install it as a Docker plugin. On Windows you are expected to be inside WSL or WSL 2, because the commands are shell commands. Then you clone the repository into a directory, copy .env.example to .env because the real one is git ignored, and run docker compose up --build, with the warning that the first time takes five to ten minutes depending on your connection and hardware because it downloads Docker images and builds the Ruby and Yarn dependencies. In a second terminal you run ./run rails db:setup, and then you visit http://localhost:8000. If you get a port in use error, the README points you at the DOCKER_WEB_PORT variable documented in the .env file.
git clone https://github.com/nickjj/docker-rails-example hellorails
cd hellorails
cp .env.example .env
docker compose up --build
./run rails db:setupThe run script is the interface, and it is the piece to copy
Everything goes through the run script, and the README highlights it as one of the two files of interest alongside the .env. It runs the application inside the container rather than on the host, so the local environment does not need Ruby or Node installed. The commands documented include ./run rails db:setup, ./run format, where the shorthand -a flag or --auto-correct applies any auto-correctable issues, ./run quality which lints and formats all files, and ./run test, with a -b flag that also builds the JavaScript and CSS bundles. There is also ./run rails secret, referenced from the .env example as the way to generate a more secure SECRET_KEY_BASE. For a team Dockerizing an existing application, this script is the artefact to copy, because it is what makes the container feel like the development environment rather than a packaging step you do at the end.
./run format
./run format --auto-correct
./run quality
./run test
./run test -bLicence, upkeep and what the repository does not cover
The licence is MIT, with the LICENSE file at the repository root, and the primary language is Ruby. The last push to the repository was on 2026-09-15, the repository is not archived, and there are no GitHub releases, since the deliverable is a repository you clone rather than a versioned artefact. The repository layout is a standard Rails application with the container files added, so there is a Dockerfile, a compose.yaml, a .dockerignore, a .env.example, a .hadolint.yaml for linting the Dockerfile, a .rubocop.yml, a Rakefile, a run script, a cable/ directory for the Action Cable process, a lib/ directory and a vendor/ directory. What the project deliberately does not provide is a deployment tool, since Kamal and Thruster are removed for now, and the README's additional resources section points at Docker and Ruby on Rails learning material and a separate deploy to production guide, which tells you where the project expects you to go next once the container is running.
Editorial conclusion
docker-rails-example suits a developer who wants a Rails deployment that works identically on a laptop, in CI and on a server, or who is Dockerizing an existing Rails application and wants a worked example of the decisions rather than a starting scaffold. It is the wrong choice if you want a Rails app with no container runtime anywhere, and a poor fit if you need a deployment tool already built in, because the README removes Kamal and Thruster for now and the compose file is the whole story. Before adopting it, read the .env.example, because the profiles and environment variables there decide which services start, and note the Docker Compose requirement of 2.20.2 or newer for the optional depends_on behaviour the project uses.
Frequently asked questions
What is the docker-rails-example project?
It is a production ready example Rails app that runs under Docker and Docker Compose, which you can use as a base for a new project or as a guide to Dockerize an existing Rails app. It uses Rails 8.1.3.1 and Ruby 4.0.6, with PostgreSQL, Redis, Sidekiq and a standalone Action Cable process.
How do I run the docker-rails-example app?
Clone the repository, copy .env.example to .env because the real one is git ignored, run docker compose up --build, then run ./run rails db:setup in a second terminal and visit http://localhost:8000. You need Docker Compose v2 2.20.2 or newer, and on Windows you are expected to work inside WSL or WSL 2.
How does the example handle secrets and logging?
Credentials are removed and secrets are loaded in with an .env file, and a bunch of configuration settings are extracted into environment variables, with config/database.yml rewritten to use them. The application logs to STDOUT so Docker can consume the log output rather than writing log files inside the container.
What does the run script do?
It is the interface for everything, running commands inside the container so the host needs no Ruby or Node install. The documented commands include ./run rails db:setup, ./run format with an --auto-correct shorthand of -a, ./run quality to lint and format all files, ./run test with a -b flag that also builds the JS and CSS bundles, and ./run rails secret to generate a SECRET_KEY_BASE.
Which services does the compose file define and how are they enabled?
The services are postgres, redis, web, worker and cable, each with a profile, and the .env.example sets COMPOSE_PROFILES, defaulting to postgres,redis,assets,web,worker,cable in development. The app template's depends_on uses service_started with required false, which is a Docker Compose v2 feature that needs 2.20.2 or newer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nickjj-docker-rails-example)Was this useful?