docker-composeを使用してnginxとRailsコンテナを用意して、AWSにデプロイをしています。現在はSSH接続して、いちいち起動しています。
なので、Capistranoを使用して、自動デプロイを行えるようにしていきたいと思います。
##docker-compose.production.yml
version: '3.7'
services:
web:
build:
context: .
dockerfile: Dockerfile.production
volumes:
- .:/date_course # カレントディレクトリを/date_courseにバインドマウントしている
- public-data:/date_course/public
- tmp-data:/date_course/tmp
- log-data:/date_course/log
ports:
- "3000:3000"
command: bash -c "bundle exec puma -C config/puma.rb -e production"
nginx:
build:
context: containers/nginx
volumes:
- public-data:/date_course/public
- tmp-data:/date_course/tmp
ports:
- 80:80
depends_on:
- web
volumes:
public-data:
tmp-data:
log-data:
##Dockerfile.production
FROM ruby:2.7.2
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \
&& 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 -qq \
&& apt-get install -y nodejs yarn --no-install-recommends && rm -rf /var/lib/apt/lists/*
#WORKDIRは指定するディレクトリがもし存在しない場合は作成してくれる。そのためRUN mkdir /date_courseを省略
WORKDIR /date_course
COPY Gemfile /date_course/Gemfile
COPY Gemfile.lock /date_course/Gemfile.lock
RUN gem install bundler
RUN bundle install
COPY . /date_course
RUN mkdir -p tmp/sockets
RUN mkdir -p tmp/pids
データベースはAWSのサービスであるRDSのmysqlを実装しています。
ここからはCapistranoの設定を行います。
###Gem追加
gem 'capistrano', '~> 3.15'
Gemの追加はこれだけになります。
直接Railsやnginxを動く際はGemをさらに追加する必要がありますが、
このアプリケーションではdocker-composeを動かせばいいのでこれだけで充分です。
$ bundle install
$ bundle exec cap install
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified
###Capfile設定
特になにもいじりません。
なにも編集しない理由は
Dockerを動かせばrailsもnginxも動くからです。
###config/deploy/production.rb
server '××.××.×××.×××', user: 'ec2-user', roles: %w{web}
serverのElasticIPを設定します。
ElasticIPをAWSで関連づけすることに注意してください。
そうしなければIPアドレスが変わってしまうので
###config/deploy.rb
# config valid for current version and patch releases of Capistrano
lock "~> 3.16.0"
set :application, "date-course" #アプリケーション名
set :repo_url, "https://github.com/daisuke-harada/date-course.git" # githubのurl
set :deploy_to, "/home/ec2-user/date-course" # applicationをdeployする場所
set :docker_compose_path, "docker-compose -f docker-compose.production.yml"
set :RAILS_ENV, "RAILS_ENV=production"
namespace :deploy do
application = fetch :application
docker_compose_path = fetch :docker_compose_path
rails_env = fetch :RAILS_ENV
rails_compile = "#{docker_compose_path} run web rails assets:precompile #{rails_env}"
db_drop = "#{docker_compose_path} exec -T web rails db:drop #{rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1"
db_migrate = "#{docker_compose_path} exec -T web rails db:migrate #{rails_env}"
db_create = "#{docker_compose_path} exec -T web rails db:create #{rails_env}"
db_seed = "#{docker_compose_path} exec -T web rails db:seed #{rails_env}"
task :application_update do
on roles(:web) do # config/deploy/production.rbのroles: %w{web}を指定している。
execute "cd #{application};" "git pull origin master"
end
end
task :build do
on roles(:web) do
execute "cd #{application};" "#{docker_compose_path} build"
end
end
task :application_compile do
on roles(:web) do
execute "cd #{application};" "#{rails_compile}"
end
end
task :up_containers do
on roles(:web) do
execute "cd #{application};" "#{docker_compose_path} up -d"
end
end
task :database_create do
on roles(:web) do
execute "cd #{application};" "#{db_create}"
end
end
task :database_set_up do
on roles(:web) do
execute "cd #{application};" "#{db_create};" "#{db_migrate};" "#{db_seed};"
end
end
task :database_reset do
on roles(:web) do
execute "cd #{application};" "#{db_drop};" "#{db_create};" "#{db_migrate};" "#{db_seed};"
end
end
task :down_containers do
on roles(:web) do
execute "cd #{application};" "#{docker_compose_path} down"
end
end
task :destroy_images do
on roles(:web) do
execute "cd #{application};" "docker rmi -f `docker images -q`"
end
end
task :application_set_up do
on roles(:web) do
execute "cd #{application};" "git pull origin master;" "#{docker_compose_path} down;" "docker rmi -f `docker images -q`"
execute "cd #{application};" "#{docker_compose_path} build;" "#{rails_compile};" "#{docker_compose_path} up -d"
end
end
end
実行する際は、例えばapplication_set_upのtaskを実行する際は、
bundle exec cap production deploy:application_set_up
で実行します。bundle exec cap production の後に名前スペース名:task名で実行できます。
さらにconfig/deploy.rbないのコードから気になる部分を解説します。
set :docker_compose_path, "docker-compose -f docker-compose.production.yml"
set :RAILS_ENV, "RAILS_ENV=production"
setで指定したものはfetchで展開できます。
docker_compose_path = fetch :docker_compose_path
rails_env = fetch :RAILS_ENV
taskを解説します。
task :application_update do
on roles(:web) do # config/deploy/production.rbのroles: %w{web}を指定している。
execute "cd #{application};" "git pull origin master"
end
end
on roles(:web) do ...endは先ほどconfig/deploy/production.rbで指定したserver '××.××.×××.×××', user: 'ec2-user', roles: %w{web}のサーバーを指定しています。
executeは実行するコマンドを指定しています。
まとめるとこのtaskはIPアドレス'××.××.×××.×××'のサーバー内でAWSuserのec2-userの実行権限を持ってcdコマンドを実行しアプリケーション内に移動します。その後、git pull origin masterを実行します。
###まとめ
Docker、docker-composeを実装していたため、capistaranoの設定が少なく済みました。
次回はGitHubActionsを使用しての自動デプロイを実装していきたいと思います。