0
1

More than 1 year has passed since last update.

[Rails6] Capistrano+docker-composeを使用してデプロイ を自動化する。

Posted at

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を使用しての自動デプロイを実装していきたいと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1