How to use Docker containers for Ruby on Rails development in Visual Studio Code
Tags: ruby, rails, vscode
Published: 2023-03-17 07:25:41

---
title: How to use Docker containers for Ruby on Rails development in Visual Studio Code
published: true
description: 
tags: Ruby, Rails, VSCode 
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nv7l80dou57ooezskgun.jpeg
# Use a ratio of 100:42 for best results.
# published_at: 2023-03-17 00:30 +0000
---

# 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](https://dev.to/konyu/how-to-debug-rails-running-on-ruby-31-using-vscode-and-dev-containers-166l)

# 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](https://github.com/konyu/base_rails/tree/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
```
  
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:
```
  
```
docker compose up
```
  
Create a database
  
```
docker compose run --rm web rails db:prepare
```

Access [http://localhost:3000](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](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](https://aka.ms/vscode-remote/download/containers)** for this use
 
- **[Remote - SSH](https://aka.ms/vscode-remote/download/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](https://marketplace.visualstudio.com/items?itemName=ms-vscode.remote-server)** - 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](https://aka.ms/vscode-remote/download/containers)** - Work with a separate toolchain or container based application by opening any folder mounted into or inside a container.
- **[WSL](https://aka.ms/vscode-remote/download/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
]
}
```
  
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
}
```
  
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"
```

### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8331pwpiw3s1tbozipq.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgfp9d18jr8d79iindim.png)

## 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
			]
		}
	}
}
```

### 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
  }
}
```

### 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
```

### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zzwyp1lo2r25erjcmt35.png)


**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](https://solargraph.org/)  

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxhoywq2uyfu2zgyng1m.png)



## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hb1vtn1tci0jj4iudtgt.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2esxsipovb8libfst3q.png)

## Tips
### If you want to get out of the container
  
Run `Reopen Folder Locally` from the command palette.  

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r8eas1zlfcybtml6h9ij.png)


### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z135o0yres0x2efm2fy.png)

# 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.