📑

【Nuxt x Rails】サンプルTODOアプリ - Docker編

2022/04/12に公開

今回検証目的でフロントに Nuxt、バックエンドに Rails、インフラに AWS を使って以下のような TODO アプリを作りました。
image
この記事では Docker に関する解説を行います 🙋‍♂️

  • 以下の記事で全体の解説を行っています。

https://zenn.dev/tokku5552/articles/nuxt-rails-sample

  • 全ソースコードはこちら

https://github.com/tokku5552/nuxt-rails-sample

環境

  • ローカル(docker)
# docker -v
Docker version 20.10.12, build e91ed57
  • インフラ構成図

image

全体像

image
コンテナとしては 3 環境立ち上げるようにしていて、それぞれwebappdbというサービス名となっています。
先にdocker-compose.ymlの解説をしておきます。

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
    volumes:
      - ./tmp/db:/var/lib/mysql
  app:
    build: docker/app
    tty: true
    volumes:
      - ./api:/api
      - ~/.ssh:/root/.ssh
    ports:
      - "8000:8000"
    depends_on:
      - db
    environment:
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
      AWS_DEFAULT_REGION: ap-northeast-1
  web:
    build: docker/web
    ports:
      - "3000:3000"
    volumes:
      - ./front:/var/www/html
    tty: true

web と app は Dockerefile から立ち上げるようにしていますが、db は mysql のイメージをそのまま使っています。
ローカル環境ということもあり、パスワードなどはベタ書きしています。

特筆すべきことはあまりないですが、appは docker の中から capistrano を使ってデプロイを行いたかったので、AWSCLI の設定を行っています。
また、ssh の設定をローカルの Mac のものと共有させるために~/.ssh:/root/.sshというようにそのままマウントしています。

app

Ruby を Docker で立ち上げています。
本番環境は puma と nginx を使っていますが、ここでは単純にrails sで立ち上げるのみとしています。
起動前にいかの環境変数を定義しておく必要があります。

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
  • Dockerfile
docker/app/Dockerfile
FROM ruby:2.6.6
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    default-mysql-client \
    nodejs \
    sudo \
    vim

RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
    unzip awscliv2.zip && \
    sudo ./aws/install

RUN curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb" && \
    sudo dpkg -i session-manager-plugin.deb

RUN mkdir /api
WORKDIR /api
COPY Gemfile /api/
COPY Gemfile.lock /api/
RUN bundle install

ruby のイメージは suffix をつけない場合 debian になるようです。
bash and apt が使えます。
参考:Ruby - Official Image | Docker Hub

  • 起動用の Gemfile
    bundle install を行うために、Gemfile が必要だったのでdocker/app/Gemfiledocker/app/Gemfile.lockを配置しています。
    .lock の方は空ファイルですが、Gemfileは rails のみ記載しています。
docker/app/Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6.1.4'

web

Nuxt を動かすためのコンテナです。
yarn devで動かすため、ただnodeを入れているだけです。

docker/web/Dockerfile
FROM node:16-alpine3.14

WORKDIR /var/www/html

RUN apk update && \
    npm install -g npm

EXPOSE 3000
ENV HOST 0.0.0.0

alpine ベースの軽量なものを使っているので bash が使えません

起動方法(Makefileによる短縮コマンド)

この技最近良く使うのですが、Makefileをコンパイル用ではなく、単なる短縮コマンドの定義用に使用しています。
例えば

make up
make bash

とかでappコンテナに入れますし、起動したいときは

make up
make web
make app

と打てば環境が起動します。(make webmake appは別ターミナルで実行)

Makefile
up:
	docker compose up -d
build:
	docker compose build --no-cache --force-rm
remake:
	@make destroy
	@make up
stop:
	docker compose stop
down:
	docker compose down --remove-orphans
restart:
	@make down
	@make up
destroy:
	docker compose down --rmi all --volumes --remove-orphans
destroy-volumes:
	docker compose down --volumes --remove-orphans
ps:
	docker compose ps
logs:
	docker compose logs
log-app:
	docker compose logs app
log-app-watch:
	docker compose logs --follow app
ash:
	docker compose exec web ash
bash:
	docker compose exec app bash
web:
	docker compose exec web yarn dev
app:
	docker compose exec app bundle install
	docker compose exec app bundle exec rails s -p 8000 -b '0.0.0.0'
db:
	docker compose exec db mysql -h localhost -ppassword

もちろんMakefileを使わなくても、上記のコマンドをそのまま打てば全く同じことができます。
私は上からlogsくらいまでは固定で使いまわしています。

まとめ

割と簡易的な説明になりましたが、このファイル類を置いとくだけで環境構築できるのはありがたいですね。
appwebからでなくてもcurlコマンドなどで直接実行することもできるので、かなり便利です。

Discussion