#はじめに
今回は、Docker環境を構築しようと思う。私自身、フロントエンドとバックエンドを一つのリポジトリに管理して、そこでDocker環境を構築した経験はないため、それなりの苦労を強いられた。今回は、私のように一つのリポジトリにフロントとバックを管理する環境下でDockerを導入することになった際に取る手順を紹介していきたいと思う。
皆さんの開発環境は、私のポートフォリオの環境とは異なる部分もあるだろうから、適宜調整しながら参考にしてもらえたら幸いである。
##環境
Redis 6.2
Ruby on Rails 6.1.3.1
Next.js
Docker 20.10.0-rc1
MySQL 8.0.23
追記:今回は、フロントとバックエンドを一つのディレクトリで管理しているので注意してもらいたい。
Github等で別々のリポジトリで管理している場合は、リポジトリを統一するか別々のリポジトリでやる方法を調べていただけたら幸いである。
階層構造
│
├ m-api(API側)
│ └ config
│ └ database.yml
│ └ Dockerfile
├ m-front(クライアント側)
│ └ Dockerfile
│
├ mysql-confd
│ └ default_authentication.cnf
├ docker-compose.yml
│
├ .env (環境変数を管理するファイル)
##1. database.ymlの設定
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV['DB_USERNAME'] %> #.envにDB_USERNAMEを記入
password: <%= ENV['DB_PASSWORD'] %> #.envにDB_PASSWORDを記入
+ host: db
- socket: /tmp/mysql.sock
development:
<<: *default
database: m_api_development
test:
<<: *default
database: m_api_test
production:
<<: *default
database: m_api_production
username: m_api
password: <%= ENV['M_API_DATABASE_PASSWORD'] %>
ここでは、hostを次に書くdocker-compose.yml
のdbのservice名に合わせる。
##2.docker-compose.ymlの作成
フロントエンドとバックエンドと同じ階層にdocker-compose.yml
を作成する。
version: '3'
services:
redis:
image: redis:6.2
command: ["redis-server"]
ports:
- "6379:6379"
volumes:
- "./data/redis:/data"
command: redis-server --appendonly yes ##MySQLとredis-serverの永続化
db:
image: mysql:8.0.23
container_name: api-container
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
environment:
MYSQL_ROOT_PASSWORD: $DB_PASSWORD
MYSQL_DATABASE: sample
MYSQL_PASSWORD: $DB_PASSWORD
ports:
- ${DB_PORT}:3306
volumes:
- ./mysql-confd:/etc/mysql/conf.d
api:
std_open: true #binding.irbでデバックする際に必要となる
tty: true #binding.irbでデバックする際に必要となる
depends_on:
- db
build:
context: ./m-api/ #m-apiの部分は自身の環境に合わせて変える
dockerfile: Dockerfile
ports:
- "3000:3000"
links:
- db
- redis
volumes:
- ./m-api:/app #m-apiの部分は自身の環境に合わせて変える
- bundle_path:/bundle #Gemの永続化
command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
environment:
REDIS_URL: redis://redis:6379
front:
build:
context: ./m-front/ #m-frontの部分は自身の環境に合わせて変える
dockerfile: Dockerfile
volumes:
- ./m-front/app:/usr/src/app #m-frontの部分は自身の環境に合わせて変える
command: 'yarn dev'
ports:
- "8080:8080"
volumes:
bundle_path: #Gemの永続化
mysql-data:
driver: local
今回、Redis-server、MySQL、Next.js、Rails(APIモード)を使うということで、上記のようにする。
私は、Firebase Authでredis-serverを使っているため、今回はRedisをdocker-compose.yml
に記載したが、そうではない場合は書かなくてよい。
なお、$DB_PASSWORD
とDB_PORT
は.env(docker-compose.ymlと同じ階層)で環境変数を設定してもらいたい。
また、Redis-serverを使う際に、
command: redis-server --appendonly yes
の1行がなければ、Railsのサーバーを再起動するたびにUserやPost等のデータが消えてしまうため、データの永続化ができなくなる。そのため、redisとMySQLを使う場合は必ずこの1行は入れること。
##3. mysql-confの作成
MySQLのvolumeを管理するため、docker-compose.yml
と同じ階層にmysql-confd
を作成し、その中にdefault_authentication.cnf
というファイルを作成する。
[mysqld]
default_authentication_plugin= mysql_native_password
##4. Dockerfileの作成(クライアント側、API側)
まずはクライアント側からm-front/Dockerfile
を作成する
FROM node:14-alpine
WORKDIR /usr/src/app
なお、1行目のnodeは Docker Hubからnodeのバージョンを選択するのが望ましい。
次に、API側でm-api/Dockerfile
を作成する
FROM ruby:2.7.3
ENV LANG=C.UTF-8 \
TZ=Asia/Tokyo
RUN apt-get update -qq && apt-get install -y nodejs default-mysql-client
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app
# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
ここも、Docker HubからRubyのバージョンを選択するのが望ましい。
##5.Dockerコマンドの実行
まずは、
$ docker-compose build
でDocker環境をビルドする。
次に、Docker環境の中にデータベースを作成するために、
$ docker-compose run api rails db:create
を実行する。
なお、ここでのapi
は、docker-compose.yml
内で指定したAPI側のservice名である。
適宜調整してコマンドを実行すること。
そして、databaseを作ることができたら、
$ docker-compose run api rails db:migrate
を実行して、マイグレーションを実行する。
これでローカルで作成したデータベースはDocker環境でも再現できたことになる。
そして、
$ docker-compose up -d
または
$ docker-compose up
を実行して、Dockerコンテナをupする。
http://localhost:3000/
にアクセスし、下記の画面が出てきたら成功である。
##おわりに
Dockerは一度作成するまでにかなりの時間を要するが、一度作ればずっと使える。そのため、エラーが出ても途中で折れずに進めることを推奨する。
また、今回の記事でどこか間違っている部分があれば指摘していただけると幸いである。