Skip to content

Instantly share code, notes, and snippets.

@yano3nora
Last active November 28, 2021 14:13
Show Gist options
  • Select an option

  • Save yano3nora/cf33d4fe3367507a4cefde02d95048e8 to your computer and use it in GitHub Desktop.

Select an option

Save yano3nora/cf33d4fe3367507a4cefde02d95048e8 to your computer and use it in GitHub Desktop.
[dev: Heroku] Cloud PaaS for application with faster build & deploy. #heroku #dev

OVERVIEW

Heroku: クラウド・アプリケーション・プラットフォーム

Salesforce 社が運営する PaaS でアプリケーション開発のサポート具合が半端ない。高速なビルド & デプロイが可能でインフラのことを気にしないでガシガシコードをデプロイできる。Git や Docker など開発ツールとの連携も進んでおり、開発者がアプリケーションとデータのことだけに集中できるのが売り。

The Twelve-Factor App

12factor.net/ja
とにかく分かりづらいTwelve-Factor Appの解説を試みる

Heroku は The Twelve Factors というクラウドプラットフォームで開発・提供されるアプリケーションのベストプラクティスを提唱しており、サービスはこの基本原則に則って構成されている。一読しておくこと。

Dyno

Dynos - devcenter.heroku.com
Dynos and the Dyno Manager - devcenter.heroku.com

Heroku は実行リソースを Dyno という独自の単位で取り扱っている。開発者はこの Dyno を利用してアプリを実行し、Dyno 利用分の課金がされていくという仕組み。内部的にはコンテナ技術によって仮想化されたプロセスらしく、負荷に応じて個数をスケールアウト可能。

また Dyno には Web Dyno ( WEB アプリ稼働時間 ) と Worker Dyno ( 長時間かかるバックエンド処理など ) と One-Off Dyno ( $ heroku run によるコマンド実行など ) の 3 種類あり、通常 1 アプリにつき最低 1 つの Web Dyno を用意し、30 秒以上かかるようなバックエンド処理 ( Web Dyno は WEB リクエスト用のリソースなので重い処理 / 長時間かかる処理に向かない ) などは Worker Dyno を用意してアプリを構成する。

Restart & Shutdown

Dynos > Restarting
Dynos > Shutdown

Heroku の Dyno は以下の条件で再起動されることを念頭におくこと。( 当然そのほかクラウドサービスの VM も「開発側が意図しない再起動」を念頭において構成するべきなのだが ... )

  • 24 h 前後経過した際の日時の再起動
    • 正確には 24 h + 0 ~ 216 m の周期なので毎日ずれる
    • 複数の Dyno でスケーリングしている場合はそれらが被らないようランダムにしているらしい
    • この日次を含めた全ての再起動完了後は 24 h サイクルがリセットされる
  • 何らかの Heroku 要因による逐次の再起動
    • ハードウェア障害などによるリソースのアドレス移動など
  • 開発者によるリリース・環境変数などの設定変更・アドオンの変更時の再起動

再起動時には、立ち上がっている全プロセスに対して SIGTERM が送信される決まり。その後しばらくして SIGKILL でまだ生きてるヤツを全員殺しにかかる流れ。再起動は数十秒から長くても数分程度で完了するよう。

Web Dyno は heroku ps:scale web=2 のように 2 Dyno で冗長構成しておけば、適当にセッション周りの共通化やリクエストの振り分けを行ってくれるのであまり意識することはないかもしれない。

対して Worker Dyno の再起動についてはもう少し慎重に構成を考える必要がある。通常 Worker サービスで行うような処理は、24 時間 365 日稼働している環境を理想とすることが多い。しかし前述したように どのようなプラットフォームであれ、100 % の可用性は実現できないため、何らかの「システムダウン対策」をとる必要がある。 具体的に Celery などでジョブのキューイングを行っている場合、再起動時にプロセスが SIGTERM → SIGKILL で強制終了され、その際のタスクは REVOKE されてしまう ( 場合によっては REVOKE が間に合わずタスクそのものが失われることもある ) 。

対策として、以下のようなジョブの実装 & 構成を考慮しつつ、Worker Dyno の冗長化を合わせて行うのがよろしい。

Celery のプロセス異常終了と立ち向かいたい
Celery > Management Of Shutting Down

# Worker プロセスのログ確認は以下で取得可能
# https://devcenter.heroku.com/articles/python-rq#troubleshooting

$ heroku logs -p worker

# 例えばログからエラーっぽいのだけみたいなら ...
$ heroku logs | grep -i error

Preboot

Preboot - devcenter.heroku.com
Heroku の Preboot 機能を深掘りした

プリブートは、Web dyno の標準 dyno 開始動作を変更します。新しいものを開始する前に既存のWeb dynoのセットを停止する代わりに、プレブートは、既存のWeb dynoが終了する前に新しいWeb dynoが開始されるようにします(そしてトラフィックを受信します)。これは、ダウンタイムゼロの展開に貢献できます。

Comparison of AWS

Heroku を採用する利点として、Docker 開発からのステージング → スタートアップ程度なら他プラットフォームに比べて割安&手軽にスタートできる点があげられる。小規模サービスならそこからのスケーリングで十分対応可能。但しリソースのスペック費用対効果でいうと AWS に比べ割高なので、最初からある程度予算が確保されていて、複雑な構成・潤沢なリソースの利用・柔軟なスケールなどが求められる場合は Amazon ECS などを検討するべき。

Heroku x Rails のサービスを本番運用する際に確認したいこと

上記記事を参考に「本番環境のベース構成」を考えるとざっとこんな感じで月 15k くらいか。

Heroku Standard 1X Dyno * 2 ~ ( Web Dyno 用 $50 ~ / month )
Heroku Standard 1X Dyno * 1 ( Worker Dyno 用 $25 / month )
Heroku Postgres Standard 0 ( $50 / month )
Heroku Redis Premium 0 ( $15 / month )

費用感として Heroku は 5k ~ 15k ちょい程度の月額でスタートアップ ~ 小規模までスケールできる。中規模以上だと 数万 ~ 数十数万 ... といった感じ。単純なスペックで考えると割高感があるが、モニタリングやスケールなど管理の容易性を考慮すると、大規模かつ複雑な構成にしない限りは AWS に十分張り合える印象。

Heroku に比べると AWS は CPU やメモリなどスペックの費用対効果は安いが、データ転送量の課金などが複雑でコストが予想し辛い。反面、構成のバリエーションが豊富なので VPC やクラスタ構成などの柔軟性は分配があがる。

また、それなりの規模のシステムを DevOps 両面で面倒見るようなケースでは、Amazon ECS の Fargate x EKS ( Kubernetes ) で組んだ方が料金の調整も聞き、サービス全体の管理もしやすそう。

Heroku toolbelt

The Heroku CLI - devcenter.heroku.com
Heroku コマンド集

Heroku 新規アカウントを作成したら、Heroku 開発用 CLI をダウンロードしてマシンに導入する。Heroku ではアプリ開発をこの CLI を通して行い、ビルド・デプロイやプラグイン設定などを WEB サイトのダッシュボードから行う流れになる。各言語ごとに「どんなふうにしたらビルド/デプロイできるの?」っていうのは以下公式マニュアルを参照。

Get Started - 各言語毎のビルド/デプロイ方法

# インストール
$ brew tap heroku/brew && brew install heroku

# 導入時
$ heroku            # 初回のみこのコマンドでビルドが必要
$ heroku --version  # 動作確認
$ heroku login      # 初回のみログインが必要

# 稼働中のアプリ確認
$ heroku ps -a ${APP_NAME}

# 開発 → アプリ作成
$ mkdir my_app
$ cd my_app
$ git init
$ touch index.html
$ git add .
$ git commit -m "Init my_app onto heroku git repo."

$ heroku create my-app
> Creating app... done, stack is cedar-14
> https://xxxxxxxxxx.herokuapp.com/ | https://git.heroku.com/xxxxxxxxxx.git

# 環境変数のセット
$ heroku config                      # list
$ heroku config:get ENV_VAR          # get
$ heroku config:set ENV_VAR="value"  # set
$ heroku config:unset ENV_VAR        # remove

# アプリのデプロイ
$ git push heroku master
$ heroku open my-app

# 削除
$ heroku apps:destroy --app my-app

# コマンド実行
$ heroku run <command>
$ heroku run bash  # 料金注意

# Dyno 操作
$ heroku ps
$ heroku ps:scale worker=2
$ heroku ps:restart
$ heroku ps:restart web.1

-a option

Push したりした直後はスキップできるっぽいが、基本的に各種 heroku コマンドは -a オプションでアプリ名を指定してあげる。

$ heroku logs --tail -a my-app

Heroku Dashboard

GUI ( Heroku 管理画面 ) からはもアプリケーションの様々な設定が可能。

  • Overview: アプリのアクティビティや課金状態の概要
  • Resources: アドオン設定?
  • Deploy: デプロイ時の pipeline ( ビルド > デプロイ > リリースの CI 動線 ) や GitHub 連携
  • Metrics: アプリ稼働状況などの確認
  • Activity: アクティビティ / GitHub 連携でコード差分とか見れるみたい
  • Access: アプリの Collaborators ( 共同開発者 ) 管理
  • Settings: 環境変数 / ドメイン / buildpack / メンテモードなど

Free Dyno Usage

Heroku にはアカウント毎に毎月 1000 dyno/h 程度の無料利用枠がある。利用量が 100 % に近づくとアラートメールを飛ばしてくれる ... らしい。

管理画面のユーザアカウント Account settings より Manage Account > Billing と進み Free Dyno Usage 項目から現在の利用量を確認できる。

Domain settings

Herokuで独自ドメインを割り当てる(お名前.com)
Herokuに独自ドメインのSSL接続を無料で導入できるようになった話(有料Dynoのみ)
お名前.comで購入したドメインをHerokuに設定する

Heroku Point DNS アドオンで ルートドメインなど高度な解決を行う場合は Point DNS add-on の項を参照

  1. お名前.com でドメイン取得
  2. Heroku のアプリ Dashboard > Settings > Domains and certificates でドメイン追加
    • www.example.com などを追加 ( www 必須かな? )
    • DNS Target の xxx.herokudns.com をメモ
  3. お名前.com の DNS レコード設定より以下を追加
    • HOST: www
    • TYPE: CNAME
    • TTL: 3600
    • VALUE: xxx.herokudns.com ( DNS Target )
    • 状態: 有効
  4. Heroku の Configure SSL → Automatically で HTTPS 対応
  5. 数分 ~ 数時間待つと Heroku DNS とお名前.com DNS 間の名前解決が浸透する

DEPLOYING WITH DOCKER

Deploying with Docker
Container Registry & Runtime (Docker Deploys)

2017 年 9 月より Docker ベースのデプロイサービス Container Registry が正式リリースされた。これまでは Docker で構築したサービスを Heroku buildpack サービスを経由してデプロイ ... という流れだったが、これにより本番環境で Docker コンテナの運用が可能になった。但し docker-compose などオーケストレーションは利用できないので、複数コンテナの展開の際は Dockerfile を工夫する必要がる。 また docker-compose.yml は当然解釈されないため「開発用」と割り切る必要がある。

また前提として ... ローカル環境で docker コマンドによってビルドしたコンテナを、Heroku 上のコンテナホスティングサービスへ Push して、リリースの際にコンテナプロセスを実行 ( = CMD 実行 ) したものを、Heroku のアプリとして動かす という建付けになっている。

加えて、当然だが「ビルドしてコンテナを生成」したタイミングで、Git 管理かどうか?とは無関係に Dockerfile が存在するアプリルート ( コンテナルート? ) 以下全て ( 厳密には Dockerfile 内で COPY . /app などしたファイル群が ) コンテナイメージとして固まるため、Git 管理していないであろう .env / bundle.js / style.css なども全て、実行時のプロセス上には存在している。よって Push → Release する前にフロントエンド類は全てプロダクション向けにビルドし、.env などは初期化しておくのが望ましい。

Heroku にデプロイする以上コンテナ間のリンクが使えないので、web コンテナに WEB サーバとアプリサーバ両方詰め込んで ... という構成が楽。

いつからか push & release 直後に更新が反映されず heroku dyno:restart してちょっと待ってから更新されるようになってる気がする。。。。

# Login Heroku & Heroku Container Registry.
$ heroku login
$ heroku auth:token
> xxxx-xxxx-xxxx-xxxx
$ docker login registry.heroku.com
> Username: heroku-user-name
> Password: xxxx-xxxx-xxxx-xxxx

# Create app onto heroku at first deploy.
$ heroku create my-app
$ heroku addons:create heroku-postgresql:hobby-dev  # Heroku Postgres
$ heroku addons:create sendgrid:starter             # SendGrid
$ heroku addons:add scheduler:standard              # Heroku Scheduler

# Setting environment variables.
# @see     .env.development
# @see     https://dashboard.heroku.com/apps/my-app/settings
# @exapmle $ heroku config:set RAILS_ENV=production
#          $ heroku config:set RAILS_MASTER_KEY=xxxxxxxxxx
#          $ heroku config:set DATABASE_URL=xxxxxxxxxxxxxx
$ cp .env.development .env  # Generate dummy .env file for production.

# Compile back/front-end files before container building.
$ npm run build

# Push & Release Container onto Heroku Container Registry.
$ heroku container:push web --arg RAILS_ENV=production,DOMAIN=${APP_DOMAIN}
$ heroku container:release web

# Reset & Migrate Database ( If you need ).
# @see https://dashboard.heroku.com/apps/my-app/settings
$ heroku pg:reset DATABASE_URL
$ heroku run rake db:migrate
$ heroku run rake db:seed

# Reset Dynos.
$ heroku ps:restart

Workflow

1. Login to registry.heroku.com

Issues / docker login exited with 1 #45 - heroku/heroku-container-registry

初回のみ Heroku の Container Registry ( Heroku 内の Docker Hub 的なサービス ) にログインする必要がある。コンテナホスティングサービスへのログインは内部的に docker コマンドを利用するため Windows 環境下では予め $ docker-machine start で Docker ホストを立ち上げておくこと。 また Windows x Docker Toolbox 環境だと Heroku 提供のログインコマンドでコケるため $ docker login 直打ちする必要あり。

# heroku login 済みで以下
$ heroku container:login

# もしも上記でエラーだったら ...
$ heroku auth:token
> xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx

$ docker login registry.heroku.com
> Username: ${HEROKU_USER_NAME}
> Password: ${heroku auth:token}

2. Create container app

既に Docker コンテナがローカルでデプロイできている前提。通常の Heroku アプリ作成と同じ。

$ git add .
$ git commit -m "init"
$ heroku create my-app

# 任意でアドオン ( ミドルウェアみたいなやつ ) をインストール
# https://elements.heroku.com/addons
$ heroku addons:create heroku-postgresql:hobby-dev  # Heroku Postgres
$ heroku addons:create sendgrid:starter             # SendGrid
$ heroku addons:add scheduler:standard              # Heroku Scheduler

# 本番環境用の環境変数をセット
$ heroku config:set RAILS_ENV=production
$ heroku config:set RAILS_MASTER_KEY=xxxxx  # @see config/master.key
$ heroku config:set DATABASE_URL=xxxxxxxxx

このあとコンテナを Heroku がホストする Contianer Registry へ Push & Release するが、その際にコンテナがローカルで docker build されて、リリース後に Dockerfile 末尾 CMD が実行される。このため Dockerfile には各コンテナのビルド時コマンドを必ず記載しておく必要がある

# Rails を立ち上げる Dockerfile の例
FROM    ruby:2.5.3
RUN     apt-get update -qq && \
        apt-get install -y build-essential libpq-dev nodejs

# Build rails.
RUN     mkdir /app
COPY    Gemfile /app/Gemfile
COPY    Gemfile.lock /app/Gemfile.lock
WORKDIR /app
RUN     bundle install
COPY    . /app

CMD     ["rails", "server", "-b", "0.0.0.0"]  # Release 時に実行

3. Push and release container

Heroku Container - heroku/cli

作成した Heroku アプリは $ heroku container:command <process-type> 形式のコマンドで、手順 1 で作成した Heroku Container Registry 上に Push したりリリース ( デプロイ? ) したりできる。Docker コンテナは通常何らかの「サービス」が「プロセス」としてサーバ上で常駐するため、Heroku ではこれを <process-type> というラベルを付けて管理する ( web が最低限必要なサービスみたい ) 。docker-compose のサービス名と同じように考えて間違いないぽい。

# Rails が .env を吸い上げるなら修正しておく
$ vi .env

# フロントエンド系ファイルは production 向けにビルドしておく
$ webpack --mode production

# 単体コンテナを Push & Release
$ heroku container:push web     # コンテナイメージをビルド
$ heroku container:release web  # コンテナイメージを実行

# その他コマンド
$ heroku help container
> container:login    log in to Heroku Container Registry
> container:logout   log out from Heroku Container Registry
> container:pull     pulls an image from an app process type
> container:push     builds, then pushes Docker images to deploy your app
> container:release  Releases previously pushed Docker images to your app
> container:rm       remove the process type from your app
> container:run      builds, then runs the docker image locally
Passing environment variables on building.

container:push - heroku/cli
Docker env vars + Heroku; Heroku requires ENV while local build requires ARG

開発で Docker-Compose を利用している状況では、Dockerfile のビルド時の環境変数 Docker-Compose ちゃんが .env から吸い上げて Dockerfile に渡してくれるが、Heroku に Push する際は Docker-Compose なしでビルドする関係で「Dockerfile の中で利用する環境変数は container:push のタイミングで渡してあげる」必要があります。

# コンテナビルド時の引数を渡す
$ heroku container:push web --arg RAILS_ENV=production,DOMAIN=www.example.com

また、Rails に dotenv-rails みたいな .env 読み上げ環境変数ぶち込み gem を入れたりしていると、環境変数が Heroku でセットしたものと競合する可能性があるので注意。( 基本的に Heroku 側が優先されるので大丈夫っぽいけど ... 後追いでぶち込むのかな )

Rails x Puma x nginx

nginx: For heroku - gist
docker: Deploy rails x puma x nginx to heroku

Rails アプリを Puma で動作させ nginx を前段にかました構成でハマった。

Push and release multiple containers.

複数のイメージを push するには

複数コンテナ構成のサービスをまとめて Push → リリースする場合は --recursive が使える。

$ tree
> web/
>   Dockerfile.web
> db/
>   Dockerfile.db 
$ heroku container:push --recursive
$ heroku container:release

4. Execute commands to deploy app on container

リリースしてアクセスできる状態になったら heroku run ${COMMAND} でコンテナで一時コマンドの実行が可能になるので、マイグレーションなどを実行していく ... DB に Heroku Postgres を利用している場合は既に DB は存在するので db:create は不要 ( というか権限がないので新規 DB は作成できない ) 。

# Rails アプリならこんな感じでマイグレーション
$ heroku run rake db:migrate
$ heroku run rake db:seed

# bash を立ち上げて作業とかも一応可能
# 但し one-off プロセスとして時間が課金対象なので
# 接続しっぱなしにすると料金が発生するので注意
$ heroku run bash

# Heroku ログの確認
$ heroku logs --tail

5. Settings for Heroku

plataformatec/devise > Additional Informations > Heroku
HerokuでRailsをデプロイしたら、Devise.secret_key was not set
Rails5.2からsecrets.ymlが廃止されcredentials.yml.encに統合されるよ
Rails5.2から追加された credentials.yml.enc のキホン
RailsアプリをHerokuへデプロイするときの手順まとめ

Rails の production モードの RAILS_MASTER_KEY 環境変数設定忘れや、Heroku 環境下 Rails のログの標準出力化 gem 導入 ( rails_12factor ) や、devise の Heroku 環境下限定設定や dotenv-rails が参照するダミーの .env ファイルが存在しない ... など、本番環境ならではのセットアップが必要。

加えて、当たり前なことだが database.yml や db 配下のシードなど、全て production モードで実行されるので、development モードで開発してデプロイする前に一度 production モードでもビルド → デプロイ → 動作テストを実施してからやった方がよい ( 真顔 ) 。

# dotenv-rails は .env ファイルを参照するため
# 本番環境に .env を削除してアップするとキーなしエラーが出る
# .env.development をコピって無害な .env をあげるのがよいかな
$ cp .env.development .env

# 本番環境用の環境変数セット忘れずに
$ heroku config:set RAILS_ENV=production
$ heroku config:set RAILS_MASTER_KEY=xxxxxxxxxx
$ heroku config:set DATABASE_URL=xxxxxxxxxxxxxx
# Gemfile
#
# rails_12factor で production モードのログを標準出力に流す
# これがないと heroku logs --tail で Rails の吐いたログが見れない
#
gem "rails_12factor", group: :production

# config/initializers/devise.rb
#
# Rails は secret_key ( フレームワークの salt ) を
# config/credentials.yml.enc に暗号化して保存しており
# 通常 .gitignore されている config/master.key で復号
# Rails.application.credentials.hoge で参照できるようにしている
# んで、devise は devise で production 時にシークレットキーが必要なので
# コードベースにベタ書かないで Rails の credential 使おうって話
#
if Rails.env.production?
  config.secret_key = Rails.application.credentials.secret_key_base
end
Basic Authentication

Ruby on Rails > Basic 認証

Nginx

Heroku へデプロイする際には $PORT を Listen する Nginx とアプリサーバ + アプリを単一コンテナにまとめた「 Heroku デプロイ専用 Dockerfile / nginx 設定ファイル」みたいなの作っておいて、開発環境とは分けて考えた方が楽。

# イメージは言語&フレームワークで決める
#
FROM    python:3.7
ENV     PYTHONUNBUFFERED 1
RUN     mkdir app
WORKDIR /app

# 言語/アプリの前に Nginx をセットアップ
#
ARG  DOMAIN
RUN  apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN  wget "http://nginx.org/keys/nginx_signing.key" && \
     apt-key add nginx_signing.key && \
     echo "deb http://nginx.org/packages/debian/ stretch nginx" >> /etc/apt/sources.list && \
     echo "deb-src http://nginx.org/packages/debian/ stretch nginx" >> /etc/apt/sources.list && \
     apt-get update
RUN  apt-get install -y nginx && \
     rm -rf /etc/nginx/conf.d/* && \
     rm -rf /etc/nginx/sites-enabled/*
COPY uwsgi_params /etc/nginx/uwsgi_params
COPY heroku.conf  /etc/nginx/conf.d/default.conf

# アプリケーションの依存インストール & アプリサーバ実行
#
COPY requirements.txt requirements.txt
RUN  pip install -r requirements.txt
COPY . /app

# Nginx の設定ファイルについて $PORT 書き換えなどを実行
# $PORT は実行時に引き渡されるため Dockerfile 上では ENV できない
# その後 Nginx をデタッチで起動し、アプリサーバを立ち上げ
#
CMD sed -e "s/PORT/${PORT}/g" -i /etc/nginx/conf.d/default.conf && \
    sed -e "s/DOMAIN/${DOMAIN}/g" -i /etc/nginx/conf.d/default.conf && \
    nginx -c /etc/nginx/nginx.conf && \
    uwsgi --ini django.ini

Worker Dyno on Container Registry

Worker Dynos, Background Jobs and Queueing
Heroku x WebSocket - gist.github.com

上記の通り Heroku ではバックグランドタスクは Worker Dyno にやらせる必要がある。Docker 構成でデプロイする場合は、Web コンテナとは別に Worker コンテナを用意して、こちらを Web とは別に Worker Dyno としてデプロイしてやる。

$ ls
> Dockerfile.web     # いつもの Web Dyno 用のコンテナ
> Dockerfile.worker  # Worker Dyno として使いたいコンテナを別に用意して .worker とする

$ heroku container:push --recursive
$ heroku container:release web worker

# Worker Dyno をスケールアップして 1 台起動させる ( 初回のみ必要 )
$ heroku ps:scale worker=1

Web コンテナ内に Worker 系のプロセスを同居させたりすると、Dyno Type の違いからか Worker 系の ( = 常時稼働系の ) プロセスが死ぬことがある?


ADD-ONS

Papertrail

Papertrail - devcenter.heroku.com
Papertrail - elements.heroku.com
HeokuのAddOn papertrailで不要なログを保存しない方法

Heroku で一般的なログ管理サービス。無料でもそこそこの機能があるので脳死で入れておいた方がいい。本番運用では S3 用意してアーカイブそっちに流すのと、1 日のログ転送量に注意する (必要ならフィルタリング) 、アラート入れて Slack 通知設定しておくくらいか。

Rails の papertrail gem (audit みたいなやつ) とは別物なので検索時注意。

# Free プラン機能
1日のログ転送量 10 MB
ログ保持期間    7 日間
検索可能な期間  2 日間
アラート機能    利用可

# Fixa (Free の次) プラン機能
1日のログ転送量 65 MB
ログ保持期間    365 日間
検索可能な期間  7 日間
アラート機能    利用可

ログの量がそこそこあるなら、フィルタリング頑張って heart beat 系削るなりしてもいい。ただ有償プラン $8/month で一日の転送量 10 MB -> 65 MB 、アーカイブ 1 年になるのでお金で解決したほうが楽そう。

# install
$ heroku addons:create papertrail

# open dashboard
$ heroku addons:open papertrail

Point DNS add-on

HEROKUのサイトをWWWなし独自ドメインで
herokuでルートドメインを最速で設定する

Point DNS はアプリに DNS サーバ機能を付与するアドオン。ドメイン管理サービスへ Point DNS を「当該ドメインのネームサーバ」として登取し、ドメインの名前解決を Point DNS 側で行う設定にすることで、ルートドメインの解決 ( ALIAS レコードの利用 ) が可能になる。

  1. お名前.com でドメイン取得
  2. Heroku で Add Domain でドメインを追加
    • example.com などルートドメインで
    • DNS サーバホスト名をメモ
  3. Point DNS アドオンを追加
  4. Point DNS 管理画面より ALIAS な DNS レコードを追加
    • ALIAS でルートドメイン解決を行い CNAME レコードでサブドメインを解決するのが一般的みたい
  5. お名前.com 管理画面より Point DNS のネームサーバホスト名 *.pointhq.com を当該ドメインのネームサーバとして登録
# ALIAS レコードの登録例
Record Type : ALIAS
Name : ( 入力せず )
Target : xxxxxx.herokudns.com  # Add Domain で付与された DNS サーバ名
TTL : 60

# CNAME レコードの登録例
Record Type : CNAME
Name : www
Target : example.herokuapp.com  # デフォルトの Heroku ドメインに飛ばしちゃうとか
TTL : 3600

Heroku Postgres

A5mk2 とかで接続する場合は Heroku Dashboard > Resource > Add-ons > Heroku Postgres > Settings > Database Credentials より接続情報を確認すればよろしい。このとき SSL モードを「優先」にすること。

Upgrade & Backup

herokuのpostgresqlをアップグレードする
Herokuでデータベースのバックアップを行いたい

基本新規プランでアドオン追加 → DB データを以降 ... という手順

$ heroku login
$ heroku pg:info -a ${APP_NAME}

# メンテモードへ
$ heroku maintenance:on -a #{APP_NAME}

# Hobby Basic プランの Heroku Postgres アドオンを追加
$ heroku addons:create heroku-postgresql:hobby-basic -a ${APP_NAME}
> Created postgresql-closed-xxxxx as HEROKU_POSTGRESQL_ONYX_URL  # 環境変数が新規作成される
> Use heroku addons:docs heroku-postgresql to view documentation

# 既存 DATABASE から新規 ONYX へデータコピー
$ heroku pg:copy DATABASE_URL HEROKU_POSTGRESQL_ONYX_URL -a ${APP_NAME}

# DB 参照先を変更
$ heroku pg:promote HEROKU_POSTGRESQL_ONYX_URL -a #{APP_NAME}

# DATABASE_URL 環境変数が新規 ONYX と同じになっているか確認
$ heroku pg:info -a ${APP_NAME}
> === HEROKU_POSTGRESQL_ONYX_URL, DATABASE_URL
> Plan:                  Hobby-basic
> Status:                Available

# 定期バックアップ設定
$ heroku pg:backups:schedule DATABASE_URL --at '4:00 Asia/Tokyo' -a ${APP_NAME}

# 定期バックアップスケジュール確認
$ heroku pg:backups:schedules -a ${APP_NAME}

# メンテモード解除
$ heroku maintenance:off -a #{APP_NAME}

# 必要ならば GUI ( 管理画面 ) から旧アドオンを削除

pg:buckups:restore

https://devcenter.heroku.com/articles/heroku-postgres-import-export#import-to-heroku-postgres

s3 に dump ファイルアップして読ませろって ... はいぃ。restore した後 s3 ファイル消すの忘れないように。

# aws cli で s3 signed url 発行
$ aws s3 presign s3://your-bucket-address/your-object

# restore
$ heroku pg:backups:restore -a p62-bizops-proto '<SIGNED URL>' DATABASE_URL

heroku pg:reset

Heroku Postgres は既に DB が割り当てられた状態で提供され、この DB を DROP したり CREATE したりすることはできない。よって Rails などで rake db:createrake db:drop によるリセットが行えない。既存データが全て消えて問題ないなら pg:reset で似たようなことができる。

# これ DATABASE_URL 環境変数を使うよって意味なので
# 実際の postgres://xxxx みたいなやつを打つんぢゃないよ
$ heroku pg:reset DATABASE_URL

# リセット後は DB が空なので初回同様にマイグレート/シードをする
$ heroku run rake db:migrate
$ heroku run rake db:seed

Heroku Scheduler

Heroku Scheduler
curl で Basic 認証(Authorization ヘッダを利用した場合)

Daily / Hourly / Every 10 minutes のいずれかの周期でコマンド実行できる Cron みたいなやつ。実行時間はそのまま One-Off Dyno 換算されるため、重たい処理は料金がかさむ。軽い処理を定時実行したいときに使える。60 秒程度のタスク 10 分毎にさせた場合、1 か月 80 時間弱なので、Free プランの常時稼働用タスク ( 10 分置きに curl で GET して Web Dyno 叩き起こすやつ ) 分 6.2 時間 + Web Dyno 常時稼働 744 時間とあわせてなんとか無料枠内。

また Very Rare に動かなかったり、重複実行されたりするケースがあるため超重要な処理は注意。厳密かつ柔軟な定時処理を行いたい場合は各言語向けの Cron ライクなカスタムクロック ( スケジューラ ) ツールを利用すると良い。

Scheduled Jobs and Custom Clock Processes Better Heroku Schedulerを探したらCustom clock processesにたどり着いた

# 常時起動させたいだけなら、既に常時起動してるサーバから
# Cron で 30 分に 1 回 curl で GET するだけでいい
$ curl --head -X GET https://my-app.herokuapp.com/

# Basic 認証つきならこう
$ curl --basic -u username:password --head -X GET https://my-app.herokuapp.com/

Daily Dyno Restart の時刻を固定

HerokuのDynoの日次再起動の時刻を指定する

上記参考記事は buildpack を利用しているため Container Registry の場合は buildpack の導入をスキップして Scheduler に Platform API を curl でキックするよう仕込めばよいかな。

Getting Started with the Platform API
Platform API Reference > Dyno Restart

# Platform API キック時に利用する長期トークンを生成
$ heroku authorizations:create
> xxxx-xxxx-xxxx-xxxx
$ heroku config:set HEROKU_API_KEY=xxxx-xxxx-xxxx-xxxx

# Heroku Scheduler の追加と設定
$ heroku addons:create scheduler:standard
$ heroku addons:open scheduler

# ブラウザで以下コマンドが実行されるよう設定
$ curl -X DELETE "https://api.heroku.com/apps/${HEROKU_APP_NAME}/dynos" \
  -H "Authorization: Bearer $HEROKU_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/vnd.heroku+json; version=3"

SendGrid

ActionMailer
HerokuアドオンなSendGridを独自ドメインで使用するまでの3ステップ

# config/environments/production.rb

config.action_mailer.smtp_settings = {
  :user_name => ENV['SENDGRID_USERNAME'],
  :password => ENV['SENDGRID_PASSWORD'],
  :domain => 'yourdomain.com',
  :address => 'smtp.sendgrid.net',
  :port => 587,
  :authentication => :plain,
  :enable_starttls_auto => true
}

Inbound Parse

Inbound Email Parse Webhook
Sendgridでメールサーバのお守りから解放され、かんたんに受信メールを取り扱えるようになる話

SendGrid にはメール受信イベント発生時に特定 URL へ受信したメール情報をパースしてキックする Inbound Parse という機能がある、受信可能なメールは 20 MB まで。ちなみに「メール投稿によって新規記事を作成」のような利用方法を想定しているみたい。キックする API 経由で予め Slack に設置した Incoming Webhook を叩くようにすれば「メール受信 → Slack 投稿」のような疑似メール受信 + メールボックスも実装できる。

  1. アプリケーションに Slack などに投稿を流す Webhook を作成
  2. Sender Authentication よりドメイン認証を完了する
  3. Inbound Parse を新規作成
    • スパムチェックはお好み
    • POST raw データはほとんどの場合不要

Heroku Redis

Heroku Redis - elements.heroku.com
Heroku Redis - devcenter.heroku.com

Heroku Redis の同時接続数 ( Connection Client ) はかなり渋いので、利用の際はそれ相応のプランを選択するか、アプリ側から同時接続数を絞るようにしてあげると宜しい。

Sidekiq + Heroku RedisでERROR: ERR max number of clients reachedと言われたら

また、プラン変更の際は「アプリ再起動 → ちょっと遅れて新プランの Redis が割り当て」になるため注意。

CLI

redis:cli
Heroku: RedisにCLIでアクセスし、コマンド操作する

# redis-cli へ接続
$ heroku redis:cli -a myapp

# 全消し
$ flushall

# 終了は Ctrl + C で

RedisMonitor

RedisMonitor - elements.heroku.com
RedisMonitor - devcenter.heroku.com
Heroku Redis を使ってるなら利用したい Redis Monitor アドオン

Redis のダッシュボードアドオン。課金すると key 毎のメモリ使用量とか見れる。無料プランでも以下を監視できるので入れといて損ない。

  • Memory 使用量
  • Key 総量
  • 接続 Client 数
  • Command 数 /分
  • Slow Query
# Heroku Dashboard に追加
$ heroku addons:create redismonitor:free --url -a myapp

# ↑ Dashboard > Resources からアクセスして Redis の URL 確認して入力
$ heroku config:get REDIS_URL -a myapp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment