🪂

【初学者向け】Dockerの環境構築からFly.ioへのデプロイまで

2023/12/08に公開1

背景

11月からCOUNTERWORKSに入社しました、キタデと申します。
現在、新卒研修の一環としてアプリケーションを作成しています。
自分でDockerを使った仮想環境を構築した経験がなかったので、良い機会だと思い挑戦させていただきました。
Docker環境の構築からFly.ioへのデプロイまでの手順をまとめました。
この記事がどなたかの助けになれば幸いです。

実装

今回はRuby on Rails (以下Rails)のAPIモードのプロジェクトを作成し、Fly.ioにデプロイしていきます。
バージョン情報は以下の通りです。

  • Docker Engine : 24.0.6
  • docker-compose : 2.23.0
  • Ruby : 3.2.2
  • Rails : 7.1.2

Docker環境構築

1.必要ファイルの作成

作業ディレクトリを作成し

  • Dockerfile
  • docker-compose.yml
  • Gemfile
  • Gemfile.lock
  • entrypoint.sh

を作成します。内容は下記になります。

Dockerfile
Dockerfile
#ベースイメージの指定
FROM ruby:3.2.2

#環境変数
ENV TZ Asia/Tokyo
ENV LANG ja_JP.UTF-8
ENV LC_ALL C.UTF-8
ENV EDITOR=vim

#dbにpostgreSQLを使用するので対象のパッケージをインストール
RUN apt-get update && apt-get install -y postgresql-client vim

#appディレクトリを作成
RUN mkdir /app
#コマンドを実行するディレクトリを/appに指定
WORKDIR /app

#ローカルのGemfileとGemfile.lockをコンテナ内にコピー
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

#bundle installを実行
RUN bundle install

#ローカルの現在のディレクトリをコンテナ内にコピー
COPY . /app

#後述のentrypoint.shを実行するための記述
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

#コンテナがリッスンするPORTを指定
EXPOSE 3000

#コンテナ作成時にサーバーを立てる
CMD ["rails", "server", "-b", "0.0.0.0"]

各記述の詳細はDockerfileリファレンスを参考にしてください。

docker-compose.yml
docker-compose.yml
services:
  web:
    build: . #現在のディレクトリのDockerfileを指定
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on: #先にdbから起動させる
      - db
    tty: true
    stdin_open: true
  db:
    image: postgres:16
    volumes:
      - db-store:/var/lib/postgresql/data # データを永続化するための設定
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      TZ: 'Asia/Tokyo'
    ports:
      - "5432:5432"
    restart: always
volumes:
  db-store:
Gemfile
Gemfile
source 'https://rubygems.org'
gem 'rails','7.1.2'

railsの記述のみで大丈夫です。今回は実装時の最新安定版の7.1.2を指定しました。

Gemfile.lock
Gemfile.lock

Gemfile.lockには何も記述しなくて大丈夫です。

entrypoint.sh
entrypoint.sh
#!/bin/sh
set -e
rm -f /app/tmp/pids/server.pid
exec "$@"

こちらはエントリーポイントの実行スクリプトです。 これはサーバー内にserver.pidというファイルが先に存在していたときに、サーバーが再起動できなくなるRails特有の問題を回避するためのものです。コンテナが起動されるたびに実行されます。
https://matsuand.github.io/docs.docker.jp.onthefly/samples/rails/

以降、実行するコマンドは作業ディレクトリ直下で実行しています。

2.Railsプロジェクトの作成

Railsプロジェクトを作成します。

$ docker-compose run web bundle exec rails new . --force --database=postgresql --api --skip-bundle --skip-docker

. : 現在のディレクトリにプロジェクト作成
--force : ファイルを上書きして作成
--database=postgresql : DBをpostgreSQLに指定
--api : APIモードで作成
--skip-bundle : bundle installを実行しない
--skip-docker : Docker関連のファイルを作成しない

3.環境変数の設定

gem "dotenv-rails"を追加します。

Gemfile
source "https://rubygems.org"

ruby "3.2.2"

gem "rails", "~> 7.1.2"

gem "pg", "~> 1.1"

gem "puma", ">= 5.0"

gem "tzinfo-data", platforms: %i[ windows jruby ]

gem "bootsnap", require: false

+ gem "dotenv-rails"

group :development, :test do
  gem "debug", platforms: %i[ mri windows ]
end

.envファイルを作成し、環境変数を追加します。

.env
DB_USERNAME = "postgres"
DB_PASSWORD = "password"
DB_HOST = "db"
DB_PORT = "5432"

4.DBの作成

3で設定した環境変数を用いて以下のようにdatabase.ymlを設定します。

database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+ username: <%= ENV.fetch('DB_USERNAME') %>
+ password: <%= ENV.fetch('DB_PASSWORD') %>
+ host: <%= ENV.fetch('DB_HOST') %>
+ port: <%= ENV.fetch('DB_PORT') %>

コンテナを立ち上げます。

$ docker-compose up --build -d

--build : サービス起動前にイメージをビルド
-d : デタッチモード。サービスをバックグラウンドで実行

次にDBを作成します。

$ docker-compose exec web rails db:create

5.ブラウザで確認(http://localhost:3000/)


無事Railsの立ち上げ画面が表示されました。
Dockerを使用してローカルでの環境構築ができました。

Fly.ioへのデプロイ

上記で作成したアプリケーションをFly.ioにデプロイしていきます。

1.CLIのインストール

Homebrew経由でflyのCLIをインストールします。

$ brew install flyctl

ログインします。(登録がまだの方は先にそちらを行ってください)

$ fly auth login

上記コマンドを打つとブラウザが開きます。

登録しているメールアドレスであることを確認して認証してください。
認証するとfly launch等のコマンドが使用可能になります。

2.デプロイ準備 : fly launch

launchコマンドでfly.tomlなどのデプロイに必要なファイルが生成されます。

$ fly launch --dockerfile .

上記コマンドを入力すると、ブラウザが立ち上がり、以下のような設定画面に飛びます。

この画面で各種設定を行います。

  • Basics : アプリケーションの名前を設定します。Organizationを指定することもできるみたいです。
  • Region : VMのリージョンを指定します。近いのでTokyoにしました。
  • Services : Port番号を指定できます。3000番に指定。
  • Memory & CPU : VMのサイズ、メモリの大きさ等を指定します。詳しくはこちらを参照して下さい
  • Database : DBを指定します。今回はPostgresを使用します。DBのマシン名や容量等もここで指定します。
  • Redis : Redisを使用するかどうかを指定します。

3.デプロイ : fly deploy

下記コマンドでデプロイします。

$ fly deploy

ヘルスチェックが通ったらデプロイされます。

Blocked hostsエラーについて

development環境でデプロイしている場合、BlockedHostsというエラーが出ることがあります

こちらはDNSリバインディング攻撃を防止する ActionDispatch::HostAuthorizationに由来するエラーのようで、Rails6系から導入されています。
https://github.com/rails/rails/pull/33145
development.rbconfig.hosts << "[host名]"の記述を追加することで回避できるようです。

config/environments/development.rb
Rails.application.configure do

+ config.hosts << "sample-app-1.fly.dev"
 
end

productiontest環境ではHostヘッダのチェックは行われないようです。

4.環境変数の設定

Fly.ioのダッシュボードから設定することもできますが、今回はCLIで設定します。

$ fly secrets set DB_USERNAME=postgres
$ fly secrets set DB_PASSWORD=password
$ fly secrets set DB_HOST=db
$ fly secrets set DB_PORT=5432

5.ブラウザで確認

無事デプロイされているのを確認できました。

参考記事

https://blog.pentagon.tokyo/3544/
https://qiita.com/Yusuke_Hoirta/items/3a50d066af3bafbb8641
https://weseek.co.jp/tech/680/

We are hiring!!

COUNTERWORKS では一緒に働く仲間を絶賛募集中です。
今後の更なる成長のためには圧倒的に仲間が不足しています。皆さまのご応募お待ちしております!
https://counterworks.co.jp/recruit/?utm_source=zenn&utm_medium=referral&utm_campaign=advent-calendar-2023&utm_content=8

COUNTERWORKS テックブログ

Discussion

TakutoTakuto

この記事を頼りに進めていき、無事にデプロイすることができました!
renderやheroku等、試してみましたが、私の開発環境が悪いのか、デプロイに苦戦し、挫折しかけていました。どうしてもお礼が言いたくコメント差し上げた次第です。
本当にありがとうございました!