Dockerでrails(nginx, mysql, redis)を使った環境を立ち上げる+ECSでも（備忘録）


開発用のため、RDS, ElastiCacheを使わずに以下のコンテナを立ちあげ、お互いの連携を設定する。

* railsコンテナ
* mysqlコンテナ
* redisコンテナ
* nginxコンテナ

本番稼動しているサービスの設定としては、セキュリティガバガバすぎるのであくまでもテストとして動かした程度です。


先に今回苦労したところ
---

* ActionController::InvalidAuthenticityToken
* public以下の読み込み
* cssが読み込まれない

先に今回の肝を言っておくと
---

* nginxコンテナの設定（nginx.conf)マジ大事
* DockerのData Volumeマジ大事

最後の方に参考程度のnginx.confの設定を載せています。

ActionController::InvalidAuthenticityTokenについて
---

試しに作ってみたアプリケーションは、railsを使う人ならお馴染み？のgem `devise` を使ったユーザー認証を行っています。

実際に、ユーザー登録をしてみると下記のエラーが

```
ActionController::InvalidAuthenticityToken
```

結論から言うと、nginxの設定が抜けていました。
解決方法は以下の記事がとても参考になりました。

http://qiita.com/youcune/items/962d71f0ac19dfdcec11


public以下の読み込みについて
---

railsではcss, jsなどは`rake assets:precompile`をしてproduction環境で動かすと思います。

ここで、Dockerでnginxコンテナ、railsコンテナそれぞれを独立させて動かすと以下の点に気付きます。

* css, js, 500.htmlなどの静的なファイルは、railsコンテナ内に存在する
* nginx内からrailsコンテナ内の静的ファイルにアクセスする必要がある

ここに関してはDockerのData Volume機能を使って、railsコンテナのpublicディレクトリをnginxコンテナ内から読み取れるようにします。

DockerのData Volumeの機能に関しては、以下の記事が参考になると思います。

http://qiita.com/lciel/items/e21a4ede3bac7fb3ec5a

cssが読み込まれない
---

nginx.confの設定漏れです。

```
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
```

忘れてはいけない（戒め）

結論
---

今回はDataVolumeとnginx周りでめちゃくちゃ詰まっていました。

最終的にnginx.confがどんな感じになったかというと

```
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    upstream puma {
      server app:3000;
    }

    server {
        listen       80;
        try_files $uri @puma;

        location ^~ /assets/ {
            root /"Dockerのマウントで指定したrailsアプリのパス"/public/;
        }

        location @puma {
            proxy_pass http://puma;

            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Client-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

user  nginx;
worker_processes  auto;

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

events {
    worker_connections  1024;
}

```

（実際のサービスで動かすわけではないので、access logとかの設定は抜けてますが）

実際にDockerコマンドで４つのコンテナを立ち上げる場合は

* mysql

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

`mysql`というのはimageの名前です。
`MYSQL_ROOT_PASSWORD=password`と言うDBのパスワードを書いて、railsのdatabase.ymlには、passwordとベタ書きをしています。ガバガバなので真似しないでください。

* redis

```
docker run --name redis -p 6379:6379 -d redis:latest
```

* rails


~~~
docker run -it -v "railsのディレクトリ" --name puma --link redis:session_store --link mysql:db my_rails 
~~~

1. `-v "railsのディレクトリ"` volumeを作成するコマンドです。後述のnginxのコマンドで`--volumes-from puma`を添えること、ファイルの共有ができるます。
2. `--link redis:session_store` redisの情報をrails上から読み込むためにリンクを設定しています。
	3. ちなみにconfig/environments/production.rbはこんな感じになります。

	```
	    config.session_store :redis_store, {
       servers: {
          host: ENV['SESSION_STORE_PORT_6379_TCP_ADDR'],
          port: ENV['SESSION_STORE_PORT_6379_TCP_PORT'],
          db: 0,
          namespace: 'hoge'
        },
        expire_in: 1.day
    }
	
	```
3. `--link mysql:db` mysqlの情報をrails上から読み込むためにリンクを設定しています。
	4. ちなみにdatabase.ymlはこんな感じです。(真似してはいけない）

	```
	production:
	  adapter: mysql2
	  database: production_db
	  username: root
	  password: password
	  host: <%= ENV['DB_PORT_3306_TCP_ADDR'] %>
	  port: <%= ENV['DB_PORT_3306_TCP_PORT'] %>
	```
	
* nginx

```
 docker run -d --name nginx --link puma:app -p 80:80 --volumes-from puma nginx:latest
```

1. `puma:app`の記述は、[ここ](http://qiita.com/RyujiKawazoe/items/ade7e1d8039bd78c00c7)に記事を書いたので、良ければ。
2. `--volumes-from puma` これがrailsのディレクトリと連携する部分ですね。


ECSで設定するには
---

先ほどのコマンドで分かるとおり、

* name
* port
* link
* volume

が重要。

linkは以下。

![スクリーンショット 2017-02-07 18.33.59.png](https://qiita-image-store.s3.amazonaws.com/0/18331/5c061852-89f5-f742-0f38-2ad89d465dc5.png "スクリーンショット 2017-02-07 18.33.59.png")

nginxがrailsのディレクトリを見れるようには以下のように。

![スクリーンショット 2017-02-07 18.33.39.png](https://qiita-image-store.s3.amazonaws.com/0/18331/0bdedb11-bb54-5ee5-f920-1630e0568286.png "スクリーンショット 2017-02-07 18.33.39.png")

ポートは以下。

![スクリーンショット 2017-02-07 18.33.27.png](https://qiita-image-store.s3.amazonaws.com/0/18331/d47a9587-0ff7-696c-36f1-b870ea2bad5d.png "スクリーンショット 2017-02-07 18.33.27.png")

なお、今回railsディレクトリをData Volumeとして指定する必要があるわけだが、私はDockerfileで以下を記述しbuildしている。

```
VOLUME "railsのディレクトリパス"
```