開発用のため、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の設定が抜けていました。
解決方法は以下の記事がとても参考になりました。
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の機能に関しては、以下の記事が参考になると思います。
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コマンドで4つのコンテナを立ち上げる場合は
- 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
-
-v "railsのディレクトリ"
volumeを作成するコマンドです。後述のnginxのコマンドで--volumes-from puma
を添えること、ファイルの共有ができるます。 -
--link redis:session_store
redisの情報をrails上から読み込むためにリンクを設定しています。- ちなみに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 }
-
--link mysql:db
mysqlの情報をrails上から読み込むためにリンクを設定しています。- ちなみに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
-
puma:app
の記述は、ここに記事を書いたので、良ければ。 -
--volumes-from puma
これがrailsのディレクトリと連携する部分ですね。
ECSで設定するには
先ほどのコマンドで分かるとおり、
- name
- port
- link
- volume
が重要。
linkは以下。
nginxがrailsのディレクトリを見れるようには以下のように。
ポートは以下。
なお、今回railsディレクトリをData Volumeとして指定する必要があるわけだが、私はDockerfileで以下を記述しbuildしている。
VOLUME "railsのディレクトリパス"