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]>
“既存のRailsアプリにDockerを導入する” に対して1件のコメントがあります。