Docker on Rails デモ ヤリマスヵ...

# はじめに
　　　　　　　　　　　　　　　　 )
　　　　　　　　　　　　　　 　 ( ＿
　　　　　　　　　　　　, - ﾆ￣　　￣ `　､
　　　　　　　　　　 ／ 　 　 　 　 　 　 　 ｀ヽ
　　　　　　　　, - '､　　　　　 -＝-　　-＝- ',_
　　　　　　 r´　　　ヽ. 　　 γ ￣ ヽ　γ￣ヽ ',ヽ.
　　　　　　{ 　　　　　ｉ＝＝{ ｌ　　　 ｌ.=ｌ l　　 .} |　i＿＿ 　Docker デモ ヤリマスヵ...
.　　　　　　i　　＜￣｀ヽ､　弋ゝ　_ノ　弋ゝ ノ　>´ , ィ´
　　　　　　弋__ ＿＞ ､　ヽ､　￣　 　 　 ￣　/ ／ヽ
　　　　　　　　 |　　　　 ｀ ｰ`　　　　　　　　　　　　 }
　　　　　　　　 ゝ､　　　　　　　　　　　　　　　　　 /
　　　　　　　　　　 ｀ｰ -､ - ＿＿＿＿＿＿ ,　ィ´
　　　　　　　　　　 /　 　 ｌ　/ 　 |>く| ＼ ﾊ
　　 　 　 　 　 　 /＿ 　 .ｌ　＞　.|:H:|　く l ﾊ
　 　 　 　 　 　, ‐´ 　｀ヽ､ｌ /　　.l:l l:l　　ｌ.ｌ-‐'ｰ､
　　　　 　　 γ　　　 　　 ヽ.',　　l:l l:l　　ｌ ｌ　　　 ヽ
　　　　 　 　 {　　　　　　 　}. ',　 l:l l:l 　.l　ｌ　 　 　 }
　　　 　 　 　 ', 　 　 　 　 /　 ',　l:l l:l　 ｌ　 ｌ　　　 /

# やりたいこと
- Postgresql と Redis がつながる Rails を Docker の上でつくりたい
  - Docker
     - できるだけ軽く、速く、安全なコンテナを作る
     - Ubuntu で Docker を使うと権限関連がひどいことになるので、それを防ぎたい
  - PostgreSQL
     - Rails でマスタとレプリカを使いたいので、コンテナは２台は必要
  - Redis
     - Rails でキャッシュと Sidekiq 用に２台ほしい
  - Ruby on Rails
     - 快適な Rails 開発環境を手に入れたい

# 開発環境について
```bash
$ uname -a
Linux def 5.4.0-29-generic #33-Ubuntu SMP Wed Apr 29 14:32:27 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ docker -v
Docker version 19.03.8, build afacb8b7f0
$ docker-compose -v
docker-compose version 1.25.0, build unknown
```

# コード
[Github のレポジトリ](https://github.com/seahal/qiita) にあります。
### まずは Ruby の Dockerfile をつくろう
```dockerfile
FROM node:14.1.0-alpine3.11 as node

FROM ruby:2.7.1-alpine3.11 as ruby

ENV LANG=C.UTF-8
ENV RAILS_ENV=development
ENV RACK_ENV=development
ENV USER_NAME=un
ENV GROUP_NAME=gn
ENV USER_ID=1000
ENV GROUP_ID=1000

WORKDIR /usr/www/com/

COPY --from=node /usr/local/bin/node /usr/local/bin/

COPY Gemfile Gemfile.lock yarn.lock package.json ./

RUN addgroup -S ${GROUP_NAME} -g ${GROUP_ID} && \
    adduser -S ${USER_NAME} -G ${GROUP_NAME} -u ${USER_ID} && \
    apk update && apk upgrade && \
    apk add build-base tzdata libxml2-dev curl imagemagick postgresql-client postgresql-dev yarn && \
    if [ ${RAILS_ENV} != "production" ]; then apk add git chromium-chromedriver chromium zlib-dev xvfb wait4ports xorg-server dbus ttf-freefont mesa-dri-swrast curl udev graphviz; fi && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    gem update --system && \
    if [ ${RAILS_ENV} = "production" ]; then bundle config set without 'production'; fi && \
    bundle install --jobs 20 --retry 5 && \
    bundle update && \
    yarn install && \
    yarn upgrade && \
    yarn cache clean

USER 1000:1000
```
   
### つぎは docker-compose でも組み立てよう
```yaml
version: '3.7'

volumes:
  pg-volume:
  redis-sidekiq-volume:
  redis-cache-store-volume:    
    
networks:
  main:
    driver: bridge
    
services:
  database-master:
    image: postgres:12-alpine
    ports:
      - 54321:5432
    environment:
      POSTGRES_USER: asdf
      POSTGRES_PASSWORD: qwer
      POSTGRESQL_REPLICATION_MODE: master
      TZ: Etc/GMT
    volumes:      
      - pg-volume:/var/lib/postgresql/data      
    networks:
      main:

  database-replica:
    image: postgres:12-alpine
    ports:
      - 54322:5432
    environment:
      POSTGRES_USER: asdf
      POSTGRES_PASSWORD: qwer
      POSTGRESQL_REPLICATION_USER: asdf
      POSTGRESQL_REPLICATION_PASSWORD: asdf
      POSTGRESQL_MASTER_HOST: database-master
      POSTGRESQL_REPLICATION_MODE: slave
      POSTGRESQL_MASTER_PORT_NUMBER: 5432
      TZ: Etc/GMT
    depends_on:
    - database-master
    networks:
      main:
       
  redis-cache-store:
    networks:
      main:
    image: redis:5.0.7
    environment:
      TZ: Etc/GMT
    ports:
      - 6379:6379
    volumes:
      - redis-cache-store-volume:/var/lib/redis
    networks:
      main:

  redis-sidekiq:
    networks:
      main:
    image: redis:5.0.7
    environment:
      TZ: Etc/GMT      
    ports:
      - 6380:6379
    volumes:
      - redis-sidekiq-volume:/var/lib/redis
    networks:
      main:

  application-server:
    user: 1000:1000
    build:
      context: ./rails/
      target: ruby
    ports:
      - 3001:3000
    volumes:
      - ./rails/:/usr/www/com/
    stdin_open: true
    tty: true
    environment:
      REDIS_CACHE_STORE_URI: 'redis://redis-cache-store:6379/0'
      REDIS_SIDEKIQ_URI: 'redis://redis-sidekiq:6379/0'
      DATABASE_MASTER_HOST: 'database-master'
      DATABASE_MASTER_USERNAME: 'asdf'
      DATABASE_MASTER_PASSWORD: 'qwer'
      DATABASE_MASTER_PORT: 5432
      DATABASE_REPLICA_HOST: 'database-replica'
      DATABASE_REPLICA_PASSWORD: 'qwer'
      DATABASE_REPLICA_USERNAME: 'asdf'
      DATABASE_REPLICA_PORT: 5432
    command: 
      /bin/sh -c "yarn install --check-files && bundle update && bundle exec rails db:migrate:reset && bundle exec rails s -p 3000 -b '0.0.0.0' --early-hints"
    links:
      - redis-cache-store
      - redis-sidekiq      
      - database-master
      - database-replica
    networks:
      main:
```
### 動作確認
```sh
$ docker-compose up -d && xdg-open http://localhost:3001/    
```
![Screenshot from 2020-05-05 17-50-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190937/c256c36f-28b2-1148-630f-75af5ac0417e.png)
これがみれるとホッとしますね...  


# やれていないこと
- リバースプロキシが入っていない
- Docker
  - [Trivy](https://github.com/aquasecurity/trivy)でイメージの安全性を確認する。
  - マルチステージビルドを活用して、コンテナを軽量化する
  - Production環境で使えるイメージには程遠い...

# おわりに
計算機科学ノ進歩、発展ノタメニハ、犠牲ガツキモノナノデース.

# 参考文献
- https://gist.github.com/satendra02/1b335b06bfc5921df486f26bd98e0e89
- https://naoty.dev/posts/87.html
- https://ruby-rails.hatenadiary.com/entry/20141102/1414854000

# 更新履歴
- 2020-05-07: Dockerfile を更新