There was talk of making the environment docker in order to proceed with the complete renovation at the part-time job. I decided to make it with the configuration of front end Nuxt.js and back end Rails 6, and I will be in charge of the back end part, so let's write a Dockerfile a lot! So I will introduce the completed configuration by implementing it for studying as well. How to make a Rails container is briefly written on Docker official page , but this time the Docker file considering Rails 6 I will also introduce how to write and how to create a MySQL container.
It was about a year and a half ago that I started touching rails as an individual, and my practical development experience as a web engineer is just over a year, which is not a long period of time. However, I am growing rapidly by taking advantage of the wide range of prerequisite knowledge I gained at university and the attitude of taking on various challenges. Even in the previous project, I was touching around docker, changing the database container (MarinaDB-> MySQL), creating a shell script for initial setting, etc. I didn't have a chance to make docker from scratch by myself, so I tried this time.
From here on, we will actually create an environment using docker.
First of all, I will briefly introduce the file structure.
Assuming that the name of the application to be created is sample
, the files related this time have the following file structure.
sample
|- backend --- app
| |- bin
| |- config --- ...
| | |- database.yml
| | |- ...
| |- ...
| |- Dockerfile
| |- Gemfile
| |- Gemfile.lock
| |- ...
|- db --- data --- ...
| |- my.cnf
|- docker-compose.yml
Actually, there will be more files (created), but these are the only files to be manipulated this time.
Next, I will describe the files related to docker. backend/Dockerfile This will be a file with instructions for building a Rails container. The contents are listed below, and the comments explain what each process is doing.
backend/Dockerfile
#Image and version to use
FROM ruby:2.7.1
#Install the required libraries
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs
#The following is rails 6 or later(Excluding API mode)Needed in
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
#Create a folder called app in the container
#* The folder is not created on the local PC.
RUN mkdir /app
#Change root to app directory
ENV APP_ROOT /app
WORKDIR $APP_ROOT
#Gemfile in local PC(.lock)Into the container
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock
#Execute bundle install to copy the files on the local PC into the container
RUN bundle install
ADD . $APP_ROOT
#The port number that the container listens on
EXPOSE 3000
#Command to be executed
CMD ["rails", "server", "-b", "0.0.0.0"]
Since rails6, Webpacker is the default, so if yarn
is not installed, an error will occur when doing rails new
.
However, you do not need to install yarn
when creating in API mode described later.
backend/Gemfile
Write Gemfile
in advance to install Rails.
This file will be rewritten later when you do rails new
.
Here, rails 6 or later version is specified.
backend/Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6'
backend/Gemfile.lock
When you do bundle install
, it will create something like a library blueprint based on the dependencies.
Create an empty one. Later I got an error if the file did not exist.
backend/Gemfile.lock
db/data/ Let's prepare only the directory
db/my.cnf This is a file related to MySQL settings.
my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
sql_mode=''
[client]
default-character-set=utf8mb4
The character code is set and the sql_mode
is set.
Especially, I think it is better to set sql_mode
.
This is because the default sql_mode
has changed from MySQL 5.7, and especially in modes such as ʻonly_full_group_by, it often throws an error, so it is explicit which
sql_mode` to use. Let's write it down. This time, no setting (default for MySQL 5.6.5 or earlier) is explicitly specified.
(I want to write more articles around here)
docker-compose.yml Finally write docker-compose. A brief explanation is given in the comments.
docker-compose.yml
version: "3"
services:
# MySQL
db:
#Image to build
image: mysql:5.7
#Specifying environment variables
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: spportunity
MYSQL_USER: root
MYSQL_PASSWORD: root
TZ: 'Asia/Tokyo'
#Set the character code to utf8mb4
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
# db/Mount the data directory on the container's mysql directory
- ./db/data/:/var/lib/mysql
# /db/my.cnf file my in container.Mount on cnf config file
- ./db/my.cnf:/etc/mysql/conf.d/my.cnf
ports:
- 3306:3306
#Rails
backend:
#Specify build source
build:
context: ./backend
dockerfile: Dockerfile
#Specifying the container name
container_name: "sample-backend"
#Command specification at startup Rails s is done after terminating the previous process
command: bash -c "rm -f tmp/pids/server.pid && rails s -p 3000 -b '0.0.0.0'"
#Mount the files in the backend folder to the app directory inside the container
volumes:
- ./backend/:/app
ports:
- "3000:3000"
#Start after db container
depends_on:
- db
Now that the file is ready, let's create a rails application.
Create a rails application using the docker-compose
command.
Make sure the current directory is sample
.
% docker-compose run backend rails new . --force --no-deps --database=mysql --skip-bundle
--Rewrite --force
... Gemfile
---- database = mysql
... Specify MySQL for the database
--Skip --skip-bundle
... bundle
(Gemfile.lock
is not changed yet)
% docker-compose run backend rails new . --force --no-deps --database=mysql --skip-bundle --api
---- api
... Creation options in API mode
When completed, you will have a large number of rails related folders and files in the backend /
folder.
I will write about the difference between API mode and normal mode and the difference between files.
% docker-compose build
Running this command will create a MySQL container and bundle install
in the rails container.
If you look at the console, you can see that the contents of the Dockerfile are being executed in order.
backend/config/database.yml
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: root
host: db
development:
<<: *default
database: sample
test:
<<: *default
database: sample_test
production:
<<: *default
database: sample_production
username: <%= ENV['APP_DATABASE_USER'] %>
password: <%= ENV['APP_DATABASE_PASSWORD'] %>
Change the connection information to the image of the MySQL container you created earlier for host, and the environment variables for the container you created earlier for your username and password.
% docker-compose run backend rails webpacker:install
% docker-compose run backend rails db:create
If you come to this point, the setting is complete. All you have to do is start docker!
% docker-compose up
When I access http: // localhost: 3000 / with a browser, Rails is launched successfully.
I didn't mention it this time, but by adding a frontend container etc., it will be possible to create an environment that combines a frontend application and an API server in one shot. In that case, you will have to create a Dockerfile and add a container to docker-compose in the same procedure. I'm still a front-end beginner, so I'd like to eventually make a front container as well.
After all docker is convenient. I didn't use docker in my personal development, but I'm thinking of using it positively from now on. In that case, I would like to write an article.
It was my first time to write an article about qiita, and when I was wondering how much I should write, it became quite long. However, there are many people who write a lot of very rich articles, and I feel that I still have a lot to do. I may not be able to write something that still has content often, but I would like to publish my knowledge little by little.
I referred to the following qiita article. I also imitated the writing style, which was very helpful. Thank you very much.
https://qiita.com/azul915/items/5b7063cbc80192343fc0 https://qiita.com/kodai_0122/items/795438d738386c2c1966
In addition to the above article, it also includes API mode, MySQL container mount and settings, etc., so please forgive the similar writing style.
Recommended Posts