DEV Community

Cover image for How Makefile Helps Rails Developers
Ilya N. Zykin
Ilya N. Zykin

Posted on

How Makefile Helps Rails Developers

Introduction

Several years ago, I needed a quick playground for launching Rails applications for new projects and experiments. I also create video lectures and masterclasses on Rails, and I needed a project where my program attendees could practice their skills.

This is how the RailsStart project was created, which allows launching Rails applications quickly, almost instantly.

The main goal of the project - to enable running Rails on any operating system with literally one command.

In this article, I will tell you about the importance of Makefile for implementing my project. Its architecture is based on the elegant use of Makefile - a tool that transforms complex Docker and Rails commands into simple and understandable calls.

What are Make and Makefile?

Make is a build automation utility that manages the compilation and build process of software. It uses a file called Makefile, which describes the rules and dependencies for building a project.

Makefile is a text file containing a set of instructions for the Make utility.

Makefile is commonly used in C/C++ projects for compilation, in system administration for task automation, in DevOps for deployment management, and in various projects for standardizing development commands.

In my project, Make and Makefile are of great importance. These tools allow me to automate project setup and Rails application launch.

Thanks to the simplicity of Make, launching a Rails application in my project is done simply, elegantly, and with literally one command.

What do you need to run Rails Start?

To run Rails Start, you need only three tools familiar to any developer:

  • Git - to get the project from GitHub
  • Make - to run the automatic installation process
  • Docker - to run the application in a container

If these tools are available on your operating system, you can consider that the Rails application will be installed in less than 5 minutes.

Why do I use Make instead of Ruby scripts?

The first version of the project relied on automation and launch scripts based on Ruby technologies.

However, to make the process universal for host machines where Ruby might not be installed, I switched to using the popular Make, which can be used both on the host machine and in a container.

Advantages of Make over Ruby scripts:

  • Universality - Make is available on virtually all Unix systems
  • Independence - does not require Ruby installation on the host system
  • Simplicity - clear syntax for command automation
  • Standardness - a familiar tool for developers

Two-Level Makefiles Architecture

The key feature of RailsStart lies in the two-level Makefiles system:

The RailsStart project uses 2 levels of Makefiles. One level is designed for use at the host system level (the computer you work on), the second level of Makefiles is designed for use inside Docker containers.

I try to adhere to unified and consistent command names so that identical commands can be run at different levels using approximately identical Make commands.

1. Host Level (Project)

Location: /Makefiles/

This level is responsible for managing Docker containers and orchestrating the entire project. Host-level commands automatically delegate execution to the appropriate containers, providing a uniform interface:

# Simple launch of the entire project
make rails-start

# Container management
make start    # Start containers
make stop     # Stop containers
make status   # Container status

# Delegating Rails commands to container
make rails-console     # Open Rails console
make rails-db-migrate  # Run migrations
make rails-server      # Start Rails server
Enter fullscreen mode Exit fullscreen mode

Main functions:

  • Docker Compose management
  • Project environment setup
  • Command delegation to containers
  • File structure organization
  • Unified interface for all operations

2. Container Level

Location: /__RailsApp__/Makefiles/

This level contains commands that are executed directly inside the Rails container. Commands have similar names to host commands but are executed in the container context:

# Commands inside container
make setup      # Rails application setup
make console    # Rails console
make db-migrate # Database migrations
make server     # Start Rails server
make bundle     # Install gems
Enter fullscreen mode Exit fullscreen mode

Main functions:

  • Rails-specific commands
  • Database management
  • Dependency management (bundler)
  • Generators and testing
  • Direct execution in Rails application context

Modular Structure

Each level is organized with sets of Makefile files with specific purposes for better structure and maintenance:

rails-start/
├── Makefiles/                   # Host level
│   ├── 100_Project.mk           # Docker and project management
│   ├── 200_Rails.mk             # Rails command delegation
│   ├── 300_Rails-Production.mk  # Production environment
│   └── 400_env.mk               # Environment variables management
│
└── __RailsApp__/
    └── Makefiles/               # Container level
        ├── 100_Project.mk       # Common container commands
        ├── 200_Rails.mk         # Rails development
        └── 300_Production.mk    # Production commands
Enter fullscreen mode Exit fullscreen mode

Host level:

  • 100_Project.mk - Docker and project management
  • 200_Rails.mk - Rails command delegation
  • 300_Rails-Production.mk - Production environment
  • 400_env.mk - Environment variables management

Container level:

  • 100_Project.mk - Common container commands
  • 200_Rails.mk - Rails development
  • 300_Production.mk - Production commands

Advantages of This Approach

1. Command Uniformity at Different Levels

Thanks to unified command names, developers can use similar commands both on the host and inside the container:

# On host
make rails-console     # Delegates to container
make rails-db-migrate  # Delegates to container

# Inside container (after make rails-bash)
make console           # Executes directly
make db-migrate        # Executes directly
Enter fullscreen mode Exit fullscreen mode

2. Ease of Use

# Instead of complex command:
docker compose -f ./docker/docker-compose.yml exec rails_app bundle exec rails db:migrate

# Simply:
make rails-db-migrate
Enter fullscreen mode Exit fullscreen mode

3. Command Unification Across Operating Systems

Whether you work on macOS, Linux, or Windows (via WSL), the commands remain the same.

4. Self-Documentation

make help                   # General help
make rails-help             # Rails commands
make project-help           # Project management
make rails-production-help  # Production commands
Enter fullscreen mode Exit fullscreen mode

5. Transparent Command Delegation

Host commands are automatically delegated to containers, maintaining interface uniformity:

# On host (Makefiles/200_Rails.mk)
rails-console:
    docker compose -f $(COMPOSE_FILE) exec rails_app make console

rails-db-migrate:
    docker compose -f $(COMPOSE_FILE) exec rails_app make db-migrate

# In container (__RailsApp__/Makefiles/200_Rails.mk)
console:
    bundle exec rails console

db-migrate:
    bundle exec rails db:migrate
Enter fullscreen mode Exit fullscreen mode

This architecture allows developers not to think about where exactly the command is executed - the system automatically chooses the right context.

Practical Examples

Quick project start:

git clone https://github.com/the-teacher/rails-start.git
cd rails-start
make rails-start  # All ready!
Enter fullscreen mode Exit fullscreen mode

Daily development:

make rails-console     # Open Rails console
make rails-db-migrate  # Run migrations
make rails-logs        # View logs
make rails-status      # Check processes
Enter fullscreen mode Exit fullscreen mode

Database operations:

make rails-db-create   # Create database
make rails-db-seed     # Seed with data
make rails-db-reset    # Full reset (with warning)
Enter fullscreen mode Exit fullscreen mode

Generators and testing:

make rails-bash                             # Enter container
make generate-model name=User               # Create model
make generate-controller name=Users         # Create controller
make test                                   # Run tests
Enter fullscreen mode Exit fullscreen mode

Conclusion

Makefile is not commonly found in Rails projects, and this technology is not very widespread for working with Rails applications. However, the RailsStart project shows an example of an effective and elegant solution for running Rails on any operating system.

Makefile in the RailsStart project doesn't just simplify commands - it creates a unified management interface for the entire Rails application lifecycle.

The two-level architecture provides clear separation of responsibilities between infrastructure management (host) and application development (container).

This solution is especially valuable for:

  • Development teams - workflow unification
  • New project members - quick understanding of available commands
  • DevOps practices - deployment standardization
  • Rails learning - focus on development rather than environment setup

RailsStart proves that a properly organized Makefile can transform a complex Docker + Rails environment into a simple and intuitive development tool.


Glossary

Host machine - a physical or virtual computer on which Docker and other software runs. In the context of the article - your working machine (macOS, Linux, Windows).

Container - an isolated application runtime environment created using containerization technology. Contains the application and all its dependencies.

Docker - a platform for developing, delivering, and running applications in containers. docker.com

Docker Compose - a tool for defining and running multi-container Docker applications. docs.docker.com/compose

Make - a build automation utility for managing compilation and command execution. gnu.org/software/make

Makefile - a configuration file for the Make utility, containing rules and commands for task automation.

Rails (Ruby on Rails) - a web framework for the Ruby programming language. rubyonrails.org

Git - a distributed version control system. git-scm.com

WSL (Windows Subsystem for Linux) - a Windows subsystem for Linux that allows running a Linux environment on Windows. docs.microsoft.com/windows/wsl

Top comments (0)