はじめに
前回Vite+Dockerでフロントエンドの開発環境を作成しました。
【Vue3】Docker + Viteで Vue3 + TypeScriptの爆速開発環境を構築する【Mac】
今回はAPIサーバーをDocker環境に載せていきます。
本記事を読む前に
フロントエンドは前回作成した環境を使用します。
Rails + MySQL
のみの環境を作る際にも利用できるかと思います。
本記事では、各ツールやライブラリの説明は行いません。
あくまで環境構築を目的とした記事となっております。
Dockerfile
やdocker-compose.yml
の記法・使用するコマンドは事前に学習しておくと、スムーズに進めることが出来ると思います。
目次
事前準備/条件
- Macを使用していること
- Dockerを導入していること
Dockerをインストールしていない方はこちらからインストールしてください。
Windowsだと一部のコマンドが動作しない場合がありますので、あくまで参考程度にご覧いただければと思います。
構築手順
各種ファイルの作成
任意の作業ディレクトリを作成し、Dockerfile
を作成します。
※前回作成したフロントエンドの環境はfrontend
に移動します(cpコマンドかmvコマンドを使用してください)。
$ mkdir docker_vue3
$ cd docker_vue3
$ mkdir frontend
$ mkdir backend
$ mkdir db
$ cd backend
$ touch Dockerfile
$ touch Gemfile
$ touch Gemfile.lock
$ touch entrypoint.sh
# ベースとなるイメージ
FROM ruby:3.1.3 as base
WORKDIR /app
ENV NODE_MAJOR_VERSION 16
# 各種ライブラリをインストール
FROM base AS builder
RUN curl -sL https://deb.nodesource.com/setup_$NODE_MAJOR_VERSION.x | bash - && \
apt-get update -qq && \
apt-get install -y --no-install-recommends \
vim locales build-essential curl libpq-dev libmariadb-dev nodejs yarn nginx sudo default-mysql-client openssl
# bundle install
FROM builder as bundle
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
# 最終的に使用するイメージ
FROM bundle as main
COPY . .
# railsの起動設定
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
今回はマルチステージビルドを使用しdockerfileを作成します。
マルチステージビルドを使用し、レイヤーを追加していくことで、イメージサイズを小さくすることが出来ます。
Gemfileの作成
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '3.1.3'
gem 'rails', '~> 6.1.7'
dockerfile
で指定しているrubyバージョン3.1.3
と、rails
のバージョン指定をします。
今回は6.1.7
を使用します。
Gemfile.lockの作成
M1 Mac
の場合、Platformの指定をしなければいけません。
PLATFORMS
aarch64-linux
entrypoint.shの作成
こちらを参考にentrypoint.sh
の作成を行います。
#!/bin/bash
set -e
# Rails に対応したファイル server.pid が存在しているかもしれないので削除する。
rm -f /myapp/tmp/pids/server.pid
# コンテナーのプロセスを実行する。(Dockerfile 内の CMD に設定されているもの。)
exec "$@"
docker-compose.ymlの作成
続いてdocker-compose.ymlファイルを作成します。
docker-compose.ymlの前準備
前回作成したfrontend
の環境に関して以下対応します。
- フォルダ名変更→
frontend
-
Dockerfile
の配置先をfrontend/Dockerfile
に変更 -
docker-compose.yml
のport
を8000
に変更 -
vite.config.ts
のport
も8000
に変更します。
~~~省略~~~
server: {
host: true,
port: 8000,
},
docker-compose.ymlの作成
version: '3.9'
services:
frontend:
build:
# frontend配下に変更
context: ./frontend
dockerfile: Dockerfile
working_dir: /app
volumes:
- ./frontend:/app
ports:
- '8000:8000'
networks:
vite_rails_net:
ipv4_address: '172.28.0.3'
backend:
build:
context: ./backend
dockerfile: Dockerfile
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- './backend:/app'
environment:
TZ: UTC
# DBに設定したIPを指定
DB_HOST: 172.28.0.5
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
ports:
- '3000:3000'
networks:
vite_rails_net:
ipv4_address: '172.28.0.4'
# backendを起動する際はDBも起動する
depends_on:
- db
db:
platform: linux/x86_64
command: --default-authentication-plugin=mysql_native_password
image: mysql:8.0.28
volumes:
- './db/data:/var/lib/mysql'
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
ports:
- '3306:3306'
networks:
vite_rails_net:
ipv4_address: '172.28.0.5'
# ネットワーク作成
networks:
vite_rails_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.28.0.0/24
.envの作成
docker-compose.yml
内で$MYSQL_ROOT_PASSWORD
を設定していますが、こちらは.envに記載することで、環境変数を使用できます。
docker-compose.yml
と同階層に配置します。
$ touch .env
MySQLの環境変数に関してはこちらを参照してください。
MYSQL_ROOT_PASSWORD=hogehoge
dockerのイメージ作成
Dockerfile
とdocker-compose.yml
の作成が出来たらdockerのイメージをビルドします。
$ docker compose build
railsコマンドでプロジェクトの作成
bundle install
をdocker compose build
で完了しているので、rails
コマンドが使用できるようになりました。
rails
を使用してプロジェクトを作成します。
$ docker compose run backend rails new . --api --force --database=mysql
[+] Running 13/13
⠿ db Pulled 15.1s
⠿ 4be315f6562f Pull complete 3.0s
⠿ 96e2eb237a1b Pull complete 3.1s
~~~省略~~~
[+] Running 1/1
⠿ Container database Started 0.3s
exist
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
create .gitattributes
force Gemfile
~~~省略~~~
create app
create app/assets/config/manifest.js
create app/assets/stylesheets/application.css
create app/channels/application_cable/channel.rb
create app/channels/application_cable/connection.rb
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/javascript/channels/consumer.js
create app/javascript/channels/index.js
create app/javascript/packs/application.js
create app/jobs/application_job.rb
create app/mailers/application_mailer.rb
create app/models/application_record.rb
create app/views/layouts/application.html.erb
create app/views/layouts/mailer.html.erb
create app/views/layouts/mailer.text.erb
create app/assets/images
create app/assets/images/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
create bin
create bin/rails
~~~省略~~~
remove config/initializers/new_framework_defaults_6_1.rb
run bundle install
Fetching gem metadata from https://rubygems.org/...........
Resolving dependencies...
Using rake 13.0.6
Using zeitwerk 2.6.7
Using builder 3.2.4
~~~省略~~~
run bundle binstubs bundler
backend
はdocker-compose.yml
で指定したService名です。
各種ファイルが生成されたのでデータベースを作成していきます。
データベース接続設定
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: <%= ENV['DB_HOST'] %>
username: root
password: <%= ENV['MYSQL_ROOT_PASSWORD'] %>
development:
<<: *default
database: app_development
データベース作成
$ docker compose build backend
$ docker compose run backend rails db:create --trace
--trace
コマンドを付けておくと接続が出来なかった際のデバッグがしやすいです。
実行確認
docker compose up
でサーバー起動をします。
$ docker compose up
0.0.0.0:3000
かlocalhost:3000
にアクセスします。
無事接続できました。
フロントエンドからAPIを叩く
まずはaxios
をフロントエンドに導入します。
$ docker compose run frontend yarn add axios
続いて/api
でバックエンドにproxy
するように設定します。
~~~省略~~~
server: {
host: true,
port: 8000,
proxy: {
'^/api': {
// docker-compose.ymlに記載しているbackendのIPを指定
target: 'http://172.28.0.4:3000',
changeOrigin: true,
},
},
},
最後にApp.vue
がマウントされた際にAPI
を叩くようにApp.vue
を編集していきます。
ついでに、APIが返却値を画面に表示するようにします。
<script setup lang="ts">
~~~省略~~~
import { onMounted, ref } from 'vue'
import axios from 'axios'
const message = ref<string>('')
onMounted(async () => {
const res = await axios.get('api')
message.value = res.data.message
})
</script>
<template>
~~~省略~~~
<div>{{ message }}</div>
~~~省略~~~
</template>
APIの作成
controller
を作成します。
$ touch backend/app/controllers/api_controller.rb
class ApiController < ApplicationController
def index
render json: {message: 'Hello World'}, status: 200
end
end
続いてルーティングの設定を行います。
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
resources :api do
get '/', to: 'api#index'
end
end
localhost:8000
にアクセスします。
axios
からAPIが叩かれHello World
が返却されていることが確認できました。
以上が環境構築となります。
まとめ
今回はVue + Rails(MySQL)環境を作成していきました。
開発中に何度もビルドしますが、マルチステージビルドを使用することで、ビルドの時間を短くすることができます。