DockerがApple M1チップに対応したので、挙動を確認しつつ導入してみました。
将来的にECSで本番やテスト環境構築でも使いたい。

結論はいい感じ!短時間で環境構築が終わる。
ただ、docker-composeの起動に少し時間が掛かるのと、
パワーが欲しい場合はDBやNoSQLだけDocker使うのが良さそう。

要件

・公式で提供されているイメージを使う。
・軽量化したい。Alpine Linux版があればそっちを採用。
・MySQLを使いたい。公式に手順のあるPostgreSQLも試す。

Dockerインストール

Docker Desktop for Macをダウンロードして、普通にインストール
https://hub.docker.com/editions/community/docker-ce-desktop-mac/

イメージ作成

Dockerfile

Dockerfile を既存のRailsアプリのルートに作成
※イメージに入れるもの

# https://hub.docker.com/_/ruby
FROM ruby:3.0.0-alpine
RUN apk update && apk add --no-cache --update build-base tzdata bash yarn python2 imagemagick graphviz mysql-dev mysql-client

WORKDIR /workdir
ENV LANG="ja_JP.UTF-8"

COPY Gemfile Gemfile.lock ./
RUN bundle install --no-cache

COPY package.json yarn.lock ./
RUN yarn install && yarn cache clean

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]

Tips

・bashを入れたのは、Alpineのデフォルトがashで、entrypoint.shで使う為
(書き換えても良いのでが、学習コストを考えて)
・yarnを動かすのにpython2が必要
・imagemagickとgraphvizは必要な場合
・mysql-clientがないとrails dbでコケる

おまけ

PostgreSQLを使いたい場合は、「mysql-dev mysql-client」を「postgresql-dev postgresql-client」に変更

RUN apk update && apk add --no-cache --update build-base tzdata bash yarn python2 imagemagick graphviz postgresql-dev postgresql-client

Ubuntuのを使う場合は、最初の所を下記に書き換えればOK

FROM ruby:3.0.0
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y yarn imagemagick graphviz default-mysql-client

Tips: 最新のUbuntuだと「mysql-client」は使えず「default-mysql-client」なら使える

同様にPostgreSQLを使いたい場合は、「default-mysql-client」を「postgresql-client」に変更

RUN apt-get update -qq && apt-get install -y yarn imagemagick graphviz postgresql-client

entrypoint.sh

entrypoint.sh を作成
※起動時に実行したいものかな。公式のまま使用

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /workdir/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

.dockerignore

.dockerignore を作成
※軽量化の為、イメージ含めないもの。「設計」は私のに入れているので追加

.bundle
.byebug_history
.yardoc
.yarn-integrity
config/master.key
db/*.sqlite3
db/*.sqlite3-journal
db/*.sqlite3-*
db/erd.pdf
doc
log
node_modules
public/assets
public/packs
public/packs-test
public/robots.txt
public/uploads
storage
tmp
yarn-error.log
yarn-debug.log*
設計

docker-compose.yml

docker-compose.yml を作成
※今回は、Dockerfileで作るイメージ以外にDBも起動する

version: '3.9'
services:
  db:
    platform: linux/x86_64 # Tips: mysql -> ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries
    image: mysql:8.0 # https://hub.docker.com/_/mysql
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - ./tmp/mysql:/var/lib/mysql:delegated
    environment:
      MYSQL_ROOT_PASSWORD: xyz789
    ports:
      - 3306:3306
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/workdir
      - /workdir/node_modules
      - /workdir/public/packs
      - /workdir/public/packs-test
    ports:
      - 3000:3000
    depends_on:
      - db

Tips

・「tmp/mysql」にDBのデータが入るので、作り直してもデータが残る
(バージョン変える場合は、tmp/mysqlを削除すればOK)
・delegated:速度優先にする為
(コンテナ上の更新がホスト上に反映するまで、遅延が発生するのを許容)
・「.:/workdir」は.(ローカル)を/workdir(Dockerイメージの中)と同期
・「/workdir/node_modules」(public/packsとpacks-testも同様)は、node_modulesをDockerイメージの中だけにして、ローカルと同期しない
・明示してませんが、gemもデフォルトだと別のパスなので、Dockerイメージの中だけ

おまけ

PostgreSQLを使いたい場合は、dbの所を下記に書き換えればOK

  db:
    image: postgres:13.3-alpine # https://hub.docker.com/_/postgres
    volumes:
      - ./tmp/postgresql:/var/lib/postgresql/data:delegated
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: xyz789
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=ja_JP.UTF-8"
    ports:
      - 5432:5432

config/database.yml

config/database.yml を修正

  # encoding: utf8
  # collation: utf8_bin
  encoding: utf8mb4 # Tips: MySQL 5.7.7以降でないとmigrateに失敗する
  collation: utf8mb4_bin
  # username: rails_app
  # password: abc123
  # host: localhost
  username: root
  password: xyz789
  host: db

Tips

utf8/utf8_binだとrails cでエラーになりました。

% docker-compose run web rails c 
ERROR -- : run() in thread failed: incompatible character encodings: ASCII-8BIT and UTF-8:\n /usr/local/bundle/gems/listen-3.0.8/lib/listen/record/entry.rb:47:in `join'

おまけ

PostgreSQLを使いたい場合も同様に

  username: postgres
  password: xyz789
  host: db

docker-compose build

初回とDockerfileを変更した場合
※bundleやyarn installはコマンド叩いてもいいけど、buildしても良いかも

% docker-compose build
db uses an image, skipping
Building web
[+] Building 225.3s (14/14) FINISHED                                                                                                                            
 => [internal] load build definition from Dockerfile                                                                                                       0.0s
 => => transferring dockerfile: 37B                                                                                                                        0.0s
 => [internal] load .dockerignore                                                                                                                          0.0s
 => => transferring context: 35B                                                                                                                           0.0s
 => [internal] load metadata for docker.io/library/ruby:3.0.0-alpine                                                                                       3.6s
 => [internal] load build context                                                                                                                          0.1s
 => => transferring context: 12.12kB                                                                                                                       0.0s
 => [1/9] FROM docker.io/library/ruby:3.0.0-alpine@sha256:17fcf2715439387dc050fcd6801a98c6b61c196739e56d4c8a12d93bb0dcecac                                 0.0s
 => CACHED [2/9] RUN apk update && apk add --no-cache --update build-base tzdata bash yarn python2 imagemagick graphviz mysql-dev mysql-client             0.0s
 => CACHED [3/9] WORKDIR /workdir                                                                                                                          0.0s
 => [4/9] COPY Gemfile Gemfile.lock ./                                                                                                                     0.0s
 => [5/9] RUN bundle install --no-cache                                                                                                                  101.6s
 => [6/9] COPY package.json yarn.lock ./                                                                                                                   0.0s
 => [7/9] RUN yarn install && yarn cache clean                                                                                                           117.5s 
 => [8/9] COPY entrypoint.sh /usr/bin/                                                                                                                     0.0s 
 => [9/9] RUN chmod +x /usr/bin/entrypoint.sh                                                                                                              0.2s 
 => exporting to image                                                                                                                                     2.2s 
 => => exporting layers                                                                                                                                    2.2s 
 => => writing image sha256:167eeb845d441d0a6ccd708afc01ecd105f8316cccf2a9da669630d683edfaa2                                                               0.0s 
 => => naming to docker.io/library/rails-app-origin_web                                                                                                    0.0s 

コンテナ起動

docker-compose up

% docker-compose up   
Pulling db (mysql:8.0)...
8.0: Pulling from library/mysql
b4d181a07f80: Pull complete
a462b60610f5: Pull complete
578fafb77ab8: Pull complete
524046006037: Pull complete
d0cbe54c8855: Pull complete
aa18e05cc46d: Pull complete
32ca814c833f: Pull complete
9ecc8abdb7f5: Pull complete
ad042b682e0f: Pull complete
71d327c6bb78: Pull complete
165d1d10a3fa: Pull complete
2f40c47d0626: Pull complete
Digest: sha256:52b8406e4c32b8cf0557f1b74517e14c5393aff5cf0384eff62d9e81f4985d4b
Status: Downloaded newer image for mysql:8.0
Creating rails-app-origin_db_1 ... done
Creating rails-app-origin_web_1 ... done
Attaching to rails-app-origin_db_1, rails-app-origin_web_1
〜省略〜
db_1   | 2021-07-18T09:35:32.747062Z 1 [ERROR] [MY-012585] [InnoDB] Linux Native AIO interface is not supported on this platform. Please check your OS documentation and install appropriate binary of InnoDB.
db_1   | 2021-07-18T09:35:32.747900Z 1 [Warning] [MY-012654] [InnoDB] Linux Native AIO disabled.
db_1   | 2021-07-18T09:35:34.401824Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.

InnoDBの初期化は出来てるので、良いのかな?

〜省略〜
db_1   | 2021-07-18T09:35:36.184517Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

DB起動OK

web_1  | => Booting Puma
web_1  | => Rails 6.1.4 application starting in development 
web_1  | => Run `bin/rails server --help` for more startup options
web_1  | Puma starting in single mode...
web_1  | * Version 4.3.8 (ruby 3.0.0-p0), codename: Mysterious Traveller
web_1  | * Min threads: 5, max threads: 5
web_1  | * Environment: development
web_1  | * Listening on tcp://0.0.0.0:3000
web_1  | Use Ctrl-C to stop

Rails起動OK

DB作成

別のタブで

% docker-compose run web rails db:create db:migrate db:seed

http://localhost:3000/

web_1  | Started GET "/" for 172.21.0.1 at 2021-07-18 09:39:16 +0000
〜省略〜
web_1  | [Webpacker] Compiling...
web_1  | [Webpacker] Compiled all packs in /workdir/public/packs

ローカルにpublic/packsディレクトリが作られるけど、中身はなしでOK
(node_modulesも同様)

Ctrl-C(または % docker-compose down)で終了

^CGracefully stopping... (press Ctrl+C again to force)
Stopping rails-app-origin_web_1 ... done
Stopping rails-app-origin_db_1  ... done

確認とクリーニング

Docker内のイメージ

% docker images
REPOSITORY             TAG       IMAGE ID       CREATED          SIZE
rails-app-origin_web   latest    167eeb845d44   36 minutes ago   842MB
mysql                  8.0       5c62e459e087   3 weeks ago      556MB

起動中のコンテナ

% docker ps    
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Docker内のコンテナ

% docker ps -a
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS                          PORTS     NAMES
cd6552669118   rails-app-origin_web   "entrypoint.sh bash …"   9 minutes ago   Exited (1) About a minute ago             rails-app-origin_web_1
053357b127cc   mysql:8.0              "docker-entrypoint.s…"   9 minutes ago   Exited (0) About a minute ago             rails-app-origin_db_1
コンテナ削除
% docker rm <CONTAINER ID>

コンテナ全消し
% docker container prune

イメージ削除
% docker rmi <IMAGE ID>

イメージ全消し
% docker images -aq | xargs docker rmi

おまけ:DBだけ起動したい

% docker-compose up db
Starting rails-app-origin_db_1 ... done
Attaching to rails-app-origin_db_1
〜省略〜
db_1   | 2021-07-18T09:53:26.605750Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.
% telnet localhost 3306
Trying ::1...
Connected to localhost.
Escape character is '^]'.

database.ymlのhostをlocalhostに戻せば繋がりそうですね。
MySQLの場合、localhostだとポート番号を指定してもsocket接続になってしまう。127.0.0.1にすればOKそう。

% mysql -h localhost -P 3306 -u root -p rails_app_development
Enter password: 
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
% mysql -h 127.0.0.1 -u root -p rails_app_development   
Enter password: 
MySQL [rails_app_development]> 

今回のコミット内容
https://dev.azure.com/nightonly/rails-app-origin/_git/rails-app-origin/commit/dbe8b45ecb4d071a6d1ea898e892a1a68ce39b13

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です