Open6

Docker Compose × Rails6 × Webpack 環境構築

rnittarnitta

バックエンド開発用のDockerfileを書きます。
iceplantはプロジェクト名なので各自よしなに

Ruby3のslimイメージを使います

# 開発用なのでslimで構築 よりスリムにしたければalpine等を使う
FROM ruby:3.0.0-slim
ENV LANG ja_JP.UTF-8
# RUN コマンドを減らすとレイヤーが減ると噂で聞いたためつなげている。
# nanoやgitやgraphvizやimagemagickはプロジェクトによっては不要なので状況に合わせて消す。
RUN sed -i.bak -e "s;http://httpredir.debian.org/debian;http://ftp.jaist.ac.jp/pub/Linux/debian;g" /etc/apt/sources.list &&\
    apt-get update -qq &&\
    apt-get install -y build-essential libpq-dev nodejs vim-nox nano locales locales-all curl git graphviz imagemagick &&\
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - &&\
    apt-get clean &&\
    rm -rf /var/lib/apt/lists/* &&\
    ln -snf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && echo Asia/Tokyo > /etc/timezone

WORKDIR /iceplant
COPY Gemfile /iceplant/
# native extensionのソースやオブジェクトファイルは無駄にディスクを食うだけなので消してしまう。
# わざわざ消す必要もあまりない。
RUN bundle install -j4 --retry 3 &&\
    rm -rf /usr/local/bundle/cache/*.gem &&\
    find /usr/local/bundle/gems/ -name "*.c" -delete &&\
    find /usr/local/bundle/gems/ -name "*.o" -delete
ADD . /iceplant
rnittarnitta

フロントエンド用のDockerfileを書きます。

# Rails開発でnodeのバージョンはさして重要にならない(と私は思う)ので、ltsにしてしまう。
# フロントエンドのコンテナ内で作業することはあまりないのでalpineでいいきがする。
FROM node:lts-alpine
ENV LANG ja_JP.UTF-8
RUN apk --update add git curl tzdata bash vim openssl &&\
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata &&\
    rm -rf /var/cache/apk/*

WORKDIR /iceplant
# webpack.config.js とか package.jsonとかコピーするため。気になる方は一つずつコピーしていくといいのでは
COPY ./* /iceplant/
# /frontディレクトリにフロントエンドのスクリプト群を置いているため
COPY ./front/ /iceplant/front/
COPY ./webpack/ /iceplant/webpack/
RUN yarn
rnittarnitta

ちなみにディレクトリ構成はざっくりこんな漢字。

.
├── Gemfile
├── app
├── bin
├── config
├── data
├── db
├── docker
├── docker-compose.yml
├── front
├── package.json
├── public
├── tsconfig.json
├── tslint.json
├── webpack
├── webpack.config.js
└── yarn.lock
rnittarnitta

で、docker-compose.ymlをドカっとやって

version: '3'
services:
  db:
    image: mdillon/postgis:11-alpine
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust

  redis:
    image: redis:latest
    ports:
      - "6379:6379"
    volumes:
      - ./data/redis:/data

  web: &app_base
    build:
      context: .
      dockerfile: ./docker/backend/Dockerfile
    command: /bin/sh -c "rm -f ./tmp/pids/server.pid; bundle exec rails s"
    volumes:
      - .:/iceplant:cached
      - bundle:/usr/local/bundle:cached
      - node_modules:/iceplant/node_modules:cached
    ports:
      - "3000:3000"
    tty: true
    stdin_open: true
    environment:
      - PORT=3000
      - BINDING=0.0.0.0
      - EDITOR=vi
      - DATABASE_USER=postgres
      - DATABASE_PASSWORD
      - DATABASE_PORT=5432
      - DATABASE_HOST=db
      - REDIS_URL=redis://redis:6379/0
      - WEBPACK_DEV_SERVER_HOST=dev_server
      - WEBPACK_DEV_SERVER_PORT=3035
    depends_on:
      - db
      - redis

  dev_server:
    build:
      context: .
      dockerfile: ./docker/frontend/Dockerfile
    tty: true
    volumes:
      - .:/iceplant
      - node_modules:/iceplant/node_modules:cached
    ports:
      - "3035:3035"
    command: bash -c "yarn && yarn webpack-dev-server"

  worker:
    <<: *app_base
    command: bundle exec sidekiq -C config/sidekiq.yml
    ports: []
    environment:
      - DATABASE_USER=postgres
      - DATABASE_PASSWORD
      - DATABASE_PORT=5432
      - DATABASE_HOST=db
      - ENABLE_BOOTSNAP=false

volumes:
  db_data:
    driver: local
  bundle:
    driver: local
  node_modules:
    driver: local

postgis使わない場合はdbのサービスはこんな感じで

  db:
    image: postgres
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust

rnittarnitta

database.ymlなんか書いちゃって

Postgis

default: &default
  adapter: postgis
  encoding: unicode
  schema_search_path: public
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= (ENV.fetch("RAILS_MAX_THREADS") { 5 }).to_i + 1 %>
  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  port: <%= ENV['DATABASE_PORT'] %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default
  database: iceplant_development

PostgreSQL

default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= (ENV.fetch("RAILS_MAX_THREADS") { 5 }).to_i + 1 %>
  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  port: <%= ENV['DATABASE_PORT'] %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default
  database: iceplant_development
rnittarnitta

あとはwebpack.config.jsをイイカンジにすればおしまい