RailsのDocker開発環境を一撃で作成するスクリプトを作ってみました

## 結論

今回ご紹介するスクリプトは以下の3つの条件の掛け合わせでDockerの開発環境を作成可能です。もちろん、起動も可能です。

- Railsのお好きな[バージョン](https://rubygems.org/gems/rails/versions)を選択(5.1以前のバージョンでもwebpackを含みます)
- Rubyのお好きな[バージョン](https://hub.docker.com/_/ruby)を選択
- MySQL(バージョン8対応)かPostgreSQLを選択

### 環境構築実行例

#### Rails5.2.2, MySQL, Ruby2.5

```bash:
$ ./build.sh 5.2.2 mysql 2.5
```

![rails5.2.2_ruby2.5](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90032/f0e1dd12-e687-f411-fddb-888c4d81c834.png)

#### Rails5.0.0, MySQL, Ruby2.5

```bash
$ ./build.sh 5.0.0 mysql 2.5
```

![rails5.0.0_ruby2.5](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90032/4d9c3012-fdf4-9e9e-b399-7b26849ec776.png)

#### Rails6.1.2, MySQL, Ruby3.0

```bash
$ ./build.sh 6.1.2 mysql 3.0
```

![rails6.1.2_ruby3.0](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90032/0c806fba-abaa-0f97-c324-18b9d4166367.png)

#### Rails5.2.2, PostgreSQL, Ruby2.5

```bash:
$ ./build.sh 5.2.2 postgres 2.5
```

![rails5.2.2_ruby2.5_post](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90032/76e9436e-b04c-680e-0b51-a3be1225ee6b.png)

※MySQLの時と同じ画面ですが、PostgreSQLで起動した時のキャプチャを貼ってます

### とにかく最初からやり直したい時

Dockerは階層型のキャッシュを利用して処理を効率化する仕組みになっているのですが、そのトレードオフとしてイメージが中途半端な状態だと場合によってはエラー対応に追われることになります。

その過程でよくわからない状態になってしまった場合、全部消えてもいいので最初からやり直したい時は、下記のコマンドを実行してください。

__※このスクリプトで作成する以外のDocker環境が既にある場合は、安易に実行しないでください。内部で[docker image prune -f](https://docs.docker.com/engine/reference/commandline/image_prune/)とか実行しているので。__

```bash
$ ./clean.sh
```

### スクリプトのリポジトリ

スクリプトはGitHubで公開しているので、下記のリポジトリからクローンをお願いします。
上記の情報以外の詳細はREADMEをご覧ください。

[Rails Docker builder](https://github.com/yuya-tajima/rails-docker-builder) 

### 注意事項

Dockerデーモン起動およびDocker Composeを利用できる環境を前提としているので、[Docker Desktop](https://www.docker.com/products/docker-desktop)等からインストールしておいて下さい。

FreeBSDをベースとしたOS(macOS)を前提条件としていますが、sedのパラメータ指定がGNU系と違うくらいの差だと思うのでそこの処理さえ変えれば他のOSでも動くと思います。

Railsのバージョン5.0以上であれば動作可能であることのテストはできていますが、4系で動かす場合はひと手間必要です。ただ、[The State of Developer Ecosystem 2020](https://www.jetbrains.com/lp/devecosystem-2020/)の[Ruby](https://www.jetbrains.com/lp/devecosystem-2020/ruby/)の現状から4系対応の処理を入れ込むメリットはないように思えているので、今のところ入れていません。

## 経緯

- プログラミング初学者がプログラミングそのものに集中できるようにしたい
- Dockerの環境操作におけるCLIのインターフェースを極力統一したい

### プログラミング初学者がプログラミングそのものに集中できるようにしたい

個人的な理由ですが、新規の環境でRailsを使ったアプリケーション開発に関わることになったので、予習をする為にRailsの環境作成を行いました。

Rails公式サイト内での[Getting Started with Rails](https://guides.rubyonrails.org/getting_started.html)で一般的なOSでのインストール方法のガイドが掲載されていましたが、僕は何かしらの仮想環境で環境構築を行いたいので最初はVirtualBox内のUbuntuを使ってRailsの環境構築を行いました。
そして、DRY原則やCoC原則に規定されたRailsのアーキテクチャに感心しながら楽しく学習を進めることができました。

そのうちDockerでのRails環境を構築して検証を進めてみたくなったので、Dockerが提供しているドキュメント[Quickstart: Compose and Rails](https://docs.docker.com/compose/rails/)を参考に環境構築を進めました。

僕の場合は、現場の環境にきっちり固定したRailsのバージョンをいくつか試してみたかったのと、DBはPostgreSQLではなくMySQLを使いたかったので上記通りではなく少し変更して環境を作成しました。  
※現場の環境にバージョンを固定して検証したいっていうニーズ自体は結構あると思っています。

ここまでやってふと思ったのが、「Railsはプログラミング初学者が最初に選択することが多いフレームワークだと思っているけど、RailsのDocker環境構築は初学者には結構ハードル高くないか？」ということです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Railsはプログラミング初学者が最初に選択することが多いフレームワークだと思っているけど、RailsのDocker環境構築は初学者にはきつい作業だなと思った。<br><br>なので、初学者がプログラミングの勉強だけに集中できるように何も考えず一発で環境構築できるコマンド作ったので共有することにする😇</p>&mdash; 親方 (@tajima_taso) <a href="https://twitter.com/tajima_taso/status/1360451462766108674?ref_src=twsrc%5Etfw">February 13, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Dockerはサービスの提供基盤としても主流になっていると思うので、初学者といえどもエンジニアを生業にすることを目指すならDocker環境上での開発に慣れておいた方が良いです。しかしながら、環境構築でのトライアンドエラーはとにかくプログラミングできるようになりたい初学者にとっては苦痛でしかないと思います。

もちろん、いずれはこういった工程を経て自力で問題を解決していくエンジニアにならなければならない局面が訪れると思いますが、初学者の今はその時ではないはずです。
※ちなみに僕はこういった調査とトライアンドエラーを繰り返す作業が大好物です😇

ただ、本当は「初学者の為」というのは後付で、自分が個人的に必要で作って使ってみたけど、他の人の助けになるかもしれないと思って公開したので一石二鳥です。

### Dockerの環境操作におけるCLIのインターフェースを極力統一したい

公開するしない以前に、僕が最初にスクリプト化しようと思った動機はこれです。

極力互換性を保ってくれてはいますが、Dockerはコマンドが新規追加されたり今まで使っていたコマンドやオプションが廃止ないし非推奨になったり、新たなユーティリティが登場したりで他のツールよりインターフェースの変化が激しいと個人的には思っています。
ただ、それは悪いことではなく、[アジャイルソフトウェア開発の流儀](https://www.amazon.co.jp/dp/4797347783/)で述べられているように、ソフトウェア開発は変化が激しくて当たり前の世界なのでエンジニアはそれらに嘆くことなく追随していく手法を確立する義務があります。

そのようなケースに対応する僕なりの解の一つが今回のスクリプトでした。今後も何か変化があったらなるべく対応していこうと思います。
その場合も、このスクリプトのインターフェースは変わらずにキープしていくつもりです。

もしスクリプトへの機能追加やバグの指摘等あれば、プルリクでも何でも良いので頂けると嬉しいです。

## Docker自体を詳しく知りたい方へ

Docker自体について詳しく知りたい方は拙文ですが[原理原則で理解するDocker](https://qiita.com/tajima_taso/items/28938415846dcc2e83ff)もあわせてご覧頂くと良いかもしれません。※内容が古くなってきているので新しい記事も書きたいですが 😅

## まとめ

何度も自由に壊したり作ったりできるオモチャのような環境を手に入れるというのは、エンジニアの経験値を効率的に上げてくれる修行場のようなものなので、今後も壊しては作っては繰り返してレベルアップしていきたいと思います。