Nextjsのセットアップでエラー2つ出たので対処した
npx create-next-appでNextjsを開始しようとしたら
error nanoid@3.1.30: The engine "node" is incompatible with this module. Expected version "^12.22.0 || ^14.17.0 || >=16.0.0". Got "12.19.0"
というエラーが出た。
シンプルにバージョンを
nodenvで16.0.0に合わせて再度実行したら
npm ERR! Could not resolve dependency: npm ERR! peer eslint@"^7.23.0" from eslint-config-next@11.1.2
が出た。
これはnpm v7からの変更らしい
node16だとnpm v7を使っているので出た
今回はnodeのバージョンを12.22.0に落とすことで対応
再度実行するとセットアップできた
nodenvでnodeのバージョン管理をする - Qiita
anyenv / nodenv 使用時に Node.js のバージョンを上げる方法 - Qiita
npm v7で`ERESOLVE unable to resolve dependency tree Could not resolve dependency:` - Qiita
ECS, Fargateで立てたサーバーをPrismaでRDSにつなぐ
使用技術
TS, Node(Hapi), Prisma, ECS, Fargate, RDS(MySQL)
現在既にAWS上でサーバーが起動しているものとする。
index.ts
import Hapi from "@hapi/hapi"; import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); const init = async () => { const server = Hapi.server({ port: 3030, }); server.route([ { method: "GET", path: "/", handler: () => { console.log("run"); return "Hello World!"; }, }, { method: "GET", path: "/users", handler: async () => { console.log("users"); const users = await prisma.user.findMany(); return users; }, }, ]); await server.start(); console.log("サーバー起動"); console.log("Server running on %s", server.info.uri); }; init();
schema.prisma
datasource db { provider = "mysql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" // ローカルでエラー起きたのでここ書いてる。いらないかも binaryTargets = ["native", "debian-openssl-1.1.x"] } model User { id Int @id @default(autoincrement()) name String? age Int? }
Dockerfile
FROM node:12 RUN apt-get update RUN apt-get install -y openssl WORKDIR /app COPY package*.json /app RUN npm install COPY . /app EXPOSE 3030 EXPOSE 5555 CMD npx ts-node src/index.ts
ローカルでは.envファイルやdocker-composeにDATABASE_URLを定義すればPrismaがそれを読み取ってくれる。だが、AWS上ではそのようなものを持たせてないので環境変数を別途AWS上で定義する。
方法はいくつかあると思うがSystems Managerを使うことにする。公式にも
Amazon ECS を使用すると、AWS Systems Manager パラメータストア パラメータに機密データを保存してコンテナの定義でそれを参照することによって、コンテナに機密データを挿入できます。
とあるのでECSとの相性は良さそう。
パラメータストアにパラメータを定義
Systems Managerという機能群の中の1つであるパラメータストアを使い実際に環境変数を定義していく。
↑ここから作成
ここでは sampleServerDatabaseUrl というキーで作成する
コンテナに環境変数を定義
作成したキーを実際にコンテナから使用する
タスク定義を修正する必要があるので対象のタスク定義から「新しいリビジョンの作成」をクリック。
現在のコンテナをクリックして、モーダルの下の方にある「環境変数」の部分で指定する。
この時、ValueFromを選択するよう気を付ける
使用するタスク定義の変更
最初に書いた通り、今回はすでにサーバーが動いている状態からの変更である。
先程タスク定義の新たなリビジョンを作成したが、サービスが使用しているタスク定義は依然として古いもののままである。
なのでサービスが使うタスク定義を最新のものに変更する
変更は↓から行うことができる
なお、ここで権限のエラーが出た場合
ECSからSystems Managerの値参照しようとしたらResourceInitializationErrorが出た - プログラミングとかのお雑な備忘録
を参照
Prismaでマイグレーション
今のままだとmigrateできてないのでする。DockerfileのCMDで行うことにする。CMDで複数コマンド実行したい場合は自分はシェルで定義しているのでここでもそうする。
start.sh
if [ "$NODE_ENV" = "development" ] then npx prisma migrate dev npx ts-node src/index.ts elif [ "$NODE_ENV" = "production" ] then npx prisma migrate deploy npx ts-node src/index.ts fi
Prismaは環境によってマイグレーション方法が prisma migrate dev とprisma migrate deployで別れるので環境変数NODE_ENVを定義して、その値で判断させることにする。
なのでまた「新しいリビジョンの作成」-> 既存コンテナクリック -> 環境変数のとこで追加する
ローカルでは.envファイルやcomposeなどにdevelopmentを定義
次に上記Dockerfileの
CMD npx ts-node src/index.ts
を
CMD ["./start.sh"]
に変更する。
権限を与えるため
chmod 744 ./start.sh
を実行
ECRの「プッシュコマンドの表示」に従い新たなImageをプッシュする。
タスク定義から「新しいリビジョンの作成」で先程プッシュしたImageのURIに更新。
サービスで使用するリビジョンを更新したバージョンに変更。
そうしてログを見てみると
こんな感じのエラーが出る。
セキュリティグループを修正してこのエラーに対応する。
セキュリティグループの修正
ECSとFargateとALBでNodeサーバーを立てる - プログラミングとかのお雑な備忘録
ここでも書いたのと同じような要領で修正セキュリティグループを修正していく。
まずサービスのセキュリティグループを確認。
ここではSample-6411
次にRDSのセキュリティグループを修正する。
[Eidit inbound rules]をから修正ページに入る。
↓このルールを追加
この中の選択されているグループは先程確認した Sample-6411
これで修正はOK
強制的に再デプロイして確認
↓強制的に再デプロイする方法
AWSコンソールでサービスを見つけます。 右上隅にある[更新]をクリックします。 [新しい展開を強制する]チェックボックスをオンにします。 他の構成をスキップして、[サービスの更新]をクリックします。 サービスは再デプロイされます。
<ALBのDNS>/users をブラウザのURL欄に打ち込んで確認
エラーが出ずに[]が帰って来れば無事成功!
TODO
DBは多分パブリックでアクセスできる必要ないのでプライベートにする。
プライベートバージョンからちゃんと接続できるか確認
Route53を用いた独自ドメインでの構築
参考
AWS ECS(バックエンド編)|Nuxt.js + Ruby on Rails + AWS Fargate の開発・デプロイチュートリアル
AWSの公式の記事色々
ECSからSystems Managerの値参照しようとしたらResourceInitializationErrorが出た
ECS, Fargateで起動させてたサーバーで環境変数が必要だったのでSystems Managerで定義してタスク定義のコンテナ追加の部分の環境変数でValueFromでそのSystems Managerの値を参照しようとしたら ResourceInitializationError ~ が出た。
タスク実行ロールには [ecsTaskExecutionRole] を使っていた。(覚えてないけど確かデフォルトで作成されてたやつ)
他のAWSのサービスに対してこのタスクから色々やる場合はここで権限を与えないといけない
エラーの原因
Systems Managerに対する権限がない
解決法
タスク実行ロールのecsTaskExecutionRoleにSystems Managerの値を参照できるように権限を与える。
まずポリシーの作成で
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:GetParameters" ], "Resource": [ "arn:aws:ssm:ap-northeast-1:<アカウントID>:parameter/<Systems Managerに定義したパラメータ>" ] } ] }
を定義して作成
これで指定したリソースに指定したアクションが許可される。
次にecsTaskExecutionRoleにこのポリシーをアタッチ
これで権限が与えらた
参照
AWS IAMポリシーを理解する | DevelopersIO
Systems Manager パラメータストアを使用した機密データの指定 - Amazon Elastic Container Service
ECSとFargateとALBでNodeサーバーを立てる
Hapi製APIサーバーをDockerコンテナ化したのでAWS上で動かしたかったのでECS, Fargateを使いデプロイすることにした。その手順を書いていく。
index.js
const Hapi = require("@hapi/hapi"); const init = async () => { const server = Hapi.server({ port: 3030, }); server.route({ method: "GET", path: "/", handler: (req, h) => { console.log("run"); return "Hello World!"; }, }); await server.start(); console.log("サーバー起動"); console.log("Server running on %s", server.info.uri); }; init();
Dockerfile
FROM node:12 RUN apt-get update WORKDIR /app COPY package*.json /app RUN npm install COPY . /app EXPOSE 3030 CMD node index.js
1. リポジトリの作成
2. Imageのプッシュ
ここの「プッシュコマンドを表示」をクリックして手順を表示
ローカルで全て手順通り打ち込む
3. クラスタの作成
「ネットワーキングのみ」を選択して「次のステップ」
名前などつける
この時、VPCの作成はしない(多分しても平気)。理由はここで色々設定しなくちゃならなくなるから。
右下の「作成」
4. タスク定義
サイドバーの「タスク定義」を開き、「新しいタスク定義の作成」をクリック
「Fargate」を選択し「次のステップ」をクリック
名前やメモリ割り当てなど色々入力していく
「タスクロール」はそのタスクから他のAWSのサービスを使いたい時には必要。ここでは空欄にする
「コンテナの追加」でリポジトリからイメージを選択する
リポジトリのイメージのURLは↓ここからとる
コンテナの追加の設定を行なっている時に「メモリ制限」という欄があるが、ここでサンプルだからって適当に1とか入れるとメモリ足りなくて起動できない可能性があるのである程度の数値入れる
「ポートマッピング」という欄があるが、ここではDockerfileでEXPOSEしてるポートを入れる。今回は3030
右下の「追加」をクリック
コンテナを追加できたら右下の「作成」をクリックして作成する
5. ロードバランサの作成
検索タブでec2を検索しそのページを開き、サイドバーの「ロードバランサー」を選択し、「ロードバランサーの作成」をクリック
ロードバランサーのタイプを選択する画面になるので、ALBを選択
Basic configuration
名前などの設定をしていく
Network mapping
ネットワークの設定をする。AZは最低2つ選択しなければいけない。
Security groups
セキュリティグループの設定
[Create new security group] を選択し新規のものを作成。既存のものでもいいが新規の方が何やってるかわかりやすいのでここでは新規作成する。
インバウンドルールに「カスタムTCP, ポート範囲80, ソースAnywhere 0.0.0.0/0」を追加
これにより、全てのipからのポート80へのリクエストが許可される。
新規作成が完了したらALBの設定画面で選択する。defaultなどが指定されてる場合は削除
Listeners and routing
リッスンするポートやルーティングの設定をする。
それぞれのリクエストに対してどこにルーティングするかを決めるために「ターゲットグループ」を指定する
ここではcreate target groupで新規作成する
ターゲットタイプはIPを選択して、Portにはフォワーディングしたいポートを指定。今回は3030
Nextを押したらRegister targetsというページが出てくる。ここではまだ対象のFargateは作成されていないので特に何もしない。
右下の[create target group]をクリックし作成。
作成されたらロードバランサ作成の画面に戻り、今作ったターゲットグループを選択する。
もしhttpsにしたい場合は[add listner]で追加する。
ここまでできたら右下の[Create load balancer]で作成
作成できたらロードバランサーのページで状態を見てみる。ここが「プロビジョニング」だと動かないので注意
6. サービスの作成
クラスターの詳細から「サービス」タブを選択。青いボタンの「作成」をクリック。
名前だとタイプだのを入力していく
「タスクの数」という項目があるがこれはなるべく少ない数の方がいい。後々スケールできるので。逆にここを50とかにすると常に50起動してしまうことになりコストがかかる。
入力が終わったら右下の「次のステップ」
ネットワーク構成の画面が出てくるのでネットワークを設定してく
ここではvpcはデフォルトのもの。
サブネットはALBでAZとして指定したものを使う。(ただこれはもしかしたら間違ってるかもしれない)
下に行くと「ロードバランサーの種類」があるのでALBを選択
「ロードバランサー名」には先程作成したものを選択
「ロードバランス用のコンテナ」という欄の中に「ロードバランサーに追加」というボタンがあるので追加
追加すると新たなコンテンツが現れる。その中の「プロダクションリスナーポート」を80:HTTPに指定
その少し下にある「ターゲットグループ名」で先程作成したターゲットグループを選択
右下の次のステップを押す。Auto Scalingを設定するページが出てくるがここは今は何もしない。次のステップ。
確認ページが出てくるので確認したら「サービスの作成」で作成する。
7. セキュリティグループの修正
今のままでALBのDNSにアクセスすると503エラーが返ってくる。
クラスタに割り当てたセキュリティグループを確認
セキュリティグループの画面で該当のものを選択し、[Edit inbound rules]をクリック
既存のルールを一旦削除する。
追加ボタンを押し↓のように設定する
セキュリティグループではALBで指定したものを選択。保存する。
8. 確認
該当のALBのDNSをコピーしてブラウザのURL欄に打ち込んで確認
参照
Hapiの公式チュートリアルに載ってるコードだとDockerでうまく動かない
https://hapi.dev/tutorials?lang=en_US
↑これに載ってる
'use strict'; const Hapi = require('@hapi/hapi'); const init = async () => { const server = Hapi.server({ port: 3000, host: 'localhost' }); await server.start(); console.log('Server running on %s', server.info.uri); }; process.on('unhandledRejection', (err) => { console.log(err); process.exit(1); }); init();
このコードだとDockerで起動はできるがリクエストをちゃん受け付けなかった。
host: 'localhost'の部分を消すとうまく動く。
const server = Hapi.server({ port: 3000, // host: 'localhost' });
react-native-background-geolocationについてのあれこれをまとめてく(随時更新予定)
https://github.com/transistorsoft/react-native-background-geolocation
を使っているのだが、機能が結構豊富だったり使い方が少し複雑に感じたので調べたこととか気づいたことをまとめてく。
既にある程度使っているのでセットアップから順にとかではない。メモりたい事をその都度書いていく。
検証は全て個人で行なったものなので保証はできません。
State.enabledはユーザー許可のことではない
これはトラッキングが有効になっているかどうか。
位置情報使用の許可のことだと思っていたので少し戸惑った。
falseの場合はトラッキングが行われない。つまり移動してもアクションは起こらない。
true when the SDK has been enabled via methods start or startGeofences. When false, the SDK is completely OFF. No tracking of any kind will occur. The SDK will consume no energy.
一度trueにしたらアプリをリロードしてもtrue。そして端末から位置情報を無効にしてもtrue。
なので基本的にアプリで一回trueにすればいい。
端末から位置情報OFFにしたりするとうまく機能しないことあったので基本的にリロードごとに毎回1回
(state) => { if (!state.enabled) { BackgroundGeolocation.start(); } },
は行った方がいい。
BackgroundGeolocation.start()
でtrueにできる。