Docker を使ってRuby on Railsの開発環境を構築（M1チップのMac）

M1 Macbookを使ってポートフォリオを作ろうと思い、Virtual Boxで開発環境を作成しようとするとVirtual Boxが使えないことが発覚したので、Dockerを使って開発環境を構築しようとした。

しかし、色んなサイトの作成方法を真似しても上手くいかず、Dockerの公式ドキュメントを参考にしたところ、Yay! You’re on Rails!の画面を出すことができた。

手こずってしまった原因がDockerへの理解不足だったため基本的な概念を備忘録として記載しようと思う。
表現が不適切なところも多々あると思うので、ご指摘くだされば幸いです。

まずはイメージ図を頭に入れる

![スクリーンショット 2022-05-14 22.31.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/101cda71-0ae6-cd6a-73d0-219009c17c04.png)
引用
https://coinbaby8.com/docker-beginner.html

Dockerイメージという雛形があって、それを使ってDockerコンテナという開発環境を作るといったことを頭に入れた。
Dockerイメージの中にはアプリコードやOSというものが中に含まれる。
そのイメージはどこにあるのかというとDockerHubというところに用意されているので、それを使い、Dockerコンテナという環境を作るのが自分のしたい開発環境の構築だと認識した。

続いて理解したのが下図

![スクリーンショット 2022-05-14 22.28.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/b5aa9e83-8e60-5cea-d4fb-684aac4f6341.png)

引用
https://docs.docker.jp/engine/introduction/understanding-docker.html

流れとしては
①クライアントがデーモンにコマンドを実行するように依頼して、デーモンがレジストリからDockerイメージをもらってくる。
②そのDockerイメージを使ってDockerコンテナを作る
このように認識した。

クライアント：依頼主のこと（イメージやコンテナを作ってほしいという依頼をしているから作業者のこと？）
デーモン：コマンドを実行する常駐プログラムのUNIX系OSにおける呼び名

これらを頭に入れて公式ドキュメントに沿って環境を作る。
https://docs.docker.com/samples/rails/

準備するものは
Dockerfile
Gemfile
Gemfile.lock
entrypoint.sh
docker-compose.yml

これらはVScodeでファイルの作成から作る。
VScodeの使い方がわからない方はドットインストールのVScodeの使い方の動画を参考にすると良いと思う。
ターミナルも見れるのでとても便利


![スクリーンショット 2022-05-14 23.05.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/e9ba43a8-60a2-7d46-251f-5f5e582e166c.png)

ピンクで囲ったところでファイルを作成できるので、上記のファイルを作成する。

私はローカルのデスクトップにRailsというフォルダを作成して、その中に上記５つのファイルを作成した。

Dockerfileの中身から記載していく。
ファイル名のDは大文字なので注意。

```ruby:Dockerfile
# syntax=docker/dockerfile:1
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install

# 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"]
```


Gemfileの中身を記載する。
```ruby:Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
```

Gemfile.lockは中身を記載しない。
公式ドキュメントだとターミナルで下記のコマンドでGemfile.lockを作成している。

```ruby:ターミナル
touch Gemfile.lock
```


```ruby:entrypoint.sh
 #!/bin/bash
set -e

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

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




```ruby:docker-compose.yml
version: "3.9"
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

これらが作成できたらターミナルで以下のコマンドを入力する。

```ruby:ターミナル
docker-compose run --no-deps web rails new . --force --database=postgresql
```
このコマンドを実行したら、自動でフォルダやファイルが作成されたと思います。
![スクリーンショット 2022-05-14 23.54.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/c85a4c82-af3a-42d7-6503-ab34062cc21b.png)

このコマンドの意味はrunコマンドを介して指定したサービスのコンテナ内でコマンドを実行できる。
runコマンドではimageの構築から、コンテナの構築・起動までしてくれるが、引数でサービスを指定しないと失敗します。

rails newをコンテナ内でやってくれている認識。


次にこちらのコマンドを入力するのですが、

```ruby:ターミナル
docker-compose build
```

このコマンドの意味はimageを構築するが、コンテナは作成しない。
上のコマンドでimageの構築から、コンテナの構築・起動までしてくれたのになぜ下記のコマンドを入力する必要があるのか。
ドキュメントを見るとこのような記載がありました。

「MacやWindowsでDockerを実行している場合、rails newで生成されたファイルを含む全てのファイルの所有権を既に持っているはずです。

新しいGemfileを手に入れたので、イメージを再度ビルドする必要があります。(再構築が必要になるのは、このときと、GemfileやDockerfileを変更したときだけです。)」

新しいGemfileになった場合、ビルドが必要みたいなので、上記コマンドを実行する。

新しくできたdatabase.ymlの中身を書き換える。
configの配下にある。

```ruby:config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
```

そしてターミナルでコマンドを入力する。

```ruby:ターミナル
docker-compose up
```

最後にデータベースを作成する。

```ruby:ターミナル
docker-compose run web rake db:create
```

これらが上手くいったらURLバーに以下を入力する。

http://localhost:3000

するとこのような画面が出るはず。

![スクリーンショット 2022-05-14 22.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/041f4feb-259d-132b-27f2-c0b628c7be08.png)


次回からはDocker Desktopというアプリを入れることでGUIでコンテナの起動とデータベースの起動ができるようにした。

![スクリーンショット 2022-05-15 0.22.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/58009d0d-1e3e-fb0b-46ea-26a35b732448.png)

![スクリーンショット 2022-05-15 0.23.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654361/3604aaef-9ac6-0ee2-40d4-7b7783b0a2ae.png)

ここで起動したり止めたりができる。

https://matsuand.github.io/docs.docker.jp.onthefly/desktop/mac/install/

M1チップのMacかインテルチップのMacかでインストールが変わるので注意。


プログラミング初心者からすると日本語の記事が多いRuby選んだのに英語読むの？と思うかもしれないが、公式ドキュメントを読む大切さを知った。

今後は英語の記事やサイトも読めるようにしていきたい。