strapiでブログを作る⑤(デプロイ編)

strapiでブログを作る⑤(デプロイ編)

herokuとcloudflareを使ってブログを公開するための設定方法を紹介します。

公開日:2024年6月5日 更新日:2024年9月4日
programming

構成

バックエンドの構成

■サーバー

heroku - dynos (Basic plan)

費用 (上限 $7/月) (Heroku の価格)

■データベース

heroku - postgres

費用 約$0.007/時間(上限 $5/月) (Heroku の価格)

最大$12なので今の$1が155.78 円なので1869.42円となると結構高い。たかが個人ブログにこの金額は結構高い。年間だと22433円もしてしまう。以前herokuは無料だったから、有料になったとはいえ良心的な価格設定に抑えてくれていると思っていたのに...

しかも日本のリージョンを使いたい場合はHeroku Enterpriseにならなくてはならず、そうでない場合はアメリカ(US)かヨーロッパ(EU)しか選ばべなかったです。

それでもなぜHerokuを選んだかというとstrapiのドキュメントの[strapi - Hosting Provider Guides] (https://docs.strapi.io/dev-docs/deployment/hosting-guides)に

  • AWS
  • Azure
  • DigitalOcean
  • Heroku
  • Strapi Cloud

のホスティングの方法が記載されていたので、これらのプロバイダーが推奨されているのでこちらから選ぼうと思った次第でした。 この中ではHerokuが一番安そうで、使ったこともあったのでHerokuを選択しました。

フロントエンドの構成

■ドメイン Cloudflare Registrar

protagram.comというドメインを取得し

管理画面用の

admin.protagram.com

オブジェクトストレージ用の

storage.protagram.com

というサブドメインも作っています。

費用は年間で**$9.77**でした。

■サーバー

cloudflare pages

ここにnuxt3で作ったフロント側のコードをデプロイします。

■オブジェクトストレージ

cloudflareのr2

r2はS3互換のオブジェクトストレージなのでawsのS3でも良かったのですが、S3よりも安く、一定の容量までは永年無料な点でこちらを選びました。

また極力少ないプロバイダーで完結したいのでr2があって助かりました。


デプロイ環境構築

今回はherokuとcloudflareという2つのプロバイダを使いデプロイを行います。

バックエンドのデプロイ設定

Herokuへのデプロイ設定

https://docs.strapi.io/dev-docs/deployment/heroku

ドキュメントの通りにやれば大体はできます。

backend編でnpx @strapi-community/dockerize を実行していれば ./config/env/production/database.tsのファイルは生成されていると思いますが以下のように書き換えます。

import { parse } from 'pg-connection-string';
const config = parse(process.env.DATABASE_URL);

export default ({ env }) => ({
  connection: {
    client: 'postgres',
    connection: {
      host: config.host,
      port: config.port,
      database: config.database,
      user: config.user,
      password: config.password,
      ssl: {
        rejectUnauthorized: false
      },
    },
    debug: false,
  },
});

/config/env/production/server.ts のファイルを作成して以下をコピー

export default ({ env }) => ({
        proxy: true,
        url: env('MY_HEROKU_URL'), // Sets the public URL of the application.
        app: { 
          keys: env.array('APP_KEYS')
        },
    });

pgとpg-connection-stringをインストール

npm install pg && npm install pg-connection-string

./.gitignoreに以下の記述を追加

package-lock.json

Herokuの設定

HerokuはCLIがるので、コマンドラインから操作することが可能です。

ただ管理画面からの方が実際どのようになったのかが分かるので個人的には管理画面から操作した方が良い気がしています。

ただどっちにしてもherokuへのデプロイのときに使うのでheroku cliをインストールはしておいた方がいい

■アカウントを作成

まずはHerokuのアカウントを作りログインします。

https://signup.heroku.com/login

※クレジットカードの登録も必要となります。

※Google Authenticatorなどの認証アプリも必要となります。

■heroku cliのインストール

brew tap heroku/brew && brew install heroku

cliでログインする

heroku login

■projectを作成

まずは左上のNEWのボタンからcreate appを選択します。

この時app-nameとregionを選ぶのですが、regionにはUnited StatesとEuropeしかないです涙

cliを使う場合は以下

heroku create

■database作成

管理画面から追加する方法

管理画面のResourceからFind more add-onsのボタンをクリック

Heroku Postgresを追加する。

Loading...

追加されたHeroku PostgresのリンクをクリックするとDBの使用状況を見ることが出来る。

Loading...

Heroku PostgresのSettingsのCredentialsのView Credentials…のボタンをクリックすることでDBの情報を見ることが出来る。

Loading...

cliから追加する方法

cliのコマンドは以下

heroku addons:create heroku-postgresql:<PLAN_NAME>

ここのPLAN_NAMEは適切なPlanを入力する。

今回私は最安のminiをにした。

昔は無料のhobbyというプランがあったのになくなってしまっていた。

https://devcenter.heroku.com/articles/heroku-postgres-plans

heroku config

こちらを実行するとDATABASE_URLをみることが出来る。

ここにDBのusernameとpasswordも含まれているので、それを使えばdbeaverなどを使ってDBを見ることも出来る。

envにDB情報を追加

とりあえずこれを元にenvのDBの以下の情報を適切に書き換えてください。

DATABASE_HOST=ec2-*****.compute-1.amazonaws.com
DATABASE_PORT=5432
DATABASE_NAME=
DATABASE_USERNAME=
DATABASE_PASSWORD=

■envの設定

Config Varsには以下のkeyと値が必要になります。

ADMIN_JWT_SECRET
API_TOKEN_SALT
APP_KEYS
CF_ACCESS_KEY_ID
CF_ACCESS_SECRET
CF_BUCKET
CF_ENDPOINT
CF_PUBLIC_ACCESS_URL
DATABASE_URL
JWT_SECRET
MY_HEROKU_URL
NODE_ENV

これらをCLIで追加する場合は.env.productionにenvの値が書いてある前提で以下のコマンドを実行すると追加される。

heroku config:set APP_KEYS=$(cat .env.production | grep APP_KEYS | cut -d= -f2-)
heroku config:set API_TOKEN_SALT=$(cat .env.production | grep API_TOKEN_SALT | cut -d= -f2)

ここで追加された内容は管理画面のSettingsのConfig VarsのReveal Config Varsというボタンをクリックすると表示されます。

■Buildpacksの設定

settingsのBuildpackのadd buildpackからnodejsを選択

Loading...

■Domainsの設定

SettingsのDomainsからCloudflareで取得したadmin.protagram.comのサブドメインを設定することで、管理画面のURLをherokuが自動で割り振ってくれたURLからサブドメインに変更することができます。

手順はちょっと忘れたのですが、適当にやっても出来るはずです。

Herokuへデプロイ

heroku cliを使う場合以下のコマンドで自動でHerokuにデプロイされる。

git push heroku HEAD:main

しかし、これで以下のエラーが出た。

Installing binaries
remote:        engines.node (package.json):   >=18.0.0 <=20.x.x
remote:        engines.npm (package.json):    >=6.0.0
remote:        
remote:        Resolving node version >=18.0.0 <=20.x.x...
remote:        Downloading and installing node 19.9.0...
remote:        Bootstrapping npm >=6.0.0 (replacing 9.6.3)...
remote: npm ERR! code EBADENGINE
remote: npm ERR! engine Unsupported engine
remote: npm ERR! engine Not compatible with your version of node/npm: npm@10.7.0
remote: npm ERR! notsup Not compatible with your version of node/npm: npm@10.7.0
remote: npm ERR! notsup Required: {"node":"^18.17.0 || >=20.5.0"}
remote: npm ERR! notsup Actual:   {"npm":"9.6.3","node":"v19.9.0"}

.....

remote: !       Push rejected to protagram.
remote: 
To https://git.heroku.com/protagram.git
 ! [remote rejected] HEAD -> main (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/protagram.git'

package.jsonのnodeのバージョンを指定している場所を修正したら治った。

"engines": {
    "node": ">=18.0.0 <=20.x.x",
    "npm": ">=9.6.3"
  },
  
これを
 
 "engines": {
    "node": "20.11.0",
    "npm": ">=9.6.3"
  },
こう

node -vでlocalのnodeバージョンを確認して変更した。

これでうまく行った。

■GitHubのpushをトリガーにしてデプロイ

ただGitHubのmainブランチにpushされたのをトリガーにデプロイされるように設定した方が良い。

これは管理画面のDeployから

  1. Deployment methodでGitHubを選択
  2. App connected to GitHubでデプロイしたいリポジトリを接続
  3. Manual deployでブランチを選択

この設定でOKだったはず。

Cloudflareの設定

■サブドメインの設定

DNSの設定は以下のような感じ

Loading...

www

wwwはhttps://www.protagram.comに来たときにhttps://protagram.comにリダイレクトさせるために設定した。これはもう一つ設定を行わないとリダイレクトされないので後で説明します。

admin

herokuで設定した管理画面のurlをhttps://admin.protagram.comにするための設定です。

HerokuのsettingsのDomeinsからtargetの情報をコピーしてこちらに貼ります。heroku側でも設定が必要です。

コンテンツ部分はtriangular-bee-xxxxxxxxxxxxx.herokudns.com みたいな感じのやつです。

protagram.com

これはnuxtで作ったクライアントサイドで使うURLです。

cloudflare pageをを使っているのでそちらと紐づけています。

R2

これは画像などを置くs3のようなオブジェクトストレージ用のURLです。

画像などはhttps://storage.protagram.com/strapi_logo_832de14ba3.jpg みたいなurlとなります。これもR2で設定が必要です。

R2

オブジェクトストレージの設定を行います。

backend編ではs3の設定方法を説明していたのですが、今回はcloudflare-r2の設定方法を説明します

strapi-provider-cloudflare-r2の設定

https://market.strapi.io/providers/strapi-provider-cloudflare-r2

npm install strapi-provider-cloudflare-r2 --save

.config/plugins.js に以下のコードを書く

module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {
      provider: "strapi-provider-cloudflare-r2",
      providerOptions: {
        accessKeyId: env("CF_ACCESS_KEY_ID"),
        secretAccessKey: env("CF_ACCESS_SECRET"),
        /**
         * `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`
         */
        endpoint: env("CF_ENDPOINT"),
        params: {
          Bucket: env("CF_BUCKET"),
        },
        /**
         * Set this Option to store the CDN URL of your files and not the R2 endpoint URL in your DB.
         * Can be used in Cloudflare R2 with Domain-Access or Public URL: https://pub-<YOUR_PULIC_BUCKET_ID>.r2.dev
         * This option is required to upload files larger than 5MB, and is highly recommended to be set.
         * Check the cloudflare docs for the setup: https://developers.cloudflare.com/r2/data-access/public-buckets/#enable-public-access-for-your-bucket
         */
        cloudflarePublicAccessUrl: env("CF_PUBLIC_ACCESS_URL"),
        /**
         * Sets if all assets should be uploaded in the root dir regardless the strapi folder.
         * It is useful because strapi sets folder names with numbers, not by user's input folder name
         * By default it is false
         */
        pool: false,
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});

./config/middlewares.js に以下を追加

module.exports = ({ env }) => [
  // ...
  {
    name: "strapi::security",
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          "connect-src": ["'self'", "https:"],
          "img-src": [
            "'self'",
            "data:",
            "blob:",
            "market-assets.strapi.io",
            env("CF_PUBLIC_ACCESS_URL") ? env("CF_PUBLIC_ACCESS_URL").replace(/^https?:\/\//, "") : "",
          ],
          "media-src": [
            "'self'",
            "data:",
            "blob:",
            "market-assets.strapi.io",
            env("CF_PUBLIC_ACCESS_URL") ? env("CF_PUBLIC_ACCESS_URL").replace(/^https?:\/\//, "") : "",
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  // ...
];

.envには以下の値が必要。これは後でcloudflareの設定をする中で値を取得していく事となる。

■R2の設定

バケットを作って設定から以下を設定します。

カスタムドメイン

DNSで作ったstrage.protagram.comを設定する。

r2.dev サブドメイン

⇒ 許可しない

CORSポリシー

許可されたオリジン許可されたメソッド許可されたヘッダー
http://localhost:1337GET開発用
https://www.protagram.comGETクライアント
https://protagram-8f5098aac22c.herokuapp.comGET管理画面

R2 APIトークンの作成

設定内容なこんな感じ

Loading...

そしたら

  • トークン値
  • アクセスキーID
  • シークレットアクセスキー
  • エンドポイント

表示されるので.envに追加していきます。

CF_PUBLIC_ACCESS_URL=storage.protagram.com
CF_TOKEN=
CF_ACCESS_KEY_ID=
CF_ACCESS_SECRET=
CF_ENDPOINT=
CF_BUCKET=protagram

CloudFlare pagesの設定

カスタム ドメインの設定

protagram.com

設定 ⇒ 環境変数

変数名
GTM_IDGTM-xxxxx
STRAPI_URLhttps://admin.protagram.com

GTMを使わないのであればGTM_IDは不要

設定 ⇒ ビルド&デプロイ

Loading...

ビルドの構成のところがちょっと重要

buildしても/distというフォルダは生成されないが/distにする。

WWWのリダイレクト設定

サイドバーのWeb サイトからドメインを選択してルール ⇒ ページルール ⇒ ページルールを作成

Loading...

以上のように設定します。

※現在ページルールはLegacy となっているので、今だとリダイレクト ルールを使ったほうが良さそです。

まとめ

一度作った後にブログの記事として書いたので、漏れたミスがあったらすみません。

今回はherokuとcloudfrareを使ってブログを公開したが、herokuの料金がちょっと高いと感じました。

次もしstrapiを使って何かサービスを作ることがあれば規模にもよるが、supabaseとcloudfrare 、もしくはspabaseとverselの組み合わせでドメイン料金くらいで運用したいと思う。

参考サイト

https://hanzochang.com/articles/1#prepare-local-s3

https://docs.strapi.io/dev-docs/deployment/heroku

https://qiita.com/yonet77/items/6c06de9ef5bf8735b27a

https://zenn.dev/platina/articles/6fca432ec1ae1a