はじめに
DockerComposeを使うとWebサーバーだけでなくPostgreSQLやRedisといった複数のDockerコンテナを組み合わせたアプリケーションを作成することができます。
DockerComposeで作成したアプリケーションを手元で動かすだけでなく、そのままHerokuにデプロイしてみました。
注意事項
- MacOS Catalinaで検証しています
- HerokuとDockerのアカウントをご用意ください
- 構築するRailsのバージョンは6.0.3、Rubyは2.7.1です
- DatabaseはPostgreSQLを使用します
- DockerのOSイメージはalpineを使用しています。
DockerとDocker Composeのバージョン確認
手元の環境で、DockerとDocker Composeのバージョンを確認します。今回は以下のバージョンでのセットアップを想定します。
$ docker -v
Docker version 19.03.13, build 4484c46d9d
$docker-compose -v
docker-compose version 1.27.4, build 40524192
DockerとHerokuへのログイン
Dockerイメージの取得や、Herokuへのデプロイができるように、あらかじめログインしておきます(HerokuCLIをインストールしてください)。
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: *********
Password: *********
Login Succeeded
$ heroku login
Enter your Heroku credentials:
Email: ************
Password: ********
Two-factor code: ******
Logged in as **********
作業場所と必要なファイルの準備
作業ディレクトリを用意します。今回はmyappとしました。
$ mkdir myapp && cd $_
Gitでバージョン管理を行う場合は git init
しておきましょう。(やらなくてもいいです)
$ git init
必要なファイルを空の状態で用意します。
$ touch Dockerfile docker-compose.yml Gemfile Gemfile.lock
用意したファイルの中身を記述していきます。
Dockerfileは以下のようにします。(myapp
は任意のアプリケーション名で置換してください)
FROM ruby:2.7.1-alpine
ENV PACKAGES="build-base linux-headers libxml2-dev libxslt-dev curl-dev nodejs tzdata postgresql-dev postgresql yarn less" \
HOME="/app"
WORKDIR $HOME
ADD Gemfile $HOME/Gemfile
ADD Gemfile.lock $HOME/Gemfile.lock
RUN apk update && \
apk upgrade && \
apk add --no-cache $PACKAGES && \
bundle install -j4
ADD . $HOME
CMD ["rails", "server", "-b", "0.0.0.0"]
続いて、docker-compose.ymlを編集します。
version: '3'
services:
db:
image: postgres:13.0
environment:
- POSTGRES_PASSWORD=password
volumes:
- db_data:/var/lib/postgresql/data # dbのデータを永続化します。無くても動きます。
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
ports:
- "3000:3000"
depends_on:
- db
volumes:
db_data:
続いて、Gemfileを編集します。
source 'https://rubygems.org'
gem 'rails', '6.0.3'
これで、Docker上でRailsアプリを動かす準備が整いました。
Railsアプリケーションを作成する
Railsアプリを作成します。 docker-compose run web xxx
は、 web
というDockerコンテナで xxx コマンドを実行する、という意味です。
$ docker-compose run web rails new . --force --database=postgresql
Docker上でRailsを起動する
PostgresのDockerコンテナと接続するために config/database.yml
を編集します。
default: &default
adapter: postgresql
encoding: unicode
host: db # 追記
username: postgres # 追記
password: password # 追記
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
Dockerコンテナをビルドします。このアプリケーションに必要なDockerイメージ(Ruby, PostgereSQL)のダウンロードも行われます。
$ docker-compose build
データベースを作成します。
$ docker-compose run web rails db:create
アプリケーションを起動します。Webサーバーが起動します。
$ docker-compose up
ブラウザで、localhost:3000 に移動して確認しましょう。以下のページが表示されれば、ひとまずローカルでのアプリケーション起動は成功です!
Herokuへデプロイする
作成したRailsアプリをHerokuにデプロイします。
ローカルでWebサーバーが動作している(pidsが存在する)と、herokuでWebサーバーが起動しない可能性があるので、一旦ローカルのサーバーを停止しておきます。また server.pid
が存在する場合は消しておきます。
$ docker-compose down
$ rm tmp/pids/server.pid
Herokuのホスト名を許可しておきます。 (今回の場合Rails.envはdevelopmentになります)
config.hosts << ".herokuapp.com" # 追記
Herokuにアプリケーションを作成します。
$ heroku create
Heroku Container Registryにimageをアップロードするためにログインし、その後コンテナをpushします。
$heroku container:login
$ heroku container:push web
今回はDBにPostgreSQLを使用しているので、add-onを追加します。
$ heroku addons:create heroku-postgresql:hobby-dev
pushしたアプリケーションをリリースします。
$ heroku container:release web
以上で完了です! 以下のコマンドで公開されたアプリケーションが確認できます。
$ heroku open
成果物
最終的なコードをこちらに置きました。
https://github.com/akirakudo/heroku-docker-rails6