When you want to develop under Rails, Vue, Posgre environment using Docker, I had a hard time creating the environment for Rails and Vue, so save it as my own memo.
・ Rails 6 and Vue and Postgres Docker environment can be built ・ Rails and Vue can be linked ・ You can operate the instance and DB with Pry.
MacOS Mojave Ruby 2.6.4 Rails 6.0.3.3 Vue 2.6.12 Webpack 4.44.2 yarn 1.22.5 Docker 2.3.0.5 VScode
This is Docker-Start-Kit from my Github. Please use it if you like. Whiro0501/Docker_Rails6_Vue
Open terminal Create a directory with any name with mkdir Change to the directory created by cd Open VScode with code.
terminal
mkdir qiita
cd qiita
code .
VS code starts I'm working in a terminal on VScode If the terminal is not running, open the terminal with ⬆︎ + Control + @
Copy the files in the remote repository locally by entering the following command on the VScode terminal
VScode
git clone https://github.com/Whiro0501/Docker_Rails6_Vue.git
cd to Docker_Rails6_Vue / directory
VScode
cd Docker_Rails6_Vue/
Build the Docker image by executing the following command
VScode
docker-compose build
Get the required node module by doing the following
VScode
docker-compose run web yarn install --check-files
Create DB (Postgres) by executing the following
VScode
docker-compose run web rake db:create
Open another terminal Launch the Rails application by doing the following
VScode
#If another terminal is awkward, docker-compose up -d is fine
docker-compose up
Open yet another terminal Every time I update the View, it compiles and it takes time, so do the following:
VScode
docker-compose exec web ./bin/webpack-dev-server
Access the following with a web browser
Web browser
http://localhost:3000
Make sure the Rails application starts
Rails and Vue are not linked at the time of initial construction, so we will link them.
Create a home controller below (the controller name can be anything).
VScode
docker-compose exec web rails g controller home index
Created by index.html.erb
rb:index.html.erb
<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>
Add "root to:'home # index'" to the following files
routes.rb
Rails.application.routes.draw do
root to: 'home#index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
Access the following with a web browser
Web browser
http://localhost:3000
First of all, the contents described in index.html.erb are displayed
Now that the groundwork has been created on the Rails side, the next setting is to link with Vue. Initial settings for app.vue
app.vue
<template>
<div id="app">
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
data: function () {
return {
message: "Hello Vue!"
}
}
}
</script>
<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>
Initial setting of hello_vue.js
hello_vue.js
import Vue from 'vue'
import App from '../app.vue'
document.addEventListener('DOMContentLoaded', () => {
const app = new Vue({
render: h => h(App)
}).$mount()
document.body.appendChild(app.$el)
console.log(app)
})
app.vue is a single file component Passed as an object to hello_vue.js. Set it to be displayed in index.html.erb.
Set index.html.erb as follows
erb:index.html.erb
<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>
<%= javascript_pack_tag 'hello_vue.js' %>
<%= stylesheet_pack_tag 'hello_vue.js' %>
Access the following with a web browser
Web browser
http://localhost:3000
Linkage with Vue is complete !!
Whiro0501/Docker_Rails6_Vue First, I will explain from the state of Github of the above link To briefly explain, it will be the state after setting the following two Therefore, it is the theory that it is possible to prepare the environment where Rails 6, Vue and Postgres can be used.
VScode
docker-compose run web rails new . --force --database=postgresql --webpack=vue
In addition, in the above state, Postgres cannot work well with Rails, so set as follows. This is also based on the official document.
database.yml:database.yml
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
production:
<<: *default
database: myapp_production
username: myapp
password: <%= ENV['MYAPP_DATABASE_PASSWORD'] %>
Dockerfile
I referred to the best practices in the official documentation. Because Docker creates layers for each FROM, RUN, COPY It is said that RUN and COPY can be stored in as few layers as possible.
Dockerfile
FROM ruby:2.6
# `apt-get install yarn`Will result in an error
#Install the tools needed for your project
# &&Make one layer by connecting with and executing the command
#apt-get update and apt-get install is done on the same RUN(If you divide it, you cannot use the latest version)
#RUN creates image and then runs(CMD runs when container starts)
RUN 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 -qq && apt-get install -y nodejs postgresql-client vim && \
apt-get install -y yarn
#Creating a directory
RUN mkdir /myapp
#Specifying the working directory
#RUN , COPY,You don't have to worry about WORKDIR because only ADD instructions create layers.
#Absolute pass
WORKDIR /myapp
#Rebuild layers only when Gemfile is updated
#The reason why I don't copy the whole project first is to separate the layers
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
#Install library dependencies
RUN bundle install
#Copy the entire project(Gemfile/Gemfile.lock is not copied)
COPY . /myapp
#Added a script that is executed every time the container is started
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
#Specifying the public port number of the container
EXPOSE 3000
#If not specified, the process to be executed by default when the container is started
#Only one CMD instruction can be written in a Dockerfile
#CMD can be used as the default argument for the ENTRYPOINT instruction
CMD ["rails", "server", "-b", "0.0.0.0"]
docker-compose docker-compose.yml also referred to the official Docker documentation.
docker-compose.yml
version: '3'
services:
db:
#Use postgres for DB
image: postgres
#host's./tmp/with db/var/lib/postgresql/Synchronize data
volumes:
- ./tmp/db:/var/lib/postgresql/data
#Specifying environment variables
environment:
POSTGRES_PASSWORD: password
web:
build: .
#Server at container startup.Remove pid and run rails s
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
#The current directory of the host is the container/Synchronize with myapp
volumes:
- .:/myapp
#Port forwarding between host and container
ports:
- '3000:3000'
#Dependencies between services
depends_on:
- db
#Use Byebug in Docker environment
stdin_open: true
tty: true
Gemfile As for Gemfile, the one that is included by default is the main one. The added package is commented, so you can delete it if you don't need it.
Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.6.6'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6.0.3', '>= 6.0.3.3'
# Use postgresql as the database for Active Record
gem 'pg', '>= 0.18', '< 2.0'
# Use Puma as the app server
gem 'puma', '~> 4.1'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 4.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use Active Storage variant
# gem 'image_processing', '~> 1.2'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
#Introducing debug tools
gem 'pry-rails'
gem 'pry-byebug'
end
group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '~> 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
#Introducing auto-completion tools
gem 'solargraph'
#Introduction of static code analysis tool
gem 'rubocop'
gem 'rubocop-rails'
#Introduction of erb format tool
gem 'htmlbeautifier'
end
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of web drivers to run system tests with browsers
gem 'webdrivers'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
package.json I added package.json because I want to use vue-router and vuex. If you want to use a UI framework such as Vuetify, add it.
package.json:package.json
{
"name": "myapp",
"private": true,
"dependencies": {
"@rails/actioncable": "^6.0.0",
"@rails/activestorage": "^6.0.0",
"@rails/ujs": "^6.0.0",
"@rails/webpacker": "4.3.0",
"turbolinks": "^5.2.0",
"vue": "^2.6.12",
"vue-loader": "^15.9.3",
"vue-template-compiler": "^2.6.12",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"version": "0.1.0",
"devDependencies": {
"webpack-dev-server": "^3.11.0"
}
}
Open a terminal on VScode Run the following in the terminal
VScode
docker-compose exec web rails console
pry starts
VScode
[1] pry(main)>
create post controller
docker-compose exec web rails g controller post index
Modify post_controller.rb
post_controller.rb
class PostController < ApplicationController
def index
@post = Post.all
end
end
model post
VScode
docker-compose exec web rails g model post name:string age:integer
Reflect the model in DB
VScode
docker-compose exec web rails db:migrate
Rewrite index.html.erb as below
erb:index.html.erb
<%= @post.name %>
<%= @post.age %>
Modify routes.rb below
routes.rb
Rails.application.routes.draw do
root to: 'post#index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
Create an instance of Post model with pry
VScode
@post = Post.new
=> #<Post:0x00005589bc4beb78 id: nil, name: nil, age: nil, created_at: nil, updated_at: nil>
#I haven't put any data in name or age yet
#Not even saved in DB
Post.all
=> Post Load (2.2ms) SELECT "posts".* FROM "posts"
[]
#Save the instance in DB
@post.save
(0.7ms) BEGIN
Post Create (5.9ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2020-09-23 13:06:47.962085"], ["updated_at", "2020-09-23 13:06:47.962085"]]
(3.1ms) COMMIT
=> true
#Post again.If you do all and get the data from the DB, the saved instance will be called.
Post.all
=> Post Load (2.2ms) SELECT "posts".* FROM "posts"
[#<Post:0x00005589bceec5f0
id: 1,
name: nil,
age: nil,
created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00,
updated_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00>]
#@Try putting data in the post instance
@post.name = "Hiro"
=> "Hiro"
@post.age = "29"
=> "29"
#Save again
@post.save
Post Update (4.0ms) UPDATE "posts" SET "name" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["name", "Hiro"], ["updated_at", "2020-09-23 13:10:26.486888"], ["id", 1]]
Post Update (2.0ms) UPDATE "posts" SET "age" = $1, "updated_at" = $2 WHERE "posts"."id" = $3 [["age", 29], ["updated_at", "2020-09-23 13:10:56.785029"], ["id", 1]]
(1.0ms) COMMIT
=> true
#Data is stored
Post.all
=> Post Load (1.4ms) SELECT "posts".* FROM "posts"
[#<Post:0x00007f1ddc7a77a8
id: 1,
name: "Hiro",
age: 29,
created_at: Wed, 23 Sep 2020 13:06:47 UTC +00:00,
updated_at: Wed, 23 Sep 2020 13:10:56 UTC +00:00>]
Access the following with a web browser
Web browser
http://localhost:3000
OK if you can get the data from DB as below
Modify post_controller.rb
class PostController < ApplicationController
def index
binding.pry
@post = Post.all
end
end
Access the following with a web browser
Web browser
http://localhost:3000
Freezes on the screen below (correct behavior)
Return to pry terminal
pry(main)>
With the above, the environment for debugging with pry is ready.
I referred to the following site. Docker Document Japaneseization Project Quick Start: Compose and Rails Dockerfile Best Practices Basic mechanism of Webpacker Let's create a development environment for "Rails / PostgreSQL" using Docker!
Recommended Posts