When I was a beginner of Docker / Rails and used Docker-compose
to build the environment of Rails6
We were able to build the environment safely with the information provided by a knowledgeable person.
However, it is very difficult for me as a beginner to understand what is being executed in the construction contents.
Unlike when building the environment with Rails5
, if you made a mistake in the processing items, you could not build the environment.
I think there are multiple points in building the environment.
In this article, based on the matters that you consulted and answered
--Disassemble and explain the code at the time of environment construction and perform your own learning and knowledge fixation --Use as a memorandum of your own and a manual when building an environment in the future ――Intention that other people can use it as a reference material as much as possible.
I summarized it for the above purpose.
There may be mistakes because you are a beginner, but if you notice something, I would appreciate it if you could point out. If you find it helpful, I would be grateful if you could ** LGTM </ font> **.
Docker-compose
Those who want to use it as soon as possible and build it are published in the GitHub repository below. The procedure is described in the README, but please execute the following commands in order.
git clone <Project name>
from the README on the following sitecd <Project name>
./qs setup
commandIt takes about 20 minutes to complete the command. Please be patient. (Lol) When you're done, hit localhost: 3000 in your browser and you'll see the familiar Rails initial screen. Docker's Dashboard should also have web, db containers in the project name.
First, create from the Dockerfile. When creating a Dockerfile
--Official site
Docker Quickstart
The explanation of the above site is easy to understand.
Containers created with images defined in
Dockerfile
should be ephemeral if possible. Our "ephemeral" means that it can be stopped and destroyed, and is clearly built and usable with minimal setup.
As quoted from the above site, Dockerfile
aims to be built with the minimum setup.
In the following, we will explain the Dockerfile
created this time for each item.
FROM ruby:2.7
ENV LANG C.UTF-8
ENV DEBCONF_NOWARNINGS yes
ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE yes
ENV XDG_CACHE_HOME /tmp
EXPOSE 3000
If you don't use the part marked with *, you can delete it.
RUN apt-get update -qq && apt-get install -y \
build-essential \
libpq-dev \
vim \
less \
graphviz
Since Webpack has become the standard since Rails6, an error will occur without yanr installation.
RUN apt-get install apt-transport-https
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y yarn
# setting work directory
RUN mkdir /app
WORKDIR /app
--To use when entering a script or container
ENV HOME /app
COPY Gemfile /app/Gemfile
If you describe all of the above, it will be as follows. (* Some comments have been added.)
# use ruby version 2.7
FROM ruby:2.7
# using japanese on rails console
ENV LANG C.UTF-8
# remove warn
ENV DEBCONF_NOWARNINGS yes
ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE yes
ENV XDG_CACHE_HOME /tmp
EXPOSE 3000
# install package to docker container
RUN apt-get update -qq && apt-get install -y \
build-essential \
libpq-dev \
vim \
less \
graphviz
# install yarn
RUN apt-get install apt-transport-https
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install -y yarn
# setting work directory
RUN mkdir /app
WORKDIR /app
# setting environment value
ENV HOME /app
# executing bundle install
COPY Gemfile /app/Gemfile
The current situation is 3.
version: '3'
db`` redis
chrome`` web: & app
spring`` solagraph
which is likely to be used this time. Dockerfile
etc. is located, but basically it is .
and it is the current directory.Supplementary matters
shm_size
.:
<<: *app
tty: true
This is also summarized below by describing all of the above.
version: '3'
services:
db:
image: postgres
ports:
- "5432:5432"
volumes:
- data:/var/lib/postgresql/data:cached
environment:
POSTGRES_PASSWORD: postgres
redis:
image: redis
ports:
- "6379:6379"
command: redis-server --appendonly yes
volumes:
- redis-data:/data:cached
chrome:
image: selenium/standalone-chrome
ports:
- "4444:4444"
web: &app
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app:cached
- bundle:/usr/local/bundle:cached
- /app/.git
environment:
HOME: /app
RAILS_ENV: development
ports:
- "3000:3000"
tty: true
links:
- db
spring:
<<: *app
command: bundle exec spring server
ports: []
solargraph:
<<: *app
command: bundle exec solargraph socket --host=0.0.0.0 --port=7658
ports:
- "8091:7658"
links: []
volumes:
bundle:
driver: local
data:
driver: local
redis-data:
driver: local
Summarize the execution contents with a shell script. By doing this, you can realize that Dockerfile
can be stopped / destroyed and can be built and used with obviously the minimum setup. Shell scripts are those used to execute Unix commands.
Although it is not a commentary article on the shell script, I will extract and describe the basics so that I can understand the target shell script. I referred to the following site for article creation and understanding of shell operation. [Introduction of basic commands for beginner shell scripts] https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337 [Shell Script Reference] https://shellscript.sunone.me/
--Declaration
#!/bin/bash
Required to declare shell scripts.
There is also a way to write #! / Bin / sh
, but if you use the unique function of bash
, sh
will be NG.
Referenced site: https://sechiro.hatenablog.com/entry/20120806/1344267619
Unless you are particular about it, you can use #! / Bin / bash.
--Comment out Just add # at the beginning.
--Output Output with ʻecho`
--if condition
--The basic way to write ʻif is ʻif [condition] then command fi
.
--If the condition is true, execute the following command with then
.
--For different conditions Check ʻelif [Condition 2] . --If there is no true condition, execute the following command of ʻelse
to exit.
--If there is no else`, it will end as it is.
--How to take arguments
When accessing a variable, put $
before the variable name. Or put $
and enclose the variable in {}
.
-e
Escape special text
$*
All arguments are processed as one. There is $ @
in a similar process.
If you do not enclose it in double quotes, it is the same as $ @, but if you enclose it, it will be output for each argument,
There is a difference in whether to output all at once with one argument.
$1
1st argument
$0
Script name
--Function
In shell scripts you can write and quote functions
Function () { echo }
End processing To end the script prematurely, give a number to the ʻexit` command.
Swith
The basic way to write a switch is the case variable in condition / value) command ;; esac
.
If the condition / value matches the variable, execute the following command.
If you create a script file that contains various commands and settings with the above contents, it will be as follows.
qs.bash
dc=$(which docker-compose) # docker-compose command with full path
if [[ -x "$dc" ]]; then
:
else
echo "Please install Docker before run this command."
exit 2
fi
rm="--rm" # To destroy a container
app="web" # describe $application service name from docker-compose.yml
db="db" # describe database service name from docker-compose.yml
app_name=$(pwd | awk -F "/" '{ print $NF }') # get project dir name
# define container name
app_container="${app_name}_${app}_1"
db_container="${app_name}_${db}_1"
echoing() {
echo "========================================================"
echo "$1"
echo "========================================================"
}
rm_pids() {
if [ -f "tmp/pids/server.pid" ]; then
rm -f tmp/pids/server.pid
fi
}
create_project() {
echoing "Exec Bundle Install for executing rails new command"
compose_build $app
bundle_cmd install
echoing "Exec rails new with postgresql and webpack"
bundle_exec rails new . -f -d=postgresql $*
echoing "Update config/database.yml"
mv database.yml config/database.yml
echoing "Exec db create"
bundle_exec rails db:create
echoing "docker-compose up"
compose_up $app
echo "You can access to localhost:3000"
}
init_services() {
echoing "Building containers"
$dc down -v
$dc build --no-cache $app
bundle_cmd install
if [ "--webpack" == "$1" ]; then
run_yarn install
fi
rails_cmd db:migrate:reset
rails_cmd db:seed
rm_pids
$dc up $app
}
compose_up() {
echoing "Create and start containers $*"
rm_pids
$dc up -d "$1"
}
compose_down() {
echoing "Stop and remove containers $*"
$dc down $*
}
compose_build() {
echoing "Build containers $*"
$dc build $*
}
compose_start() {
echoing "Start services $*"
rm_pids
$dc start $*
}
compose_stop() {
echoing "Stop services $*"
$dc stop $*
}
compose_restart() {
echoing "Restart services $*"
$dc restart $*
}
compose_ps() {
echoing "Showing running containers"
$dc ps
}
logs() {
echoing "Logs $*"
$dc logs -f $1
}
invoke_bash() {
$dc run $rm -u root $1 bash
}
invoke_run() {
renv=""
if [ -n "$RAILS_ENV" ]; then
renv="-e RAILS_ENV=$RAILS_ENV "
fi
if [ -n "$TRUNCATE_LOGS" ]; then
renv="$renv -e TRUNCATE_LOGS=$TRUNCATE_LOGS "
fi
dbenv=""
if [ -n "$DISABLE_DATABASE_ENVIRONMENT_CHECK" ]; then
dbenv="-e DISABLE_DATABASE_ENVIRONMENT_CHECK=$DISABLE_DATABASE_ENVIRONMENT_CHECK "
fi
$dc run $rm ${renv}${dbenv}$*
}
run_app() {
invoke_run $app $*
}
run_db() {
invoke_run $db $*
}
run_spring() {
$dc exec spring $*
}
run_solargraph() {
invoke_run solargraph $*
}
rails_server() {
rm_pids
# $dc run $rm ${renv}--service-ports $app rails s -p 3000 -b 0.0.0.0
$dc run $rm --service-ports $app bundle exec foreman start -f Procfile.dev
}
rails_db() {
case "$1" in
set)
rails_cmd db:migrate
;;
up)
rails_cmd db:migrate:up VERSION="$2"
;;
down)
rails_cmd db:migrate:down VERSION="$2"
;;
reset)
rails_cmd db:reset
;;
*)
rails_cmd db:migrate:status
;;
esac
}
spring_db() {
case "$1" in
set)
spring_cmd rake db:migrate
;;
up)
spring_cmd rake db:migrate:up VERSION="$2"
;;
down)
spring_cmd rake db:migrate:down VERSION="$2"
;;
reset)
spring_cmd rake db:reset
;;
*)
spring_cmd rake db:migrate:status
;;
esac
}
spring_dive() {
$dc exec spring bash
}
rails_cmd() {
bundle_exec rails $*
}
rake_cmd() {
bundle_exec rake $*
}
rspec_cmd() {
$dc start chrome
bundle_exec rspec $*
}
test_cmd() {
bundle_exec test $*
}
bundle_cmd() {
run_app bundle $*
}
bundle_exec() {
run_app bundle exec $*
}
rubocop_cmd() {
bundle_exec rubocop $*
}
rails_console() {
bundle_exec rails c $*
}
spring_cmd() {
run_spring spring $*
}
solargraph_cmd() {
run_solargraph solargraph $*
}
rake_reset_db() {
echoing "Running reset db"
compose_stop $app
DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rake_cmd "db:reset"
rake_cmd "db:fdw:setup"
RAILS_ENV=test rake_cmd "db:fdw:setup"
compose_up $app
}
db_console() {
# from config/database.yml
database="development"
username="postgres"
port="5432"
run_db psql -h $db_container -p $port -U $username $database
}
db_dump() {
# from config/database.yml
database="development"
username="postgres"
port="5432"
tm=$(date +\%Y\%m\%d-\%H\%M)
dump_file=tmp/dbdump-${dbname}-${tm}.dump
echoing "Dump database $dbname data to $dump_file"
run_db pg_dump -h $db_container -p $port -U $username --disable-triggers $database >$dump_file
echo "done"
}
run_yarn() {
run_app bin/yarn $*
}
run_npm() {
run_app npm $*
}
run_webpack() {
run_app webpack $*
}
cmd=$1
shift
case "$cmd" in
setup)
create_project $* && exit 0
;;
init)
init_services $* && exit 0
;;
ps)
compose_ps && exit 0
;;
up)
compose_up $* && compose_ps && exit 0
;;
build)
compose_build $* && exit 0
;;
start)
compose_start $* && exit 0
;;
stop)
compose_stop $* && exit 0
;;
restart)
compose_restart $* && exit 0
;;
down)
compose_down $* && exit 0
;;
logs)
logs $*
;;
bash)
invoke_bash $*
;;
run)
invoke_run $*
;;
server)
rails_server $*
;;
rails)
rails_cmd $*
;;
db)
rails_db $*
;;
cons)
rails_console $*
;;
rake)
rake_cmd $*
;;
rspec)
rspec_cmd $*
;;
test)
test_cmd $*
;;
bundle)
bundle_cmd $*
;;
rubocop)
rubocop_cmd $*
;;
reset-db)
rake_reset_db
;;
psql)
db_console $*
;;
db-dump)
db_dump $*
;;
yarn)
run_yarn $*
;;
npm)
run_npm $*
;;
webpack)
run_webpack $*
;;
spring)
spring_cmd $*
;;
sdb)
spring_db $*
;;
sdive)
spring_dive $*
;;
solargraph)
solargraph_cmd $*
;;
*)
read -d '' help <<-EOF
Usage: $0 command
Service:
setup Create new rails application
init Initialize backend services then run
ps Show status of services
up Create service containers and start backend services
down Stop backend services and remove service containers
start Start services
stop Stop services
logs [options] default: none. View output from containers
bash [service] invoke bash
run [service] [command] run command in given container
App:
server Run rails server
rails [args] Run rails command in application container
rake [args] Run rake command in application container
db [args] Run rails db command you can use set(migrate), up, down, reset, other is status
ex: ./qs db set #running rails db:migrate
./qs db up 2019010101 #running rails db:migrate:up VERSION=2019010101
rspec [args] Run rspec command in application container
test [args] Run Minitest command in application container
bundle [args] Run bundle command in application container
cons Run rails console
rubocop [args] Run rubocop
yarn Run yarn command in application container
npm Run npm command in application container
webpack Run webpack command in application container
Spring
spring Exec spring command in Spring container
sdive Into spring container
sdb [args] Run rails db command you can use set(migrate), up, down, reset, other is status
ex: ./qs db set #running rails db:migrate
./qs db up 2019010101 #running rails db:migrate:up VERSION=2019010101
Solargraph
solargraph Run solargraph command in Spring container
DB:
reset-db reset database in DB container
psql launch psql console in DB container
pg-dump dump database data as sql file in DB container
EOF
echo "$help"
exit 2
;;
esac
Although it is another setting file, the explanation is omitted because it is created by general construction. As a supplementary matter, PostgreSQL is selected as the DB. The reason is that MySQL may cause a validator error from Rails 6.0 and it is necessary to add settings. Regarding this point, if you use MySQL, you can set it, but Since PostgreSQL does not require any settings, this is used as the DB. Please refer to the following site for details. What to do if you get a warning "Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1." in Rails 6.0
database.yml
default: &default
adapter: postgresql
encoding: utf8
min_messages: WARNING
host: db
port: 5432
username: postgres
password: postgres
pool: 5
timeout: 5000
stats_execution_limit: 10
development:
<<: *default
database: development
test:
<<: *default
database: test
production:
<<: *default
database: production
Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6.0'
.gitignore
.bash_history
.bundle
.solargraph
.atom
.vscode
.viminfo
Build a development environment for Rails 6 locally while using rbenv etc. with homebrew It seems that it did not take much man-hours, but building a development environment in a stable container is Even on the Docker official website, it was described in Rails 5, and it seemed difficult to build in Rails 6.
Also, on the official website Quick Start, the execution command is described in the Dockerfile, If you want to write with the smallest possible setup, it is better to separate it into a shell script It is considered good to include maintainability as a development environment.
Thank you for reading this article. I hope it helps in some development.
Finally, we would like to thank you for your cooperation and advice in compiling this article. Thank you very much.
Quickstart Compose and Rails Dockerfile best practices Bash script execution sample New Linux textbook SB Creative
Recommended Posts