[Ruby] Procedure for migrating Rails application development environment to Docker even if you have no experience (Rails 5 + MySQL8.0 + docker-compose)

3 minute read

Introduction

This is a summary of how an inexperienced writer who has no knowledge of Docker migrates the development environment of his Rails application to Docker.

The transition period was about a week including basic learning (if there were no errors, it could be completed in about half…)

I hope that it will be useful for those who want to try Docker and are stuck with errors.

Environment

  • Mac OS
  • Ruby 2.5.1
  • Rails 5.2.4
  • MySQL8.0 (*)

**※Note! ** MySQL has different default authentication format between 5.0 and 8.0. (As of 2020/8/18) Due to this, the description of the file (docker-compose.yml) required to create Docker differs depending on the version. ** Therefore, please make sure that the version of MySQL you are using matches the version of MySQL written in the literature.

Basic learning

Teaching Material: Introduction Docker

Getting Started Docker is a hands-on, free site where you can easily learn terms and structures related to Docker.

If you don’t know anything about Docker, it will take about half a day to one day even if you try all the contents, so please study roughly with Introduction Docker. recommend.

Premise

  • I have an existing Rails application
  • Migrate development environment and test environment to Docker

Files required to use Docker

There are three files to add and modify to existing applications:

  • Dockerfile
  • docker-compose.yml
  • database.yml

The file structure is as follows.

sampleApp ---- Dockerfile # file to add
           |-- docker-compose.yml # file to add
           |-- Gemfile
           |-- Gemfile.lock
           |-- README.md
           |-- Rakefile
           |-- app
           |-- bin
           |-- config ---- application.rb
           | |-- boot.rb
           | |-- cable.yml
           | |-- credentials.yml.enc
           | |-- database.yml # file to modify
           | |-- environment.rb
           | |-- environments
           | |-- initializers
           | |-- locales
           | |-- master.key
           | |-- puma.rb
           | |-- routes.rb
           | |-- spring.rb
           | |-- storage.yml
           |
           |-- config.ru
           |-- db
           |-- lib
           |-- log
           |-- package.json
           |-- public
           |-- storage
           |-- test
           |-- tmp
           |-- vendor

Dockerfile

Dockerfile



Specify #Docker Image. Specify the version of the app you are using.
FROM ruby:2.5.1

# Install required packages. For node.js, an error occurred if it was the original description, so fix it.
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash-&& apt-get update && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt /lists/*
RUN apt-get update && apt-get install -y mysql-client --no-install-recommends && rm -rf /var/lib/apt/lists/*

# Create and set working directory
RUN mkdir /workdir
WORKDIR /workdir

# Add host side (local) Gemfile to /workdir created above
ADD Gemfile /workdir/Gemfile
ADD Gemfile.lock /workdir/Gemfile.lock

# Gemfile bundle install
I ran without #ENV and got an error. Avoid by specifying BUNDLER_VERSION.
ENV BUNDLER_VERSION 2.1.4
RUN gem install bundler
RUN bundle install

# Add all directories on the host side (local) under /workdir of Dokekr container.
ADD ./workdir

docker-compose.yml

docker-compose.yml



# Specify the version of docker-compose. I used '3' this time.
version: '3'

# Define the container to start. In this file, db, db-test and web are defined.
services:
  db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password# Change the default authentication format to mysql_native_password. Not required for MySQL 5.0 series.
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: appname_development
      MYSQL_USER: yuki # any user
      MYSQL_PASSWORD: password
      TZ: Asia/Tokyo
    volumes:
      -./mysql/mysql_data:/var/lib/mysql
      -./logs:/var/log/mysql
      -./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    ports:
      -"4306:3306"

  db-test:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: appname_test
      MYSQL_USER: yuki
      MYSQL_PASSWORD: password
      TZ: Asia/Tokyo
    volumes:
      -./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    tmpfs:
      -/var/lib/mysql
      -/var/log/mysql
      
  web:
    build:
      context:.
      dockerfile: Dockerfile
    command: /bin/sh -c "rm -f /workdir/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    depends_on:
      -db
    ports:
      -"3000:3000"
    volumes:
      -.:/workdir

database.yml

database.yml



default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") {5} %>

development:
  <<: *default
  database: appname_development
  username: yuki
  password: password
  host: db
  socket: /tmp/mysql.sock

test:
  <<: *default
  database: appname_test
  host: db-test
  username: yuki
  password: password
  socket: /tmp/mysql.sock

production:
  <<: *default
  database: <%= ENV['DB_NAME'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  host: <%= ENV['DB_HOSTNAME'] %>

Start Docker/Create DB

``


$ docker-compose build # build container
$ docker-compose up -d # start all containers

$ docker-compose run web bundle exec rake db:create #DB creation
$ docker-compose run web bundle exec rake db:migrate #migration

If you can do so far, you should be able to access at http://localhost:3000.