DEV Community

Cover image for How to use Docker containers for Ruby on Rails development in Visual Studio Code
@kon_yu
@kon_yu

Posted on • Updated on

How to use Docker containers for Ruby on Rails development in Visual Studio Code

Introduction

It has become common practice to use Docker and Docker compose when building a development environment on a developer's machine. The theory is to run the docker compose command from the terminal to test and verify the operation, but we propose a convenient way to develop with VS Code by using the Dev Containers extension of VS Code.

In this article, we will show you how to set up Dev Containers using a Rails project.

If you want to debug using VS Code's debugging features, please refer to this post

How to debug Rails running on Ruby 3.1 using VSCode and Dev Containers

Purpose

To make Rails more convenient using VS Code and Docker (where Containers is mentioned below, it refers to Docker Containers and the group of containers launched with Docker Compose).

  • You can run a terminal in a container as if you were accessing a remote server via SSH, so you don't have to type docker commands like docker compose exec xxxx to make your development work easier.
  • The ability to specify VS Code extensions to run in the container standardizes the development environment by eliminating the need for developers to install and configure extensions such as Rubcop and Solargraph individually.

Body

Preparation

The sample code for this article can be found at the following URL (vscode tag)

GitHub - konyu/base_rails at vscode

Prerequisites

We tested the following environment

  • Mac with M2 CPU
  • Docker desktop for mac: 4.16.2
  • Ruby: 3.2.1
  • Rails: 7.0.4
  • MySQL: 8
  • Detailed version information can be found in the Dockerfile and docker-compose.yml.
  • Create an appropriate Rails project with the rails new command and create Post and Comment models with scaffold.

Create a base Dockerfile to run Rails

FROM ruby:3.2.1
ENV ROOT="/app"
ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo

WORKDIR ${ROOT}

COPY Gemfile ${ROOT}
COPY Gemfile.lock ${ROOT}

RUN gem install bundler
RUN bundle install --jobs 4
Enter fullscreen mode Exit fullscreen mode

Create a docker-compose.yml to define middleware.

version: '3'
services:
  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app:cached
      - bundle-volume:/usr/local/bundle
    ports:
      - 3000:3000
    depends_on:
      - db
    tty: true
    stdin_open: true
  db:
    image: mysql:8
    volumes:
      - mysql-volume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      TZ: "Asia/Tokyo"
    ports:
      - "3306:3306"
volumes:
  bundle-volume:
  mysql-volume:
Enter fullscreen mode Exit fullscreen mode
docker compose up
Enter fullscreen mode Exit fullscreen mode

Create a database

docker compose run --rm web rails db:prepare
Enter fullscreen mode Exit fullscreen mode

Access http://localhost:3000
and verify that the top page is displayed.


Configure container settings for remote

Install the VS Code extension Remote Development.

Add from the following link

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack

Since this is a pack of features for the following four expansion periods, you may only install Dev Containers for this use

  • Remote - SSH - Work with source code in any location by opening folders on a remote machine/VM using SSH. Supports x86_64, ARMv7l (AArch32), and ARMv8l (AArch64) glibc-based Linux, Windows 10/Server (1803+), and macOS 10.14+ (Mojave) SSH hosts.
  • Remote - Tunnels - Work with source code in any location by opening folders on a remote machine/VM using a VS Code Tunnel (rather than SSH).
  • Dev Containers - Work with a separate toolchain or container based application by opening any folder mounted into or inside a container.
  • WSL - Get a Linux-powered development experience from the comfort of Windows by opening any folder in the Windows Subsystem for Linux.

Add a configuration file to recommend (but not functionally enforce) the installation of this extension for other members.

.vscode/extensions.json

{
"recommendations": [
  "ms-vscode-remote.vscode-remote-extensionpack", // Remote Development
]
}
Enter fullscreen mode Exit fullscreen mode

Create a configuration file for Dev Containers.

.devcontainer/devcontainer.json

{
    "name": "Existing Docker Compose",
    "dockerComposeFile": [ //Override the first configuration with a second docker-compose.yml
"../docker-compose.yml",
"docker-compose.yml"
    ],
    "service": "web",//Specify the service name and Rails service to be started as described in docker-compse.yml
"workspaceFolder": "/app"// The directory to connect to at startup
}
Enter fullscreen mode Exit fullscreen mode

Create a docker-compose.yml to override, so that Rails is not started by the startup command.

.devcontainer/docker-compose.yml

version: '3'
services:
web:
  # Prevent Rails from starting when docker starts
  command: /bin/sh -c "while sleep 1000; do :; done"
Enter fullscreen mode Exit fullscreen mode

Open a container from VS Code.

Click on the green area in the lower left corner of VS Code or select Ropen in Container from the command palette. Specify the extensions to use in the container

Image description

Image description

Specify extensions to use inside the container

Extensions installed outside of a container cannot be used inside a container. They must be installed anew. This may seem inconvenient at first glance, but extensions to be used in a container can be specified in a configuration file to simplify setup.

In this case, the following extensions will be installed

  • solargraph
  • rubocop
  • Ruby extension
  • rdbg * for debugging

Add .devcontainer/devcontainer.json file.

{
  // omitted

  // Extensions to use in containers
    "customizations": {
        "vscode": {
            "extensions": [
                "castwide.solargraph", // solargraph
                "rebornix.Ruby", // Ruby syntax highlighting, etc.
                "misogi.ruby-rubocop", // Rubocop
                "KoichiSasada.vscode-rdbg", // Ruby Debug see below
            ]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Configure VS Code for your project.

Configure project-specific settings. Here we set the indentation of Ruby to space 2.

.vscode/settings.json

{
  "[ruby]": {
      "editor.tabSize": 2
  }
}
Enter fullscreen mode Exit fullscreen mode

Add gem for Solergraph and Rubocop to Gemfile

Specify the gem to be installed for use in extensions.

group :development do
gem 'solargraph'
gem 'rubocop', require: false
gem 'rubocop-rails', require: false
gem 'rubocop-performance', require: false
end
Enter fullscreen mode Exit fullscreen mode

Confirmation of plugin operation

Please confirm that Rubocp and Solargraph are running by launching the container from VS Code.

Rubocop.

The familiar Linter for Ruby can be found in the Problems panel.

Image description

Solargraph

It is a useful tool for auto-completion and jumping to method and class definitions. If you are not using it, please try it.

The combination of Solargraph and VS Code is complicated to set up if you try to run it from outside a container, but using Dev Containers makes it easy to set up.

Solargraph: A Ruby Language Server

Image description

Rhythm of Rails development with Dev Containers

By using Dev Containers to develop, you can open a terminal in a Rails container, so you can develop as if you were developing locally without using Docker.

Image description

When executing commands from outside the container to Rails inside the container, you need to consider both Docker commands and Rails commands, which can be a bit brain-intensive.

If you set up Docker Compose to start Rails at startup, it is convenient to compare the commands to Rails from outside the container and the commands to Rails from inside the container, as shown in the table below.

Commands to Rails from outside the container Commands to Rails from inside the container
docker compose run --rm web bundle install bundle install
docker compose run --rm web bin/rails db:migrate bin/rails db:migrate
docker compose exec web bin/rails c bin/rails c
docker compose exec web bundle exec rspec bundle exec rspec
docker compose run -e EDITOR=emacs web bin/rails credentials:edit bin/rails credentials:edit

You can also start the rails server from the Terminal panel and run rspec from the terminal, so you can stop at breakpoints to check the operation.

Image description

Tips

If you want to get out of the container

Run Reopen Folder Locally from the command palette.

Image description

If you think your configuration is not reflected.

It is easy to solve this problem by rebuilding the container. You can try either of the following from the command palette

Image description

Pros and Cons

Pros

  • VS Code extensions can be standardized among development members
  • Easier to set up extensions that use Ruby in containers
  • VS Code terminal can work in a container, so you can skip Docker (Docker Component) commands for development
  • Easier to debug with breakpoints when launching Rails in a development environment
  • Easier to check operation and investigate bugs because docker attach command is not required

Cons

  • Not applicable for editors other than VS Code
  • Dev Containers extension is a bit quirky
  • Can't use the shell settings in the container with the usual development environment
  • Should we include Zsh, incremental search, aliases, etc.

Conclusion

I have shown how to use Docker and Docker compose and the VS Code extension Dev Containers when developing with VS Code, and I have shown an example from a Rails project.

Personally, my favorite part is the ease of setting up Solargraph and not having to use the docker attach command.

Top comments (0)