Rails 7.2 Adds Support For Devcontainer.

A development container (or dev container for short) allows us to use a container as a full-featured development environment.

It can be used to run an application, to separate tools, libraries, or runtimes needed for working with a codebase, and to aid in continuous integration and testing.

Dev containers can be run locally or remotely, in a private or public cloud, in a variety of supporting tools and editors.

Importance of devcontainers

  • Consistency Across Environments DevContainers ensure identical development environments for all team members, reducing bugs from setup inconsistencies.

  • Simplified Onboarding New team members can quickly start coding without extensive setup, as the DevContainer configures everything automatically in VS Code.

  • Dependency Management Isolate project dependencies within the container, preventing conflicts with other projects or system-wide settings.

  • Portability Easily share and replicate development environments across different machines, ideal for remote teams and occasional contributors.

  • Integration with CI/CD Pipelines Align development, build, and test environments, leading to more reliable builds and fewer environment-specific issues.

Dev containers before Rails 7.2

Before Rails 7.2, devcontainer files were not generated with new Rails applications.

To use devcontainer with Rails prior to 7.2, we had to manually set up the necessary files and configuration.

The basic steps to add a dev container to a Rails application before 7.2 would be:

  • Create a .devcontainer directory at the top level of the Rails application repository.

  • Inside the .devcontainer directory, create a devcontainer.json file that specifies the image and features to use for the dev container.

  • Optionally, we could also create a Dockerfile in the .devcontainer directory to further customize the dev container image.

  • Finally, we would need to initialize the devcontainer using either VS Code or the devcontainer CLI.

Dev containers after Rails 7.2

Rails 7.2 now ships with devcontainers as an opt-in feature.

Adding devcontainer on a new rails app

rails new <app_name> --devcontainer

Adding devcontainer to an existing rails app

bin/rails devcontainer

Executing the above command will generate a .devcontainer folder and its contents by default.

The .devcontainer folder includes everything needed to boot the app and do development in a remote container.

The container setup includes:

  • A redis container for Kredis, ActionCable etc.
  • A database (SQLite, Postgres, MySQL or MariaDB)
  • A Headless chrome container for system tests
  • Active Storage configured to use the local disk and with preview features working

The default .devcontainer folder comes with these files compose.yaml, devcontainer.json and Dockerfiler

If any of these options are skipped in the app setup they will not be included in the container configuration.

Here is the default .devcontainer/compose.yaml

name: "app_name"

services:
  rails-app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile

    volumes:
    - ../..:/workspaces:cached

    # Overrides default command so things don't shut down after the process ends.
    command: sleep infinity

    networks:
    - default

    # Uncomment the next line to use a non-root user for all processes.
    # user: vscode

    # Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
    # (Adding the "ports" property to this file will not forward from a Codespace.)
    ports:
    - 45678:45678
    depends_on:
    - selenium
    - redis

  selenium:
    image: seleniarm/standalone-chromium
    restart: unless-stopped
    networks:
    - default

  redis:
    image: redis:7.2
    restart: unless-stopped
    networks:
    - default
    volumes:
    - redis-data:/data

  
volumes:
  redis-data:

Here is the default .devcontainer/devcontainer.json

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ruby
{
  "name": "app_name",
  "dockerComposeFile": "compose.yaml",
  "service": "rails-app",
  "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",

  // Features to add to the dev container. More info: https://containers.dev/features.
  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {},
    "ghcr.io/rails/devcontainer/features/activestorage": {},
    "ghcr.io/rails/devcontainer/features/sqlite3": {}
  },

  "containerEnv": {
    "CAPYBARA_SERVER_PORT": "45678",
    "SELENIUM_HOST": "selenium",
    "REDIS_URL": "redis://redis:6379/1"
  },

  // Use 'forwardPorts' to make a list of ports inside the container available locally.
  "forwardPorts": [3000, 6379],

  // Configure tool-specific properties.
  // "customizations": {},

  // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
  // "remoteUser": "root",

  "mounts": [
    {
      "type": "bind",
      "source": "/Users/prasanthchaduvula/Documents/rails",
      "target": "/Users/prasanthchaduvula/Documents/rails"
    }
  ],

  // Use 'postCreateCommand' to run commands after the container is created.
  "postCreateCommand": "bin/setup"
}

Here is the default .devcontainer/Dockerfile

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version
ARG RUBY_VERSION=3.2.2
FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION

Conclusion

With the recent addition of DevContainer support in Rails, they are a game-changer for modern software development, addressing many of the pain points associated with environment setup and dependency management.

By leveraging the power of Docker and the flexibility of VS Code, DevContainers offer a robust solution for creating consistent, portable, and efficient development environments.

Whether we are part of a large team or a solo developer, adopting DevContainers can significantly enhance our workflow and productivity.

References

Need help on your Ruby on Rails or React project?

Join Our Newsletter