はじめに
DockerでRailsとMysqlが載った環境を用意してその上で何かを作ろうと思います。
手始めとして、以下の事を行っていきたいと思います。
- Docker上でRailsとMySQLを動かす
キーワード
Rails, Docker, make, Mysql
目次
- 環境
- 宣言
- やる
- まとめ
- 参考
環境
- docker desktop: 20.10.22
でこいつらを動かせるようにしたい
- rails: 7.0.4
- ruby: 3.2
- mysql: 8.0.3
宣言
公式が出している情報のみ引用します(エラー時は別)
使ってみる
Dockerについては前に自分がメモしていた。見返してもあんまり役に立たないですw
https://qiita.com/kajiyai/items/3e55844b9b39cb177128
公式がdockerにrailsをセットアップする方法を出しているが、postgresql版なので適宜読み替えつつ、追っていきます。
https://github.com/docker/awesome-compose/tree/master/official-documentation-samples/rails/
Dockerfileの定義
Dockerfileは環境の依存関係などを定義するときに呼び出すファイルです。rubyのバージョンだけ変更しました。
# syntax=docker/dockerfile:1
FROM ruby:3.2
RUN apt-get update -qq && apt-get install -y nodejs mysql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]
FROM
,RUN
,WORKDIR
,COPY
等の命令が何をしているかはだいたいわかりますが、ENTRYPOINT
, EXPOSE
, CMD
等のコマンドが何をしているかよくわからないので調べました。
ENTRYPOINTについて
そもそもエントリーポイントの意味が分かってなかったです。
エントリーポイントとは、プログラムを実行するうえで、プログラムやサブルーチンの実行を開始する場所のこと。プログラム全体のエントリーポイントとなる場所を含むルーチンがメインルーチンである。
https://ja.wikipedia.org/wiki/エントリーポイント#:~:text=エントリーポイントとは、プログラム,がメインルーチンである。
一番初めに処理されるプログラムを指定しているという事ですね。
EXPOSEについて
トランスポート層の設定のドキュメントとして機能するみたいです。実際にポートを開けるにはdocker run
コマンドを叩こうとかいてあります。
プロトコルのデフォルトはTCPだけど、オプションでUDPも選べるよと書いてあります。
The
EXPOSE
instruction informs Docker that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified.The
EXPOSE
instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. To actually publish the port when running the container, use the-p
flag ondocker run
to publish and map one or more ports, or the-P
flag to publish all exposed ports and map them to high-order ports.
https://docs.docker.com/engine/reference/builder/#expose
CMDについて
どうやらCMDとENTRYPOINTは奥が深そうです。
ココでは、IPアドレスを明示してrails serverコマンドを実行したいのね、と理解しておきます。
$ rails server -b '0.0.0.0'
https://railsdoc.com/page/rails_server
Dockerfileのための準備色々
Gemfileの作成
rails new
を後のステップで実行するとすぐに更新されますが、vscodeを開き、Gemfileを一時的に作成します。
source 'https://rubygems.org'
gem 'rails', '~>7'
Gemfile.lockの作成
$ touch Gemfile.lock
docker-compose.ymlの作成
posgresql→mysqlに変更してます。
services:
db:
image: mysql:latest
ports:
- "13306:3306"
volumes:
- ./.data/db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
参考
https://hub.docker.com/_/mysql/
コンテナの実行
$ docker compose run --no-deps web rails new . --force --database=mysql
このコマンドを実行した所、次のようなエラーが生じた
ERROR [7/8] COPY entrypoint.sh /usr/bin/
failed to solve: failed to compute cache key: failed to calculate checksum of ref moby::****: "/entrypoint.sh": not found
entrypoint.shファイルをentorypoint.shと名付けていたゆえのエラーだった
再度エラーが
E: Package 'mysql-client' has no installation candidate
Dockerfileの3行目、mysql-clientをdefualt-mysql-clientに変更
RUN apt-get update -qq && apt-get install -y nodejs default-mysql-client
またまたエラーが
exec /usr/bin/entrypoint.sh: no such file or directory
そんなファイル無いよ
stackoverflowのスレ
https://stackoverflow.com/questions/38905135/why-wont-my-docker-entrypoint-sh-execute
改行コードが原因?
https://kakiblo.com/docker-windows/
試したこと
- entrypoint.shファイルの改行コードをLFに変更した
- entrypoint.shファイルの先頭行を#!bin/shに変更した
- Dockerfileの10,11行目の/usr/binを/usr/local/binに変更した
動いた
参考: https://www.baeldung.com/docker-cant-connect-local-mysql
こちらのコマンドで—no-deps
を指定しているのでコマンド実行後はファイルが作成されるだけ、が正しい挙動だと思われます
docker compose run はアドホックなタスクに使用するみたいです
$ docker compose run --no-deps web rails new . --force --database=mysql
なにはともあれGemfileが更新されたのでビルドします
$ docker compose build
rails仕様のディレクトリ構成が完成しました
DBを接続
何も変更せずにdocker compose up
したらエラー
Can't connect to local MySQL server through socket '/run/mysqld/mysqld.sock' (2)
ローカルのMySQLサーバーと繋げないよ~と言ってそう
database.ymlのhostをlocalhostからdbに変更してみた
またエラー。今度はユーザ名とPWが違うと言ってそう
ActiveRecord::DatabaseConnectionError
There is an issue connecting to your database with your username/password, username: root.
Please check your database configuration to ensure the username/password are valid.
docker desktopのterminalから mysql -u root -p
でも入れない
docker-compose.ymlファイルのdb:enfironment:にMYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORDを入力して、再ビルドしてみる
services:
db:
image: mysql:latest
ports:
- "13306:3306"
volumes:
- ./.data/db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: db
MYSQL_USER: user
MYSQL_PASSWORD: password
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
エラーが解決できないので質問を投げた。
https://qiita.com/kajiyai/questions/6bb978839a2b78c8ae03
Postgresqlに変更したらwelcomeページは動いた
まとめ
MySQLで動かそうとしましたが、動きませんでした
Postgresqlでは動きました
MySQLでなければならない理由はないのでPostgresqlで作っていこうかと思いますが、何が問題なのかはっきりせず、もやもやします。お詳しい方、コメントで教えて頂けると幸いです。
次は、以下の記事を元にmakeツールでdockerコマンドを整理してみたいと思います
https://beyondjapan.com/blog/2020/10/makefile-docker/
ではまた。