ð³ DockerãçšããRailsãšMySQLéçºç°å¢æ§ç¯ã¬ã€ã
ã¯ããã«
ããã«ã¡ã¯ãTakeã§ããéœå ã®èªç€ŸéçºäŒæ¥ã§ãšã³ãžãã¢ãšããŠåããŠããŸãã
ä»åããããš
docker
, docker compose
ãçšããŠä»¥äžã®ç°å¢ãäœæããŸãã
ruby 3.3.3
rails 7.1.3.4
mysql 8.4.0
èŠä»¶
-
rails
ãšmysql
ã¯ã³ã³ãããåããããš - 以äžã®
gem
ãdevelopment
ããã³test
ç°å¢ã§ã®ã¿äœ¿çšã§ããããå°å ¥ããããš
pry-rails
factory_bot
rubocop
-
minitest
ã䜿çšããããrspec
ã¯äžèŠ -
make
ã³ãã³ãã®äœæããŠä»¥äžãå®è¡ã§ããããã«ãããã-
Docker
ç°å¢ã§Rubocop
ãå®è¡ - ãã¹ãã®å®è¡
-
åäœç¢ºèª
-
docker compose up
ã§ä»¥äžã®ã³ã³ãããèµ·åãã
rails
mysql
-
binding.pry
ãåäœãã -
factory_bot
ãåäœãã -
rubocop
ãåäœãã- ã³ã³ããã®äžã§
rubocop
ãåäœããããã«make
ã³ãã³ããäœæããŠãã
- ã³ã³ããã®äžã§
git init
ãã First Commit
ãŸã§
ãã¡ããåèã«
Dockerfile
ã®äœæ
以äžã®ãªã³ã¯ãåèã«å¿ èŠãªãã¡ã€ã«ãäœæããŸãã
以äžã®ãã¡ã€ã«ãäœæããŸããïŒDockerã§RailsãåããããïŒ
Dockerfile
docker-compose.yml
Gemfile
Gemfile.lock
entrypoint.sh
touch Dockerfile docker-compose.yml Gemfile Gemfile.lock entrypoint.sh
Dockerfile
ã®å
容
FROM ruby:3.3.3
ARG RUBYGEMS_VERSION=3.3.3
# äœæ¥ãã£ã¬ã¯ããªãæå®
WORKDIR /app
# ãã¹ãã®GemfileãšGemfile.lockãã³ã³ããã«ã³ããŒ
COPY Gemfile Gemfile.lock /app/
# bundle installãå®è¡
RUN bundle install
# ãã¹ãã®ãã¡ã€ã«ãã³ã³ããå
ã®äœæ¥ãã£ã¬ã¯ããªã«ã³ããŒ
COPY . /app
# entrypoint.shãã³ã³ããå
ã®äœæ¥ãã£ã¬ã¯ããªã«ã³ããŒ
COPY entrypoint.sh /app
# entrypoint.shãå®è¡å¯èœã«ãã
RUN chmod u+x entrypoint.sh
# ã³ã³ããèµ·åæã«entrypoint.shãå®è¡
ENTRYPOINT ["/app/entrypoint.sh"]
# ã³ã³ããèµ·åæã«rails serverãå®è¡
CMD ["rails", "server", "-b", "0.0.0.0"]
Ruby 3.3.3ãããŒã¹ã«ããã³ã³ãããäœæããRailsã¢ããªã±ãŒã·ã§ã³ãå®è¡ããããã®ãã®ã§ãã
äŸåé¢ä¿ãã€ã³ã¹ããŒã«ããã¢ããªã±ãŒã·ã§ã³ã³ãŒããšãšã³ããªãŒãã€ã³ãã¹ã¯ãªãããã³ã³ããã«ã³ããŒããŸããèµ·åæã«ãšã³ããªãŒãã€ã³ãã¹ã¯ãªãããå®è¡ããRailsãµãŒããŒãèµ·åããèšå®ãå«ãŸããŠããŸãã
docker-compose.yml
ã®å
容
version: "3.9"
services:
db:
image: mysql:8.4.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: database
MYSQL_USER: user
MYSQL_PASSWORD: password
volumes:
- mysql_volume:/var/lib/mysql
ports:
- "3307:3306"
command: --default-authentication-plugin=mysql_native_password
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/app
ports:
- "3000:3000"
stdin_open: true
tty: true
depends_on:
- db
volumes:
mysql_volume:
database.yml
ã®å
容
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: db
development:
<<: *default
database: app_development
test:
<<: *default
database: app_test
production:
<<: *default
database: app_production
username: app
password: <%= ENV["APP_DATABASE_PASSWORD"] %>
ãã®èšå®ãã¡ã€ã«ã§ã¯ãdbãµãŒãã¹ãšããŠMySQLã³ã³ããã®èµ·åèšå®ãè¡ããwebãµãŒãã¹ãšããŠRailsã¢ããªã±ãŒã·ã§ã³ã®èµ·åèšå®ãè¡ã£ãŠããŸããdbãšããååã§èšå®ãããMySQLã³ã³ããã«ãRailsã¢ããªã±ãŒã·ã§ã³ããã¢ã¯ã»ã¹ã§ããããã«ããŠããŸãã
Gemfile
ã®å
容
source 'https://rubygems.org'
gem 'rails', '~> 7.1.3.4'
Railsã¢ããªã±ãŒã·ã§ã³ã®äŸåé¢ä¿ã管çããŸããå
·äœçã«ã¯ãRubyGemsã®ãœãŒã¹ããRails 7.1.3.4
ãå«ã7ç³»ã®ããŒãžã§ã³ã䜿çšããããšãæå®ããŠããŸãã
entrypoint.sh
ã®å
容
#!/bin/ash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
RailsãµãŒããŒãæ¢ã«ååšããå Žåã«å€ãPIDãã¡ã€ã«ãåé€ãããã®åŸã«Dockerfileã§æå®ãããã¡ã€ã³ããã»ã¹ãå®è¡ããŸããã¹ã¯ãªããã¯ãšã©ãŒãçºçãããšçµäºããããã«èšå®ãããŠããŸãã
Railsãããžã§ã¯ãã®äœæã³ãã³ã
docker compose run web rails new . --force --no-deps --database=mysql
-
--force
: æ¢åã®ãã¡ã€ã«ãäžæžãããŸã -
--no-deps
: ãµãŒãã¹ã®äŸåé¢ä¿ãèµ·åããã«ã³ãã³ããå®è¡ããŸã -
--database=mysql
: MySQLããŒã¿ããŒã¹ã䜿çšããŸã
Railsã¢ããªã±ãŒã·ã§ã³å ã§ããŒã¿ããŒã¹ãäœæ
docker compose run --rm web rails db:create
MySQLãäœæãããŸã
$ docker compose run --rm web rails db:create
[+] Creating 1/0
â Container auto-registration-db-1 Running 0.0s
Created database 'app_development'
Created database 'app_test'
ãµãŒããŒãèµ·å
docker compose run --rm web rails s
æåð
gem
ãdevelopment
, test
ç°å¢ã§ã®ã¿äœ¿çšã§ããç¶æ
ã«ãã
group :development, :test do
gem 'pry-rails'
gem 'pry-byebug'
gem 'factory_bot_rails'
gem 'rubocop', require: false
gem 'rubocop-rails', require: false
gem 'rubocop-performance', require: false
end
äž»ã«ä»¥äžã®gemãè¿œå
- pry-rails
- factory_bot
- rubocop
- minitestã䜿çšããããrspecã¯äžèŠ
require: false
ãä»ããçç±ã¯ããããã®gemãèªåã§èªã¿èŸŒãŸããªãããã«ããããã§ããããã«ãããã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«äœ¿çšãããã¡ã¢ãªéãæžãããèµ·åé床ãåäžãããããšãã§ããŸãã
You may pass an array with multiple files or true if the file you want required has the same name as gem or false to prevent any file from being autorequired.
ãããŠã以äžã®ã³ãã³ããå®è¡ããŠGemfileã«èšèŒã®gemãããŠã³ããŒãããŸãã
docker compose run web bundle install
Makefileã®äœæ
èŠä»¶
4.make
ã³ãã³ãã®äœæ
Docker
ç°å¢ã§Rubocop
ãå®è¡ã§ããããã«ãããã- ããã«ããã¹ããå®è¡ã§ããããã«ããŠããã ãããšå°è¯ã
Makefileèªçåã®èæ¯
1980幎代ããCPUã®ããŒããŠã§ã¢ããœãããŠã§ã¢ãæ¥éã«çºå±ããããšã«ããã倧èŠæš¡ãªããã°ã©ã ãå¢å ããŸããã倧èŠæš¡ããã°ã©ã ã«ã¯ãå€ãã®ãœãŒã¹ãã¡ã€ã«ãããããã¡ã€ã«ãå«ãŸããŠãããè€éãªäŸåé¢ä¿ãååšããŸãã
ãããã¡ã€ã«ãä¿®æ£ã»å€æŽããéããã®å€æŽã«äŸåããå šãŠã®ãã¡ã€ã«ãåã³ã³ãã€ã«ããå¿ èŠããããããæåã§ã®ç®¡çãå°é£ãã€ã³ã³ãã€ã«ã«æéãããã課é¡ããããŸããã
Makefileèªç
Stuart Feldmanã«ãã£ãŠMakeãäœæãããŸãããMakeã¯ãããã°ã©ã ã®ãã«ãããã»ã¹(ããã°ã©ã ã®ãœãŒã¹ã³ãŒããCPUãå®è¡ã§ãã圢ã«å€æŽããäœæ¥)ãèªååããããã®ããŒã«ã§ããã®å ·äœçãªèšå®å 容ãèšèŒãããã®ãMakefileã§ãã
å ·äœçãªèšå®å 容ãšããŠã¯ããã¡ã€ã«å士ã®äŸåé¢ä¿ãã³ãã³ãããããŸããMakeã¯ããã®Makefileãèªã¿èŸŒã¿ãå¿ èŠãªãã¡ã€ã«ã ããåã³ã³ãã€ã«ããããšã§å¹ççãªãã«ãããã»ã¹ãå®çŸããŸããã
â»ãã«ãããã»ã¹ãšã³ã³ãã€ã«ã®éãã¯ãã¡ã
Makefileã®ã¡ãªãã
- å¹ççãªã³ã³ãã€ã«ïŒå€æŽããããã¡ã€ã«ã ããåã³ã³ãã€ã«ãããããã³ã³ãã€ã«ã«èŠããæéãåæžã
- äŸåé¢ä¿ã®ç®¡çïŒMakefileã«äŸåé¢ä¿ãèšè¿°ããããšã§ç®¡çã
- ãã«ãããã»ã¹ã®èªååïŒæåã®æäœãæžããããšã§ããã¥ãŒãã³ãšã©ãŒãæžå°ã
Makefileã®äžèº«ã«ã€ããŠ
# Dockerã®èšå®ãã¡ã€ã«
DOCKER_COMPOSE = docker compose
DOCKER_RUN = $(DOCKER_COMPOSE) run --rm
# ããã©ã«ãã§å®è¡ããããµãŒãã¹å
SERVICE = web
# Railsã³ãã³ã
RAILS = $(DOCKER_RUN) $(SERVICE) bundle exec rails
# Rubocopã³ãã³ã
RUBOCOP = $(DOCKER_RUN) $(SERVICE) bundle exec rubocop
# Docker
.PHONY: build up stop restart down-volumes logs clean
build:
$(DOCKER_COMPOSE) build --no-cache
up:
$(DOCKER_COMPOSE) up -d
restart:
$(DOCKER_COMPOSE) restart
down:
$(DOCKER_COMPOSE) down
down-volumes:
$(DOCKER_COMPOSE) down -v
logs:
$(DOCKER_COMPOSE) logs -f
# Rails
.PHONY: setup db-create db-drop db-migrate reset seed console annotate routes shell test
create:
$(RAILS) db:create
drop:
$(RAILS) db:drop
migrate:
$(RAILS) db:migrate
reset:
$(RAILS) db:reset
seed:
$(RAILS) db:seed
console:
$(RAILS) console
annotate:
$(RAILS) annotate
routes:
$(RAILS) routes
shell:
$(DOCKER_RUN) $(SERVICE) bash
test:
$(RAILS) test
# Rubocop
.PHONY: rubocop rubocop-auto-correct rubocop-auto-unsafe
rubocop:
$(RUBOCOP)
rubocop-auto-correct:
$(RUBOCOP) -a
rubocop-auto-correct-unsafe:
$(RUBOCOP) -A
# Bundle
.PHONY: bundle-install update
bundle-install:
$(DOCKER_RUN) $(SERVICE) bundle install
bundle-update:
$(DOCKER_RUN) $(SERVICE) bundle update
# Assets
.PHONY: assets-precompile
assets-precompile:
$(DOCKER_RUN) $(SERVICE) bundle exec rails assets:precompile
# key
.PHONY: key
key:
$(DOCKER_RUN) --rm -e EDITOR=vim $(SERVICE) bundle exec rails credentials:edit
äœæ¥äžã«çºçãããšã©ãŒé
docker-compose: command not found
bash: docker-compose: command not found
docker-compose ãããŠã³ããŒãããŠã€ã³ã¹ããŒã«ããå¿ èŠãããããã
sudo apt-get install docker-compose
ãã¡
source ~/.zshrc
äžèšãå®è¡åŸã«å床以äžãå®è¡ããããã¡
sudo apt-get install docker-compose
åãæ¿ããŠä»¥äžãå®è¡
docker compose up -d
ãšã©ãŒçºç
Error response from daemon: driver failed programming
external connectivity on endpoint registration-db-1 (urytp95eiypw48tupryjo86uwqa5o8uypt9r9d2b4730141681bfas4aw4rhj53):
Bind for 0.0.0.0:3306 failed: port is already allocated
以äžã®ãšã©ãŒã¡ãã»ãŒãžã«çç®
Error response from daemon:driver failed programming
external connectivity ã. failed: port is already allocated.
Error response from daemon:
failed to create task for container: failed to create shim task:
OCI runtime create failed: runc create failed:
unable to start container process: exec: "entrypoint.sh":
executable file not found in $PATH: unknown
èŠããã«ãentrypoint.sh
ãé©åœã«äœçœ®ããŠãã ãããšèšãããïŒPathåãéãïŒ
# ã³ã³ããèµ·åæã«entrypoint.shãå®è¡
- ENTRYPOINT ["/entrypoint.sh"]
+ ENTRYPOINT ["/app/entrypoint.sh"]
docker compose up
å®è¡æã®ãšã©ãŒã¡ãã»ãŒãž
â»äžéšæç²
[ERROR] [MY-013909] [Server] A message intended for a client
cannot be sent there as no client-session is attached.
Therefore, we're sending the information to the error-log instead:
MY-001146 - Table 'mysql.component' doesn't exist
ã¯ã©ã€ã¢ã³ãã«é¢ããã¡ãã»ãŒãžããã¯ã©ã€ã¢ã³ãã®ã»ãã·ã§ã³ãæ¥ç¶ããŠããªãããéä¿¡ã§ããŸããã
ãã®ããããã®æ
å ±ããšã©ãŒãã°ã«éä¿¡ããŸããmysql component
ããŒãã«ãååšããªããšã
äžåºŠããªã¥ãŒã ãåé€ããŠã¿ã
docker compose down -v
docker compose up
æ£åžžã«èµ·åð
[ERROR] [MY-0100343] [Server] unknown variable 'default-authentication-plugin=mysql_native_password'.
default-authentication-plugin=mysql_native_password
ãšããäžæãªå€æ°ããããŸãã
Important Change: The deprecated mysql_native_password authentication plugin is now disabled by default. It can be enabled by starting MySQL with the new --mysql-native-password=ON server option, or by adding mysql_native_password=ON to the [mysqld] section of your MySQL configuration file.
MySQL8.4.0ã§ã¯ãmysql_native_password
ã®èªèšŒãã©ã°ã€ã³ãããã©ã«ãã§ç¡å¹ã«ãªã£ããããšã©ãŒãçºçã
MySQL5.7.0ãŸã§ã¯mysql_native_password
ã¯ããã©ã«ãã®èªèšŒãã©ã°ã€ã³ã§ããããŠãŒã¶ãŒãã¹ã¯ãŒãã®ããã·ã¥åã«SHA-1ã䜿çšãããŠããã
In MySQL 8.4, caching_sha2_password is the default authentication plugin rather than mysql_native_password (deprecated).
ãã®äžæ¹ã§ãMySQL8.0ããã¯æŽã«ã»ãã¥ã¢ãªSHA-256ã䜿çšãã caching_sha2_password èªèšŒãã©ã°ã€ã³ãè¿œå ãããããã©ã«ãã®èªèšŒãã©ã°ã€ã³ã caching_sha2_password
ã«å€æŽãããçµç·¯ãããã
ãã£ãŠã以äžã®ããã«docker-compose.yml
ãã¡ã€ã«ãä¿®æ£
ä¿®æ£å
version: "3.9"
ïŒçç¥ïŒ
volumes:
- mysql_volume:/var/lib/mysql
ports:
- "3307:3306"
ããããããããcommand: --default-authentication-plugin=mysql_native_password
ä¿®æ£åŸ
version: "3.9"
ïŒçç¥ïŒ
volumes:
- mysql_volume:/var/lib/mysql
ports:
- "3307:3306"
# åé€ïŒããã©ã«ãã§caching_sha2_passwordãèšå®ãããŠããããïŒ
çŸæ®µéã§ã¯æ¡çšããªãã£ããã®
ridgepole
Railsã«ãŠã¹ããŒã管çãè¡ã䟿å©ãªããŒã« ð ïž
ãã®èæ¯
1. ä»åã¯ããŒã 人æ°ãæ¯èŒçå°ãªããããð
ridgepoleã¯ã¹ããŒãå€æŽãäžæ¬ç®¡çããããããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã®ã³ã³ããªã¯ããèµ·ããã«ããã¡ãªããããããŸãããããããä»åã¯ããŒã 人æ°ãæ¯èŒçå°ãªãããããã®æ©æµã倧ãã掻ãããªãã®ã§ã¯ãªãããšèããŠãããŸãã
2. è¿œå ã§ã®èšå®ãèŠãããã
rails g model
ãå®è¡ããå Žåã«ãã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ãç¡å¹ã«ããèšå®ãªã©ãå¿
èŠãªããã
3. éçºéäžã§ãå°å ¥ã§ãããã
Railsæšæºã§ã¯ãªããšããããšããããŸãããridgepoleã¯å®¹æã«ãããžã§ã¯ãéäžããå°å ¥ã§ãããããéçºè ãå¢ãããªã©ã®çç±ãããã€ã°ã¬ãŒã·ã§ã³ãã¡ã€ã«ã®ç®¡çãé£ãããªã£ãŠããæã«å°å ¥ãåæ€èšããããŸãã
æåŸã«
ãããŸã§èªãã§ããã ãããããšãããããŸããïŒ
ä»åã®èšäºãè¯ãã£ããšæã£ãããã²ããããããæŒããŠããã ãããšå¬ããã§ã ð
noteã§ãèšäºãå·çããŠããŸãã®ã§ããã²ãã§ãã¯ããŠã¿ãŠãã ããã
ä»ã«ããã®ãããªããšã«ã€ããŠèšèŒããŠããã®ã§ãèªã¿ããã ããã°å¹žãã§ãã
æåŸãŸã§ãèªã¿ããã ããèª ã«ããããšãããããŸããïŒ
Discussion