本シリーズ集
タイトル | |
---|---|
0 | 目標・やりたいこと |
1 | AWS編 |
2 | rails開発環境構築編 |
3 | Nginx・MySQL編 |
4 | Capistrano編 |
5 | CircleCI編 |
6 | 総集編 |
##本記事について
第1回~第5回まで全てやってきた結果の『ファイルの内容』・『ディレクトリ構造』(・今後の課題) を、本記事にまとめて、本シリーズ集は終了とする。
#APサーバ
###ディレクトリ構造
/sample
├ .circleci
| └ config.yml
├ Dockerfile
├ Dockerfile_pro
├ docker-compose.yml
├ docker-compose_pro.yml
└ ~ $ rails new / その他gem(bundle)固有のコマンドで生成されたファイル群 ~
####CircleCI関連
`.circleci/config.yml`
version: 2.1
jobs:
build:
docker:
- image: circleci/ruby:2.7.1-node-browsers
steps:
- checkout
- restore_cache:
key: Sample_Cache_{{ checksum "Gemfile.lock" }}
- run:
name: install Gemfile
command: bundle install --path vendor/bundle
- save_cache:
key: Sample_Cache_{{ checksum "Gemfile.lock" }}
paths:
- ./vendor/bundle
test:
docker:
- image: circleci/ruby:2.7.1-node-browsers
environment:
DB_HOST: 127.0.0.1
DB_PASSWORD: root
- image: circleci/mysql:5.7
environment:
MYSQL_USER: root
MYSQL_ROOT_PASSWORD: root
steps:
- checkout
- restore_cache:
key: Sample_Cache_{{ checksum "Gemfile.lock" }}
- run:
name: if do not execute this, an error occurs.
command: yarn install --check-files
- run:
name: Wait for DB
command: dockerize -wait tcp://127.0.0.1:3306 -timeout 120s
- run:
name: setup bundler target path
command: bundle config --local path vendor/bundle
- run:
name: Set up DB
command: |
bundle exec rake db:create
bundle exec rails db:migrate
- run:
name: implement test
command: bundle exec rspec ./spec/
deploy:
docker:
- image: circleci/ruby:2.7.1-node-browsers
steps:
- checkout
- restore_cache:
key: Sample_Cache_{{ checksum "Gemfile.lock" }}
- run:
name: setup bundler target path
command: bundle config --local path vendor/bundle
- run:
name: deploy app by capistrano
command: bundle exec cap production deploy
workflows:
version: 2.1
test-deploy:
jobs:
- build
- test:
requires:
- build
- deploy:
requires:
- test
filters:
branches:
only: master
####Database周り
`config/database.yml`
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV.fetch("DB_USER") { "root" } %>
password: <%= ENV.fetch("DB_PASSWORD") { "password" } %>
host: <%= ENV.fetch("DB_HOST") { "db" } %>
development:
<<: *default
database: app_development
test:
<<: *default
database: app_test
production:
<<: *default
database: app_production
username: root
password: root
host: xx.xx.xx.xx #(APサーバのIPアドレス(ドメイン))
####Capistrano周り
`config/deploy.rb`
lock "~> 3.14.1"
set :application, "sample"
set :repo_url, "git@github.com:{accout}/{repository}"
set :deploy_to, "/home/ec2-user/#{fetch :application}"
set :pty, true
set :keep_releases, 5
set :linked_files, %w[config/master-pro.key config/database-pro.yml]
`config/deploy/production.rb`
set :ip, "xx.xx.xx.xx" # APサーバのIPアドレス
server "#{fetch :ip}",
user: "ec2-user",
roles: %w{app},
ssh_options: {
keys: %w(/path/to/key),
auth_methods: %w(publickey)
}
task :upload do
shared_path = fetch :shared_path
on roles(:app) do
upload! "config/database.yml", "#{shared_path}/config/database-pro.yml" unless test "[ -f #{shared_path}/config/database-pro.yml"
upload! "config/master.key", "#{shared_path}/config/master-pro.key" unless test "[ -f #{shared_path}/config/master-pro.key ]"
end
end
task :deploy => :upload do
release_path = fetch :release_path
on roles(:app) do
execute "cp #{release_path}/config/database-pro.yml #{release_path}/databsae.yml; rm #{release_path}/config/database-pro.yml"
execute "cp #{release_path}/config/master-pro.key #{release_path}/master.key; rm #{release_path}/config/master-pro.key"
execute "sudo service docker start"
container = capture "docker container ls -a -q -f name=test-rails-container"
if container.present?
execute "docker stop test-rails-container"
execute "docker rm test-rails-container"
end
image = capture "docker image ls -q test-rails-image"
if image.present?
execute "docker rmi test-rails-image"
end
execute "docker-compose -f #{release_path}/docker-compose_pro.yml up -d"
end
end
`Dockerfile_pro`
FROM ruby:2.7.1
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y \
build-essential \
nodejs
RUN 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 -y --no-install-recommends yarn
WORKDIR /sample
COPY Gemfile /sample/Gemfile
COPY Gemfile.lock /sample/Gemfile.lock
RUN bundle install --without test development
COPY . /sample
`docker-compose_pro.yml`
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile_pro
image: test-rails-image
container_name: test-rails-container
command: bundle exec rails s -p 3000 -b '0.0.0.0' -e production
ports:
- 3000:3000
`config/deploy/production_web.rb`(追加)
__{application}__ディレクトリ内に__nginx__ ディレクトリを入れて。set :ip, "xx.xx.xx.xx" # WEBサーバのIPアドレス
server "#{fetch :ip}",
user: "ec2-user",
roles: %w{web},
ssh_options: {
keys: %w(/path/to/key),
auth_methods: %w(publickey)
}
task :webtask do
on roles(:web) do
upload! "./nginx" "/home/ec2-user/nginx"
execute "sudo service docker start"
container = capture "docker container ls -a -q -f name=test-nginx-container"
if !container.empty?
execute "docker stop test-nginx-container"
execute "docker rm test-nginx-container"
end
execute "docker run --name test-nginx-container -p 80:80 -d test-nginx"
# あらかじめ
# $ docker build -t test-nginx .
# というコマンドを打っており、『test-nginx』という名前のDockerイメージがある体の設定
end
end
`config/deploy/production_db.rb`(追加)
set :ip, "xx.xx.xx.xx" # DBサーバのIPアドレス
server "#{fetch :ip}",
user: "ec2-user",
roles: %w{db},
ssh_options: {
keys: %w(/path/to/key),
auth_methods: %w(publickey)
}
task :dbtask do
on roles(:db) do
execute "sudo service docker start"
container = capture "docker container ls -a -q -f name=test-db-container"
if !container.empty?
execute "docker stop test-db-container"
execute "docker rm test-db-container"
end
execute "docker run --name test-db-container -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7"
end
end
※注意`環境設定周り`
そのままproduction環境で始めると、エラーが起きてしまうので、`config/environments/production.rb`ファイルを一部書き換える。# config.consider_all_requests_local = false
# => trueにする
config.consider_all_requests_local = true
# config.assets.compile = false
# => trueにする
config.assets.compile = true
Webサーバ
###ディレクトリ構成
/nginx
├ public
| ├ 404.html
| ├ 422.html
| └ 500.html
├ nginx.conf
└ Dockerfile
public ディレクトリ配下は、rails new
コマンドで生成されたものを移植してきたものである。
`nginx.conf`
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
root /public;
error_page 404 /404.html;
error_page 505 502 503 504 /500.html;
location / {
try_files $uri @app;
}
location @app {
proxy_set_header HOST $http_host
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-HOST $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://xx.xx.xx.xx:3000;
}
}
`Dockerfile`
FROM nginx:latest
RUN rm -f /etc/nginx/conf.d/*
COPY ./public /public
COPY nginx.conf /etc/nginx/conf.d/nginx.conf
CMD nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
#DBサーバ
#####DBサーバはネット上のDockerイメージとコマンドのみ
各種コンテナを起動して、通信してみる
ローカル(コンテナ内)で、以下のコマンドを打ち、
$ bundle exec cap production deploy
$ bundle exec cap production_web webtask
$ bundle exec cap production_db dbtask
ブラウザから
『http://xx.xx.xx.xx
』とWebサーバにアクセスすると、、、
できたー!(あんまり見た目はパッとしませんが笑)
※ 少々心配になったので、$ rails g scaffold
コマンドでモデル・ビュー・コントローラを生成してきちんとパスにアクセスしたら表示されることを確認しました。
まとめ
CapistranoやCircleCI・Nginxなど、一から調べながらやったのもあって、このシリーズの記事を書くのに正味10日ぐらいかかりました。笑
実際の開発現場では、セキュリティの強固性を保つために、WEB・AP・DBサーバ(特にAP・DB)へのアクセスを厳格化し、デプロイ時には、webサーバを踏み台とした、web->ap、web->db
等のアクセス手法が取られる(?)と予想できるので、そうした サーバを経由した 方法に対応するデプロイも覚えていきたいと思ってます。
あと今回未実装の部分で、実際の現場でやることといえば、rails db:create(migrate) RAILS_ENV=production
等のコマンドをどう__Capistrano__に組み込むかぐらい?かな?
ちなみに、この記事を書いてて気付いたのですが、Nginxのpublic
フォルダがなくてもエラーのページが開かれました。
もしかしたら、nginxの設定ファイルのroot
は関係なく、rails(puma)
側のpublic
フォルダを参照してるんだと思います。(軽く手を動かして調べました)。
多分ですが、try_files $uri/index.html $uri @railsApp;
の部分に依存しているのかな?
try_files について -> https://tsyama.hatenablog.com/entry/try_files_is_difficult
#最後に
なんだかんだあってここまで来れました!
(各技術の基本的なものは他の方が既に上げているので)ブログみたいな記事になってしまいましたが、本シリーズをご一読してくださった方ありがとうございました!