背景
プログラミングスクールではよく、OSやバージョンの違いによるエラーにどう対処するかがしばしば問題となります。この対応にメンターの時間やリソースを多く費やしてしまうと、肝心のプロダクトの作り込みに時間を割けないで終わってしまうという事態が発生します。
GeekSalonも例外ではなく、Webコース(Ruby on rails)では特にWindowsに特有の様々なエラーの対処に多くの時間を費やしてきました。そんな環境の違いによるエラーを減らすために有効な解決作の一つが「仮想環境」の導入です。その中でも今回はDockerを紹介していきたいと思います。
Dockerとは
Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです。MacやWindowsといったホストマシーンのOS上に、仮想で別のOSを立てることができるので、RubyやRailsといった、言語/フレームワークレベルのバージョンの差を気にすることなく開発が可能となります。
準備
install
Dockerにサインアップしてinstallしてください。
- windowsの方 https://docs.docker.com/docker-for-windows/install/
- Macの方 https://hub.docker.com/editions/community/docker-ce-desktop-mac
terminal(command prompt)で、
$ docker version
$ docker-compose version
と入力して、バージョンが表示されたら準備完了です。
使い方
早速、仮想環境(=dockerではこの実行単位をコンテナと呼びます)を立ち上げてみましょう。まずは、以下のコマンドを入力してみてください。
$ docker run centos:latest /bin/echo 'Hello World' # => Hello World
内容 | 概念・役割 |
---|---|
docker | コマンド名 |
run | コンテナ実行 |
centos | イメージ名 |
latest | イメージのバージョン名 |
/bin/echo | 仮想OS上で実行するコマンド |
'Hello World' | コマンドラインに送る引数 |
解説
このコマンドによってcentosの最新(latest)バージョンのコンテナが立ち上がります。centos
には仮想実行環境に関する情報が詰め込まれており、これらは通称イメージと呼ばれます。run
によってイメージを読み込み、そこで指示されたコマンドを実行します。イメージはホストマシーン上になければ、リモートのdocker hubというところからコピーして来るため、最初に立ち上げる時は少し時間がかかリます。
もう一つ例を見てみましょう
$ docker run -it ruby:2.6.5
irb(main):001:0>
今度は-it
オプションをつけることでコンテナ上でコマンドを一度実行するだけでなく、立ち上がった実行環境の中に入ることができます。今回はruby(2.6.5)イメージを指定しており、rubyを対話的に実行できるirbを利用できます。
Railsの環境を用意する
いよいよ本題です。適当なディレクトリを作成し、以下の4つファイルを作り、以下のコードをそれぞれコピペしてください。
- Gemfile
- Gemfile.lock(空のママでOK)
- Dockerfile
- docker-compose.yml
FROM ruby:2.6.5
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential nodejs && rm -rf /var/lib/apt/lists/*
# install nodejs
RUN curl -s -L git.io/nodebrew | perl - setup
ENV PATH /root/.nodebrew/current/bin:$PATH
RUN nodebrew install-binary v12.1.0
RUN nodebrew use v12.1.0
RUN bundle config --delete frozen \
&& apt-get update -qq && apt-get install -y build-essential \
&& curl -sL https://deb.nodesource.com/setup_9.x | bash - \
&& apt-get install -y nodejs \
&& 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 \
&& apt-get update && apt-get install yarn \
&& rm -rf /var/lib/apt/lists/*
RUN gem install bundler
WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install
ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD . $APP_HOME
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
command: bundle exec rails s -p 3000 -b '0.0.0.0'
environment:
RAILS_ENV: development
volumes:
- .:/myapp
- bundle:/usr/local/bundle
stdin_open: true
volumes:
bundle:
source 'https://rubygems.org'
gem 'rails', '6.0.0'
Dockerfileは先ほど実行したコマンドに様々な設定を加えてスクリプトにまとめたものです。また、Dockerでは立ち上げたコンテナは全て独立したものとして扱われますが、docker-composeを使えば、それらを繋げて利用できます。(ただし、今回は簡単のため、データベースとアプリケーションは分けていません。)
ビルドしてサーバを起動
これらを準備したら、以下のコマンドを順番に実行してください。(Macだと全部で5~6分かかります。)
$ docker-compose build # コンテナのbuild
$ docker-compose run web bundle exec rails new . --force --skip-bundle # railsアプリを作成
$ docker-compose run web bundle update
$ docker-compose run web bundle exec rails webpacker:install
$ docker-compose run web bundle exec rails db:create
(基本的に普段のRailsのコマンドにdocker-compose run web
がつくだけです。)
Serverの起動および停止には以下のコマンドを用います。
$ docker-compose up # serverの起動
$ docker-compose down # serverの終了(別のshellから行なってください。)
起動に関して、他のコマンドと同様にdocker-compose run web rails s
で動かせそうな気もしますが、実はそれではうまく行きません。仮想環境というのはあくまでホストマシーンとは別の場所で動いているため、そこでlocalhostのサーバを起動しても、ホストマシンからはアクセスできないためです。(コマンド自体はもちろん実行できます。)
docker-compose up
では、コンテナのhttpポートをホストマシーンのポートと紐付ける設定(ポートフォワーディングと言います)も一緒に行なっているため、ホストマシンからのアクセスが可能になるのです。
セットアップできればあとは簡単なのでぜひ試してみてください!!