Docker で Rails（Nginx + Unicorn + MySQL) を動かす。


DockerHub にて、公式で各種プログラミング言語のベースイメージも公開された（Rails もある）ので使ってみようと思う。
> Docker Adds 11 Top Language Stacks to Docker Hub Registry | Business Wire : http://www.businesswire.com/news/home/20140924005223/en/Docker-Adds-11-Top-Language-Stacks-Docker#.VCVCRSt_tGR

OSX 環境なので、boot2docker使う。

```
$ boot2docker init
$ boot2docker start
```

```.zshrc
# 追記しておくと良い。
+ export DOCKER_HOST=tcp://192.168.59.103:2375
```


# Raisアプリつくる

```
$ rails new sample-app -d mysql
$ cd sample-app
$ rails g scaffold article title:string content:string
$ bundle exec rake db:migrate
```

```rb:config/route.rb
+ root "articles#index"
```

```rb:Gemfile
+ gem 'unicorn'
+ gem 'foreman'
```

```
$ bundle
```

```rb:confg/unicorn.rb
# config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end 

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end
```

```Procfile.dev
web: bundle exec unicorn -p 8080 -E production -c config/unicorn.rb
```

```
$ bundle exec rake db:create && bundle exec rake db:migrate
$ foreman start -f Procfile.dev
```
ここまでで、ローカルで動くことを確認。(Unicorn + MySQL) 
http://localhost:8080/

# Docker Hub から各イメージをとってきて動かす(pull + run)
https://hub.docker.com/ でたくさんイメージが公開されている。
今回は公式っぽいのを使う。
```docker run ```コマンド時に指定して自動的に pull + run してくれる。

## MySQL

mysql Repository | Docker Hub Registry - Repositories of Docker Images : https://registry.hub.docker.com/_/mysql/

```
$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=password -d mysql
```

## Rails
Production用の設定を反映させる。
--link オプションで コンテナ間の環境変数にアクセスできる。

```rb:config/database.yml
production:
  <<: *default
  database: sample-app_production
  username: root
  password: <%= ENV['MYSQL_ROOT_PASSWORD'] %>
  host: <%= ENV['DB_PORT_3306_TCP_ADDR'] %>
  port: <%= ENV['DB_PORT_3306_TCP_PORT'] %>

```

Dockerfile(rails) は onbuild のものを参考にする。
https://github.com/docker-library/rails/blob/master/onbuild/Dockerfile

```rb:Dockerfile
FROM ruby:2.1.3

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

ADD Gemfile /usr/src/app/
ADD Gemfile.lock /usr/src/app/
RUN bundle install --system

ADD Procfile /usr/src/app/

ADD . /usr/src/app

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

# ENV SECRET_KEY_BASE RUN ["bundle", "exec", "rake", "secret"]

# ONBUILD RUN bundle exec rake db:create RAILS_ENV=production
# ONBUILD RUN bundle exec rake db:migrate RAILS_ENV=production

EXPOSE 8080

# CMD ["bundle", "exec", "foreman", "start" ]
ENTRYPOINT bin/start_server.sh
```

start_server.sh　使わないで Dockerfile だけでやりたい（コメントアウトしたとこ）
けど、うまくできてない。。

```bin/start_sever.sh
#!/bin/bash -x
export SECRET_KEY_BASE=`bundle exec rake secret`
bundle exec rake db:create RAILS_ENV=production
bundle exec rake db:migrate RAILS_ENV=production
bundle exec foreman start
```

```
$ sudo chmod 755 bin/start_server.sh
```

```rb:Procfile
web: bundle exec unicorn -E production -c config/unicorn.rb
```

build。

```
$ docker build -t 7kaji/sample-app .
```

Railsコンテナ起動。

```
$ docker run -d --name unicorn --link mysql:db 7kaji/sample-app
```
-p 8080:8080 オプションをつけると、ホストサーバへフォワードされるので、
http://192.168.59.103:8080 で確認できるはず。

## Nginx

nginx Repository | Docker Hub Registry - Repositories of Docker Images : https://registry.hub.docker.com/_/nginx/

リバースプロキシを導入する。
Nginx用の Dockerfileを作る。

```rb:config/nginx/Dockerfile
FROM nginx:1.7.5

COPY nginx.conf /etc/nginx/nginx.conf
```

```config/nginx/nginx.conf
http {
    upstream unicorn{
      server app:8080;  # appは--linkで名前解決できる
      # server <% ENV['APP_PORT'] %>;  # ruby入れて、.erbで参照してもいいかも
    }

    server {
        listen       80;
        #server_name  localhost.com;
    
        location / {
            proxy_pass http://unicorn;
        }
    }
}

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

```

Nginx用のDockerfile のとこでbuild。
 
```
$ docker build -t 7kaji/sample-nginx .
```

Nginxコンテナ起動。

```
$ docker run -d --name nginx --link unicorn:app -p 80:80 7kaji/sample-nginx
```
## 確認

```
$ docker ps
CONTAINER ID        IMAGE                       COMMAND                CREATED             STATUS              PORTS                         NAMES
dbb77e3d9835        7kaji/sample-nginx:latest   "nginx -g 'daemon of   21 seconds ago      Up 21 seconds       443/tcp, 0.0.0.0:80->80/tcp   nginx
a9c41d021def        7kaji/sample-app:latest     "/bin/sh -c bin/star   11 minutes ago      Up 11 minutes       8080/tcp                      nginx/app,unicorn
104c5f356384        mysql:latest                "/entrypoint.sh mysq   23 minutes ago      Up 23 minutes       0.0.0.0:3306->3306/tcp        mysql,nginx/app/db,unicorn/db
```

### ブラウザで確認
http://192.168.59.103/

![スクリーンショット 2014-10-02 0.26.38.png](https://qiita-image-store.s3.amazonaws.com/0/4598/7d4d7337-665c-24ee-706d-22a5a719ccd5.png "スクリーンショット 2014-10-02 0.26.38.png")

## Dockerイメージ
```
$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
7kaji/sample-nginx   latest              ffa7aa42869b        6 minutes ago       100.2 MB
7kaji/sample-app     latest              b376d11c5669        18 minutes ago      853.8 MB
mysql                latest              e65bb8be14c0        3 days ago          235.6 MB
ruby                 2.1.3               5cd733bb7b03        3 days ago          801.5 MB
nginx                1.7.5               d2d79aebd368        4 days ago          100.2 MB
```


#参考・引用
>
- DockerHub公式の言語Stack | SOTA : http://deeeet.com/writing/2014/09/25/dockerhub-official-language-stacks/
- Dockerのネットワークの基礎 | SOTA : http://deeeet.com/writing/2014/05/11/docker-network/
- Dockerコンテナ間のlink，database.ymlの書き方 | SOTA : http://deeeet.com/writing/2014/03/20/docker-link-container/
- Dockerを使いRuby on Railsアプリ、PostgreSQL、Nginxなどのコンテナーをクラウドサービスで動かしてみた - yuumi3のお仕事日記 : http://yuumi3.hatenablog.com/entry/2014/08/06/111743
- Rails unicorn · herokaijp/devcenter Wiki : https://github.com/herokaijp/devcenter/wiki/Rails-unicorn
- 【翻訳】DockerとVagrantによるRails開発環境 - Qiita : http://qiita.com/cieux1@github/items/b2294f8adddefb357a37
- Docker上にRedmineをたてる - Qiita : http://qiita.com/mattuso/items/c3365bc226076ecba227