Rails
docker
boot2docker
DockerCompose
DockerMachine

DockerMachineとDockerComposeでRailsを構築してみる

More than 3 years have passed since last update.

TL;DR

DockerMachineとDockerComposeが発表されたので、早速Railsが起動できるところまで作ってみました。
開発環境として利用する想定で書いています。

Enviroment

  • OSX v10.10.2
  • docker-machine v0.1.0
  • docker-compose v1.1.0
  • Virtualbox v4.3.20
  • boot2docker v1.5.0
  • ruby v2.2.0p0
  • rails v4.2.0

Install

Virtualbox

https://www.virtualbox.org/ からInstallerをDLしてインストールします。

docker-machine

URLにバージョンが含まれているので、適宜最新のバージョンに読み替えてください。

$ curl -L https://github.com/docker/machine/releases/download/v0.1.0/docker-machine_darwin-amd64 > /usr/local/bin/docker-machine
$ chmod +x /usr/local/bin/docker-machine

docker-compose

URLにバージョンが含まれているので、適宜最新のバージョンに読み替えてください。

$ curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose

Docker Machineでローカルに開発環境のDockerを構築する

Docker Machineの作成

boot2dockerも自動的にダウンロードされます。

$ docker-machine create --driver virtualbox dev
INFO[0000] Creating SSH key...
INFO[0000] Creating VirtualBox VM...
INFO[0007] Starting VirtualBox VM...
INFO[0007] Waiting for VM to start...
INFO[0038] "dev" has been created and is now the active machine
INFO[0038] To connect: docker $(docker-machine config dev) ps

Dockerの環境変数をshellに設定します。

$ $(docker-machine env dev)
export DOCKER_TLS_VERIFY=yes
export DOCKER_CERT_PATH=$HOME/.docker/machines/.client
export DOCKER_HOST=tcp://192.168.99.100:2376

Docker Machineの停止

$ docker-machine stop dev
$ docker-machine ls
NAME   ACTIVE   DRIVER       STATE     URL   SWARM
dev    *        virtualbox   Stopped

Docker Machineの起動

$ docker-machine start dev
INFO[0000] Waiting for VM to start...
$ docker-machine ls
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM
dev    *        virtualbox   Running   tcp://192.168.99.100:2376

Docker Machine上にDockerComposeでRailsを構築する

Setup

Railsを作成します。Databaseはmysqlにしてあります。--skip-bundleオプションでgemをインストールしないようにしてます。DockerImage作成時にインストールするためです。

$ gem install rails
$ rails new docker-compose-rails --database=mysql --skip-bundle
$ cd docker-compose-rails

config/database.yml

Dockerで立ち上げたMysqlに接続する情報を設定します。
起動時はDockerが自動的に環境変数を設定してくれます。

default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: <%= ENV['DB_ENV_MYSQL_ROOT_PASSWORD'] %>
  host: <%= ENV['DATABASE_URL'] %>
  port: <%= ENV['DB_PORT_3306_TCP_PORT'] %>

development:
  <<: *default
  database: project_development

Dockerfile

FROM rails:onbuild

docker-compose.yml

db:
  image: mysql:5.6.21
  environment:
    - MYSQL_ROOT_PASSWORD=supersecretpass
  ports:
    - 3306
  volumes:
    - ./mysql:/var/lib/mysql
web:
  build: .
  command: bundle exec rails server -p 3000 --bind=0.0.0.0

  volumes:
    - .:/app
  ports:
    - 3000:3000
  links:
    - db
  environment:
    DATABASE_URL: mysql2://root:supersecretpass@db:3306    

Build

Gemfile.lockを作成します。gemはインストールしないので--no-deploymentオプションを付与して実行します。

$ bundle install --no-deployment

RailsのDockerImageを作成します。

$ docker-compose build
db uses an image, skipping
Building web...
Step 0 : FROM rails:onbuild
# Executing 4 build triggers
Trigger 0, COPY Gemfile /usr/src/app/
Step 0 : COPY Gemfile /usr/src/app/
 ---> Using cache
Trigger 1, COPY Gemfile.lock /usr/src/app/
Step 0 : COPY Gemfile.lock /usr/src/app/
Trigger 2, RUN bundle install
Step 0 : RUN bundle install
 ---> Running in 9995d0e1cb36
Don't run Bundler as root. Bundler can ask for sudo if it is needed, and
installing your bundle as root will break this application for all non-root
users on this machine.
Fetching gem metadata from https://rubygems.org/...........
Using rake 10.4.2
Installing i18n 0.7.0
Installing json 1.8.2
Installing minitest 5.5.1
Installing thread_safe 0.3.4
Installing tzinfo 1.2.2
Installing activesupport 4.2.0
Installing builder 3.2.2
Installing erubis 2.7.0
Installing mini_portile 0.6.2
Installing nokogiri 1.6.6.2
Installing rails-deprecated_sanitizer 1.0.3
Installing rails-dom-testing 1.0.5
Installing loofah 2.0.1
Installing rails-html-sanitizer 1.0.1
Installing actionview 4.2.0
Installing rack 1.6.0
Installing rack-test 0.6.3
Installing actionpack 4.2.0
Installing globalid 0.3.3
Installing activejob 4.2.0
Installing mime-types 2.4.3
Installing mail 2.6.3
Installing actionmailer 4.2.0
Installing activemodel 4.2.0
Installing arel 6.0.0
Installing activerecord 4.2.0
Installing debug_inspector 0.0.2
Installing binding_of_caller 0.7.2
Installing columnize 0.9.0
Installing debugger-linecache 1.2.0
Installing slop 3.6.0
Installing byebug 3.5.1
Installing coffee-script-source 1.9.1
Installing execjs 2.3.0
Installing coffee-script 2.3.0
Installing thor 0.19.1
Installing railties 4.2.0
Installing coffee-rails 4.1.0
Installing hike 1.2.3
Installing multi_json 1.10.1
Installing jbuilder 2.2.8
Installing jquery-rails 4.0.3
Installing mysql2 0.3.18
Using bundler 1.7.12
Installing tilt 1.4.1
Installing sprockets 2.12.3
Installing sprockets-rails 2.2.4
Installing rails 4.2.0
Using rdoc 4.2.0
Installing sass 3.4.13
Installing sass-rails 5.0.1
Installing sdoc 0.4.1
Installing spring 1.3.3
Installing turbolinks 2.5.3
Installing uglifier 2.7.1
Installing web-console 2.1.0
Your bundle is complete!
It was installed into /usr/local/bundle
Trigger 3, COPY . /usr/src/app
Step 0 : COPY . /usr/src/app
 ---> 2ede4b3a1b8a
Removing intermediate container 5e18d2e37320
Removing intermediate container 9995d0e1cb36
Removing intermediate container d12157b6a196
Successfully built 2ede4b3a1b8a

作成されたDockerImageを確認します。

$ docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
dockercomposerails_web       latest              2ede4b3a1b8a        2 minutes ago       939.2 MB
rails                        onbuild             fc33f5385339        4 weeks ago         828.5 MB
ruby                         2.2.0               51473a2975de        4 weeks ago         774.7 MB

UP

RailsとMysqlをDocker上で同時に立ち上げます。

$ docker-compose up
Recreating dockercomposerails_db_1...
Recreating dockercomposerails_web_1...
Attaching to dockercomposerails_db_1, dockercomposerails_web_1
db_1  | 2015-03-01 16:04:44 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
db_1  | 2015-03-01 16:04:44 1 [Note] Plugin 'FEDERATED' is disabled.
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Using atomics to ref count buffer pool pages
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: The InnoDB memory heap is disabled
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Memory barrier is not used
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Compressed tables use zlib 1.2.3
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Using Linux native AIO
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Not using CPU crc32 instructions
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Initializing buffer pool, size = 128.0M
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Completed initialization of buffer pool
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Highest supported file format is Barracuda.
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: 128 rollback segment(s) are active.
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: Waiting for purge to start
db_1  | 2015-03-01 16:04:44 1 [Note] InnoDB: 5.6.21 started; log sequence number 1625997
db_1  | 2015-03-01 16:04:44 1 [Note] Server hostname (bind-address): '*'; port: 3306
db_1  | 2015-03-01 16:04:44 1 [Note] IPv6 is available.
db_1  | 2015-03-01 16:04:44 1 [Note]   - '::' resolves to '::';
db_1  | 2015-03-01 16:04:44 1 [Note] Server socket created on IP: '::'.
db_1  | 2015-03-01 16:04:44 1 [Note] Event Scheduler: Loaded 0 events
db_1  | 2015-03-01 16:04:44 1 [Note] mysqld: ready for connections.
db_1  | Version: '5.6.21'  socket: '/tmp/mysql.sock'  port: 3306  MySQL Community Server (GPL)
web_1 | => Booting WEBrick
web_1 | => Rails 4.2.0 application starting in development on http://0.0.0.0:3000
web_1 | => Run `rails server -h` for more startup options
web_1 | => Ctrl-C to shutdown server
web_1 | [2015-03-01 16:04:47] INFO  WEBrick 1.3.1
web_1 | [2015-03-01 16:04:47] INFO  ruby 2.2.0 (2014-12-25) [x86_64-linux]
web_1 | [2015-03-01 16:04:47] INFO  WEBrick::HTTPServer#start: pid=1 port=3000

別のコンソールでdb:createを行います。

$ docker-compose run web rake db:create

Open Browser

ブラウザを開いて動作確認をします。
接続先のIPアドレスはdocker-machine ipで取得できます。

$ open "http://$(docker-machine ip):3000"

Ruby_on_Rails__Welcome_aboard.jpg

REF Dockerfile ONBUILD and FROM

Docker Official Image packaging for Ruby on Rails

//github.com/docker-library/rails/blob/master/onbuild/Dockerfile
FROM ruby:2.2.0

# throw errors if Gemfile has been modified since Gemfile.lock
RUN bundle config --global frozen 1

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ONBUILD COPY Gemfile /usr/src/app/
ONBUILD COPY Gemfile.lock /usr/src/app/
ONBUILD RUN bundle install

ONBUILD COPY . /usr/src/app

RUN apt-get update && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y mysql-client postgresql-client sqlite3 --no-install-recommends && rm -rf /var/lib/apt/lists/*

EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

Docker Official Image packaging for Ruby

//github.com/docker-library/ruby/blob/master/2.2/Dockerfile
FROM buildpack-deps:jessie

ENV RUBY_MAJOR 2.2
ENV RUBY_VERSION 2.2.0

# some of ruby's build scripts are written in ruby
# we purge this later to make sure our final image uses what we just built
RUN apt-get update \
    && apt-get install -y bison libgdbm-dev ruby \
    && rm -rf /var/lib/apt/lists/* \
    && mkdir -p /usr/src/ruby \
    && curl -SL "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.bz2" \
        | tar -xjC /usr/src/ruby --strip-components=1 \
    && cd /usr/src/ruby \
    && autoconf \
    && ./configure --disable-install-doc \
    && make -j"$(nproc)" \
    && make install \
    && apt-get purge -y --auto-remove bison libgdbm-dev ruby \
    && rm -r /usr/src/ruby

# skip installing gem documentation
RUN echo 'gem: --no-rdoc --no-ri' >> "$HOME/.gemrc"

# install things globally, for great justice
ENV GEM_HOME /usr/local/bundle
ENV PATH $GEM_HOME/bin:$PATH
RUN gem install bundler \
    && bundle config --global path "$GEM_HOME" \
    && bundle config --global bin "$GEM_HOME/bin"

# don't create ".bundle" in all our apps
ENV BUNDLE_APP_CONFIG $GEM_HOME

CMD [ "irb" ]

REF

Qiita

Official

Others