Rails on Docker(alpine)でAPIコンテナをつくってみた


はじめに

RailsにはAPIモードが存在します。バックエンド側でRailsを使いたい場合に便利そう。
この記事のGoalは、Rails on DockerでAPIコンテナを構築することにします。DBはPostgreSQLを利用します。最後にcurlでちゃんとAPIとして使えるかテストもしておきます。

dockerdocker-composeは準備済みの前提です。

ゴール

  • Rails on Docker(APIモード)を構築する
  • curlでAPIが正常に動作するかテストする

目次

  1. Rails on Dockerの下準備
  2. rails newでAPIアプリの作成
  3. 【TEST】 CRUDをテストしてみる

1. Rails on Dockerの下準備

まずはDockerfileを作っていきます。「Quickstart: Compose and Rails | Docker Documentation」でも書かれているように

  • Dockerfile
  • docker-compose.yml
  • Gemfile
  • Gemfile.lock

あたりを用意します。これらのファイルは作成するアプリのルートディレクトリにおいときます。

Dockerfile
FROM ruby:2.6.3-alpine3.10

ENV RUNTIME_PACKAGES="linux-headers libxml2-dev make gcc libc-dev nodejs tzdata postgresql-dev postgresql" \
    DEV_PACKAGES="build-base curl-dev" \
    HOME="/app_name" \
    LANG=C.UTF-8 \
    TZ=Asia/Tokyo

WORKDIR $HOME

ADD Gemfile $HOME/Gemfile
ADD Gemfile.lock $HOME/Gemfile.lock

RUN apk update && \
    apk upgrade && \
    apk add --update --no-cache $RUNTIME_PACKAGES && \
    apk add --update --virtual build-dependencies --no-cache $DEV_PACKAGES && \
    bundle install -j4 && \
    apk del build-dependencies

ADD . $HOME

CMD ["rails", "server", "-b", "0.0.0.0"]

imageの軽量化をめざしてalpine使っちゃってます。

docker-compose.yml
version: "3"

services:
  db:
    container_name: app_name_db
    image: postgres:11.4-alpine

  app:
    container_name: app_name_app
    build: .
    volumes:
      - .:/app_name
    ports:
      - 3000:3000
    depends_on:
      - db

こちらもPostgreSQLをalpineで。

Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'

Gemfileはこんな感じで。
Gemfile.lockはファイルを作っておくだけ。

$ touch Gemfile.lock

2. rails newでAPIアプリの作成

$ docker-compose run app rails new . -f -d postgresql --api

ポイントは--apiの部分です。このオプションをつけることでapiアプリに不要なものが生成されなくなります。
あとはDB作成しておきます。

config/database.yml
#####
default: &default
  adapter: postgresql
  encoding: unicode
  host: db            # add
  username: postgres  # add
  password:           # add
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 
#####
$ docker-compose build
$ docker-compose run --rm app rails db:create
$ docker-compose up -d

http://localhost:3000にアクセスしていつものRails Hello Worldページが出たら成功です。

このページは表示されますが、APIモードでアプリを作っているので他のviewをつくるのは面倒です。scaffoldしてもviewができたりはしないです。

一旦コンテナ停止しときます。

$ docker-compose down

3. 【TEST】 CRUDをテストしてみる

テスト用に適当にモデルを作ってみます。nameをもつUserモデルにします。

$ docker-compose run --rm app rails generate scaffold user name:string
$ docker-compose run --rm app rails db:migrate
$ docker-compose up -d

3-1. Create

$ curl -X POST http://localhost:3000/users -d 'user[name]=test1'
{"id":1,"name":"test1","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"}

$ curl -X POST http://localhost:3000/users -d 'user[name]=test2'
{"id":2,"name":"test2","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"}

おー、ユーザーできた。

3-2. Read

$ curl -X GET http://localhost:3000/users
[{"id":1,"name":"test1","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"},{"id":2,"name":"test2","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"}]

$ curl -X GET http://localhost:3000/users/1
{"id":1,"name":"test1","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"}

indexの取得もshowの取得もできたぜ。ちなみにGETの場合は-X GETオプションはなくてもOK。

3-3. Update

$ curl -X PUT http://localhost:3000/users/1 -d 'user[name]=test3'
{"id":1,"name":"test3","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"}

id=1のユーザーのnametest1からtest3にアップデートされましたー。

3-4. Delete

$ curl -X DELETE http://localhost:3000/users/1

$ curl -X GET http://localhost:3000/users
{"id":2,"name":"test2","created_at":"YYYY-MM-DD","updated_at":"YYYY-MM-DD"}

id=1のユーザーが消えました!

Reference