効率的なDockerfileの作成手順

概要
Railsの依存関係が変わったりRails自体のバージョンが変わったりして、都度Dockerfileの中身が変わってしまうので、実際のRUNコマンドや書き方というよりも、どうやったら効率よく最低限なdockerfileを作成できるか?を説明しています
WEB上を見ると他の方も似たような手順でやっていますが、主にRailsの場合で記述しているのでご容赦ください
前提
- dockerコマンドが使える状態
- railsに関しての説明はしません
目次
- docker hubでdocker imageを吟味
- docker pullする
- 素のruby-alpineコンテナ内で必要な依存関係のインストール
1. docker hubでdocker imageを吟味
- おなじみdocker hub
- rubyのdocker imageを好きなバージョンに合わせて選択します
- 基本的にruby:${version}-alpine${alpine最新version}を選択します
- 軽量な方が後の作業すべてでダウンロード時間などが短縮されて嬉しいためです
2. docker pullする
docker pull ${1のイメージ}
- ここで焦ってdockerfileを作りはじめない
3. 素のruby-alpineコンテナ内で必要な依存関係のインストール
ここがキモ!
いきなりdockerfileからbuildしたものにbundle install
などのコマンドを実行するのではなく、素のruby-alpineイメージにGemfileなどの依存ライブラリがあるものをmountしてコンテナ化し依存関係の確認をします
- まずは
vim Gemfile
- Gemfile内に必要なgemを記述します
docker run -it --rm --mount type=bind,src=$(pwd),dst=/usr/src/app ruby:2.7.1-alpine3.11 sh
(最後のイメージ情報は適宜変更してください)- マウントしたファイルを元にRailsが起動するところまで下記のようなコマンドを実行していきます
cd /usr/src/app gem install bundler -v ${project bundler version} bundle install --path=vendoer/bundle bundle exec rails s などなど
- 上記の各ステップ内でエラーが発生した場合、下記エラー対応を実施します
- エラーが出ずにRailsサーバーが起動できるところまでいけたら一旦素のイメージを走らせての検証は完了です
- 続いて
docker build
を実行して出来たイメージを走らせて(RUNして)bundle install
など再度Railsサーバーが立ち上がるところまで試します。 - 問題なければDockerfileの記述は完了です
- Dockerfileからbuildしたイメージを小さくする対応やdocker-composeを使ったRailsプロジェクトの立ち上げなどは別途記事にします
※ もうrbenvはいらない!dockerだけでRails開発をする方法 こちら記事にしました!
エラー対応
下記はbundle install
でのエラー時の対応例です
- ログを良く見ます
- とにかくログをよく見ます
- エラーの原因を確認し対応
- nokogiriやsasscなどでエラーが出ると思います
apk add --no-cache gcc g++
などエラー内容に対応できると思われるコマンドを実行します(これはあくまで仮です。本来はエラー内容にしたがって最小限のライブラリインストールに留めてください)
- 対応出来ているかの確認
- 再度コンテナ内で
bundle install
を実行します
- 再度コンテナ内で
- エラー対応状況によって、下記の対応を行います
エラー対応出来ていなかった場合
- コンテナはそのままでとりあえず対応出来るまで頑張る
- なにで対応出来たかわからなくなるかもしれないが、とりあえず進める
エラー対応出来ていた場合
- Dockerfileにコマンドを記載
- vim Dockerfile`
RUN {対応したコマンド}
- エラーが発生しなくなるまで繰り返す
まとめ
dockerfileを作る際は結構どこから手を付けていいのかわからなくなりがちで、いきなりdockerfileを書き始めると更新のたびにbuildを走らせる必要があったりで非常に効率が悪くなりがちです。
まず素のイメージを走らせている中で依存関係のインストールを行うと、何度もループはしますがかなりスムーズに作業が進むと思います。
良いdocker lifeを!