Node.js+Serverless+AWSでお手軽サーバレスアプリを作る: 事前準備
Serverlessフレームワークをもちると、手軽にサーバレスアプリを構築することができます。 今回はNode.js v12 と AWSをもちいてサーバレスアプリを作る事前準備について説明します。
The Serverless Application Framework | Serverless.com
Serverlessアプリケーションの作成
AWS上にNode.jsのServerlessアプリケーションを作成するには以下のコマンドで作成できます。
mkdir sls-sample $ npm install -g serverless $ sls create --template aws-nodejs
handler.js, serverless.yml の2つが作成されます。
API経由でLambda関数が動作するようにする
初期の設定だとLambda関数とHttpイベントが紐付いていないので serverless.ymlを開いてコメントアウトされているHttpイベントの部分を以下の様にコメント外します。
functions: hello: handler: handler.hello # The following are a few example events you can configure # NOTE: Please make sure to change your handler code to work with those events # Check the event documentation for details events: - http: path: users/create method: get
AWS認証情報の設定
AWSのWebコンソール上でIAMユーザを作成してAdministrator Accessのポリシーをアタッチします。
AWS アカウントでの IAM ユーザーの作成 - AWS Identity and Access Management
次に、以下のリンクを参考にローカル環境にAWSの認証情報を設定します。
これでローカル環境からすべてのAWSサービスの操作ができるようになります。
デプロイ
以下のコマンドを実行することで、Serverlessアプリケーションがデプロイされます。
$ sls deploy
ServerlessアプリケーションはAWSではCloudFormationとしてデプロイされます。
sls deployの出力結果は以下のようになっています。
Service Information service: sls-sample stage: dev region: us-east-1 stack: sls-sample-dev resources: 12 api keys: None endpoints: GET - https://xxx.execute-api.us-east-1.amazonaws.com/dev/users/create functions: hello: sls-sample-dev-hello layers: None
ここに表示されている GET - https://xxx.execute-api.us-east-1.amazonaws.com/dev/users/create を実際にリクエストしてみます。
$ curl https://xxx.execute-api.us-east-1.amazonaws.com/dev/users/create { "message": "Go Serverless v1.0! Your function executed successfully!", "input": { "resource": "/users/create", "path": "/users/create", "httpMethod": "GET", "headers": { ...
handler.jsの内容を実行することができました。
Adobe XDをつかってFlutterアプリ実装にやさしいデザインを作成する
Flutterでは、iOS/Androidのクロスプラットフォームアプリを簡単に実装することができます。 ただし、デザインによっては実装コストが高まってしまうので、Adobe XDを使って実装するエンジニアにむけて心がけていること、それはFlutterで簡単に実装できるUIをデザインすることです。
Adobe XDの使い方をそもそも勉強する
そもそもUI/UXデザインの基礎については今回は書きませんが、もしAdobe XDのような、UI/UXデザインソフトを利用したことがない場合はAdobe XD公式のチュートリアル のクイックスタートの項目だけでも目をとおしておくと良いかと思います。
特にリピートグリットはリストビューのような反復するUIを簡単に作成することができるため、必ず覚えると良いと思います。
XDことはじめStep1:まずはここから!「ワイヤーフレームを作ってみよう」 |
Material DesignのUIキットを入手する
Flutterでは基本的にはMaterial DesignベースのUIが簡単に実装できるように設計されています。
左上のハンバーガーメニューの UIキットを入手
> マテリアルデザイン
からダウンロードすることができます。
基本的にはUIキットのコンポーネントから利用するようにして、独自のコンポーネントをつくって実装コストを高めないようにします。
Material Designに定義があっても、Flutterではコンポーネントが準備されていない場合もあります。その場合はデザインの方を修正するようにしています。
デザインに対応するPackageがあるかどうかは常にエンジニアに確認しながらデザインする
サードパーティのパッケージを利用するようなUI/UXデザインにする際も、実装コストが高まりすぎないように常にエンジニアに確認しながら実装するようにします。
Adobe XD to Flutterは利用しないのか
Adobe XD to Flutterというプラグインを使うと、Flutter向けのコードが自動生成できますが、あまり自動生成系を信用していないのと、基本的には実装が楽になるようにデザインしているので利用していません。
うまく活用している事例知りたいです。
Heroku+Rails Netlify+Next.jsを中心としたWebアプリ構成
Heroku+Rails Netlify+Next.jsを中心とした構成でWebアプリを構築したのでメモです。
構成図
今回利用した技術スタック
SPAアプリ
Next.jsはReactを使ってSPAを作成するシンプルなフレームワークで、今回は利用しませんが洗練されたSSRも対応しています。
API + 管理画面
PaaSについて
Netlify
フロントエンドはNetlify を利用しました。 以下の機能を容易に設定することができるためです。
- フロントエンドのビルド機能
- CDN配信
- SSL設定
- Githubとの連携 (特定ブランチへのプッシュ、Pull Request時にプレビューアプリのデプロイ)
- パスワード設定機能(stg環境等を一部の人に公開するため)
Heroku
バックエンドのPaaSはHerokuを利用しています。 Railsのデプロイ先としては歴史があり、こちらも容易に利用できるCD機能、CLI、APIがあらかじめ揃っていることが強みです。
もしセキュリティレベル的に1段階上げたい要望がある場合、Private SpaceというVPCで動作させることができるプランもあります。
インフラやパイプラインの更新もherokuのサイクルに乗っかることで保守面のコストを下げることを狙いとしています。
またAdd-onで様々なサービスと連携が可能で、今回はメール配信に mailgun 、DNS管理にPointDNSを利用しています。
Netlify + Next.js ビルド設定
Next.jsには以下のscriptがあります。
next build
プロダクションビルドnext export
静的サイトとしてout
フォルダに書き出し
package.jsonにnpm scriptとして以下のように設定し
"scripts": { ... "build": "next build", "export": "next export" }
Netlifyのbuild設定は以下のようにしています。
APIサーバのBASE_URLなどはNetlifyのビルドの環境変数にセットし、 webpackのDefinePluginを用いて、静的ビルド時に注入するようにしています。
Next.js では next.config.js
で webpackの設定を変更することができます。
const webpack = require("webpack"); const devApiUrl = 'https://example.com'; module.exports = { webpack: (config) => { config.plugins.push( new webpack.DefinePlugin({ API_BASE_URL: JSON.stringify(process.env.API_BASE_URL || devApiUrl), SENTRY_DSN: JSON.stringify(process.env.SENTRY_DSN), SENTRY_ENVIRONMENT: JSON.stringify(process.env.SENTRY_ENVIRONMENT), }); return config; } };
Heroku デプロイ設定
RailsのパイプラインはDocker Containerを用いず、Herokuのスタックを利用しています。(これは好みかもしれません) デフォルトのスタックを利用することで、特に他のAPMなどを導入せずにRubyのmetricsを見ることができます。
現在見れるものとしては以下です。
- Puma Pool Usage
- Free Memory Slots
- Heap Objects Count
導入方法も非常にかんたんで、Heroku側は Metricsのページの設定でRuby Language MetricsをONにして、heroku/metrics
のbuildpackを追加するだけです。
Rails側は Barners gemをインストールする必要があります。
gem "barners"
Heroku Add-on設定
Heroku Add-onは追加すると、基本的に環境変数にサービスを利用するための認証情報が追加されます。
(例: Heroku Postgresであれば DATABASE_URL
に接続情報が入っている)
このあたりは適当に追加して、アプリのコードで環境変数から設定値を受け取れるように設定しました。
利用したAdd-Onは以下です。
その他利用サービス
webpack2->4とbabel6->7のアップグレード作業ログ
2017年から運用されているNode.jsのプロジェクトのwebpackとbabelのバージョンアップ作業をしたので、作業ログを残しておきます。
アップグレードしたバージョン
- babel 6 -> 7
- webpack 2 -> 4
Babelのアップグレード
Babel6 -> 7 は各パッケージ名が変更されていて、パッケージアップグレードで対応できません。 babel-upgrade をつかって、package.jsonと .babelrc をアップグレードすることができます。
npx babel-upgrade --write
いきなり最新のbabelの設定に生まれ変わります。
diff --git a/.babelrc b/.babelrc index 6cfcd56..bfb063f 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,25 @@ { - "plugins": ["transform-runtime", "babel-plugin-transform-flow-strip-types"], - "presets": ["es2015", "stage-3"] + "presets": [ + "@babel/preset-env" + ], + "plugins": [ + "@babel/plugin-transform-runtime", + "@babel/plugin-transform-flow-strip-types", + ["@babel/plugin-proposal-class-properties", { "loose": true }], + ["@babel/plugin-proposal-decorators", { "regacy": true }], + "@babel/plugin-proposal-do-expressions", + "@babel/plugin-proposal-export-default-from", + "@babel/plugin-proposal-export-namespace-from", + "@babel/plugin-proposal-function-bind", + "@babel/plugin-proposal-function-sent", + "@babel/plugin-proposal-json-strings", + "@babel/plugin-proposal-logical-assignment-operators", + "@babel/plugin-proposal-nullish-coalescing-operator", + "@babel/plugin-proposal-numeric-separator", + "@babel/plugin-proposal-optional-chaining", + "@babel/plugin-proposal-pipeline-operator", + "@babel/plugin-proposal-throw-expressions", + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-syntax-import-meta" + ] }
(使ってるところはなさそうだけど) @babel/plugin-proposal-decorators
と @babel/plugin-proposal-pipeline-operator
だけ、そのままでは動かなそうだったのでオプションを追加
diff --git a/.babelrc b/.babelrc index bfb063f3..2a985dd4 100644 --- a/.babelrc +++ b/.babelrc @@ -6,7 +6,7 @@ "@babel/plugin-transform-runtime", "@babel/plugin-transform-flow-strip-types", ["@babel/plugin-proposal-class-properties", { "loose": true }], - ["@babel/plugin-proposal-decorators", { "regacy": true }], + ["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true, "regacy": true }], "@babel/plugin-proposal-do-expressions", "@babel/plugin-proposal-export-default-from", "@babel/plugin-proposal-export-namespace-from", @@ -17,7 +17,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-optional-chaining", - "@babel/plugin-proposal-pipeline-operator", + ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }], "@babel/plugin-proposal-throw-expressions", "@babel/plugin-syntax-dynamic-import", "@babel/plugin-syntax-import-meta"
すべての箇所のrequireをimportに書き換えられたら良かったのですが、歴史のあるプロジェクトではそういうわけにもいきませんでした。 歴史的経緯でexport defaultに指定されているものをrequireする部分は以下のようにしました。
const lib = require('./lib.js').default // .defalutを追加
webpack.config.jsの変更
webpackを2 -> 4 に変更するので、当然のようにwebpack.config.js の設定が違います。
一旦webpack4で新規プロジェクトをつくって、ひとつひとつ同等の設定をしていきました。
はまったポイントとしては、webpack4では process.env.NODE_ENVの環境変数が最適化で文字列に置換されてしまうので。 実行時に環境変数から与えたいので以下のように設定しました。
module.exports = { ... optimization: { nodeEnv: false // process.env.NODE_ENVを文字列に置換しない }, ...
なるべく CJSのimportのスタイルに治す
requireを全文検索してimportのスタイルに変更
Windows+WSL2+Docker+VSCodeでdocker開発環境を作る
最近 Thinkpad X1 Extreamを購入しました。
Thinkpad x1 extream来たぜ pic.twitter.com/X1QaB6L5sE
— Shoichi Takagi @ DEPARTURE (@fly1tkg) 2020年1月18日
開発業務は基本Ubuntuでやっていきたいのですが、Windowsでしか動かないアプリたち(Adobe、MSOfficeなど)も使っていきたく。ホストOSはWindows 10 Home, 開発用としてWLS2 (Windows subsystem for Linux 2) を利用していくことにしました。
はじめはVirtualBoxを準備しようかと思いましたが、WSL2はプレビューながら業務で使えると同僚からちょっと聞いていたので、今回はこちらにしてみました。
また、最近VSCodeのRemote拡張がイケてるので合わせて導入していきます。
WSL2のインストール
WSL 2 のインストール | Microsoft Docs を参考にやってきます。
Insider Programに参加
Windows Insider Program | Get the latest Windows features に参加して、OSのアップデートをします。 僕はここでアップデートし忘れてはまりました。
Ubuntuのインストール
Windows StoreからUbuntuをインストールしました。
Windows Storeアプリを起動して、Ubuntu と検索してくれば出てきます。
WSLを有効にする
Powershellを管理者権限で実行(右クリックで選べる)してWindows Subsystem for Linux と仮想マシンプラットフォームのオプションコンポーネントの両方がインストールされていることを確認します。
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
実行後再起動します
WSL2に変更する
Powershellで以下のコマンドを実行しました。
wsl --set-version Ubuntu 2
ここまでスタートメニューからUbuntuをえらんで起動できます。
Dockerのインストール
ここから先はUbuntuのコンソールで実施していきます。
Ubuntuにdockerをインストールして、自分のユーザをdockerグループに入れます。
$ curl -fsSL https://get.docker.com -o get-docker.sh $ sudo sh get-docker.sh $ sudo usermod -aG docker {your-user}
docker起動
$ sudo cgroupfs-mount
$ sudo service docker start
動作確認としていつものdockerのhelloworldを実施してみました。
https://hub.docker.com/_/hello-world
$ docker run --rm hello-world
VSCodeのインストール
Visual Studio Code - Code Editing. Redefined からダウンロードして、インストール。
インストール後、拡張機能 ms-vscode-remote.remote-wsl
を入れます。
インストール後、Ubuntuのコンソールで code
コマンドが使えるようになっているので、任意のプロジェクトフォルダで以下コマンドを実行すると、Windows側でVSCodeが開き、プロジェクトフォルダ内のファイルを編集できます。(便利、、!)
$ code .
ファイル共有
WSL -> Windowsの参照は
/mnt/c
配下がWindowsのCドライブがマウントされているので、WSL上からWindowsのファイルを読み書きすることができる。
逆に Windows -> WSL
の参照は\wsl$
というネットワークドライブがアクセスできる(Exploreでここに移動すると見られる)
ので、クイックアクセスにピン止めしておいた
そのほかやったこと
Windowsのビーブ音を消す
なんか、tabで補完するたびにビープ音が出るので、OSの設定で消しました。
.inputrc
で制御できるみたいなのですが、sshした先とかでビープ音なっちゃうし、そもそもWindowsのビープ音腹立つのでいったんこの設定で様子見ます。
WSL向けのターミナルを入れる
複数Windowで開くなどが標準のターミナルだとできないようだったのでwslttyというターミナルを導入しました。
IoTエンジニア目指してラズパイを触り始めたメモ
突然ラズパイ(ラズベリーパイ)を使って電子工作をしてIoTエンジニア目指せる気がした、年末休暇を使って一通り勉強してみました。
ラズパイのセットアップとLチカ(LED点滅という電子工作におけるHello World的なもの)までのまとめです。
準備したもの
最近、忙しいので全部秋月電子通商の通販で取り寄せました。便利!
- OTGケーブルは持ってたのでので実際には購入していません
名称 | 通販コード | リンク |
---|---|---|
カラー図解 最新 Raspberry Piで学ぶ電子工作 作って動かしてしくみがわかる | S-10851 | 【書籍】カラー図解 最新 Raspberry Piで学ぶ電子工作 作って動かしてしくみがわかる: 電子工作便利商品 秋月電子通商-電子部品・ネット通販 |
Raspberry Piで学ぶ電子工作 パーツセット | K-10852 | Raspberry Piで学ぶ電子工作 パーツセット: 電子工作便利商品 秋月電子通商-電子部品・ネット通販 |
Raspberry Pi WH(ラズベリーパイゼロ ダブルエイチ)本体 | M-12961 | Raspberry Pi Zero WH (ラズベリーパイゼロ ダブルエイチ) 本体: マイコン関連 秋月電子通商-電子部品・ネット通販 |
ニクロムはんだこて KS-30R(30W) | T-02536 | ニクロムはんだこて KS−30R(30W): 電子工作便利商品 秋月電子通商-電子部品・ネット通販 |
はんだこて台 ST-11 | T-02537 | はんだこて台 ST−11: 電子工作便利商品 秋月電子通商-電子部品・ネット通販 |
はんだ 0.8mm | T-02594 | はんだ 0.8mm: 電子工作便利商品 秋月電子通商-電子部品・ネット通販 |
スイッチングACアダプター(USB ACアダプター) MicroBオス 5V3A | M-12001 | スイッチングACアダプター(USB ACアダプター) MicroBオス 5V3A: 電源一般 秋月電子通商-電子部品・ネット通販 |
HDMIメス⇔miniHDMIオス変換コネクタ | C-13431 | HDMIメス⇔miniHDMIオス変換コネクタ: パーツ一般 秋月電子通商-電子部品・ネット通販 |
USB OTGケーブル microB 10cm | C-13430 | USB OTGケーブル microB 10cm: パーツ一般 秋月電子通商-電子部品・ネット通販 |
TOSHIBA マイクロSDカード(microSDHC)EXCERIA 32GB 100MB/s | S-14515 | TOSHIBA マイクロSDカード(microSDHC)EXCERIA 32GB 100MB/s: 雑貨 秋月電子通商-電子部品・ネット通販 |
その他、HDMIケーブル、ディスプレイ、キーボードは必要です。
OSの準備
普段Webサーバで慣れてるので、CLIだけでいけるっしょとイキって家のネット環境がよくなく、取り急ぎDesktop無しの Raspbian Buster Lite
をダウンロードしました。
Debian Busterのラズパイ向けディストリビューションのようです。
イメージのダウンロード後、balenaEtcher
というツールでSDカードにイメージを書き込みました。
いろいろつないで起動!
下記のようにログインを要求されたら user名 : pi
パスワード : raspberry
を入力します
raspberrypi login: pi Password: raspberry
初期設定
下記設定は下記コマンドで実施できます
sudo raspi-config
Wifiの設定
仕事部屋からルータが遠く、物理接続がつらいのでまずWifiを設定します。
2 Network Options
を選択し N2 Wifi
を選択します。
繋ぎたいWifiのSSIDとパスフレーズを入力すれば利用できるようになります。
キーボード設定
4 Locarization Options
> I3 Change Keyboard Layout
から設定できます。
僕はUSキーボードなので、Generic 101-key PC > Other > English (US) > English (US) を選択
修飾キーの設定も出てくるのですが、よくわからないので雰囲気でエンターを連打しました。
SSHの設定
5 Interfacing options
> SSH
からSSHの設定をONにする
その後、別LAN内のPCからSSHしてみる
# ユーザ名@IPアドレス # パスワードは raspberry ssh pi@192.168.0.177
ラズパイのIPアドレスがわからない場合、下記コマンドでwlan0
の ローカルIPアドレス( inet
の値)を確認する
ifconfig
または、リモートPCから下記コマンドを実施して、ラズパイ WH のMACアドレスからも見つけられます。
arp -a # b8:27 から始まるMacアドレスを探す
Vimの設定をする
エディタはVimでやりたいので設定をしました
sudo apt install vim
vimrcには下記を記載しました
set expandtab set tabstop=4 set softtabstop=4 set shiftwidth=4
Lチカをする
あとは、書籍の内容に沿ってLチカをしました。
配線は+極から22ピン(GPIO 25)-> LED -> 330Ω抵抗 -> GND となるようにしています。
書籍ではIDLEというPythonの環境を利用していましたが、僕はデスクトップをインストールしていないんので普通にコマンドラインで実施しました。
下記のように非常にシンプルなコードでGPIOと呼ばれるピンの電圧を制御できます。
""" 書籍より引用 """ import RPi.GPIO as GPIO from time import sleep GPIO.setmode(GPIO.BCM) GPIO.setup(25, GPIO.OUT) try: while True: GPIO.output(25, GPIO.HIGH) sleep(0.5) GPIO.output(25, GPIO.LOW) sleep(0.5) except KeyboardInterrupt: pass GPIO.cleanup()
下記コマンドでプログラムを実行します。
python main.py
これが、、Lチカ! pic.twitter.com/XMFTvrSxls
— Shoichi Takagi @ DEPARTURE (@fly1tkg) 2019年12月22日
電源を消す
電源ボタンとかついてないので、下記コマンドでシャットダウンします
sudo shutdown -h now
感想
普段触っているLinuxやweb技術を使ってリアルな世界のインプット・アウトプットできるのすごく楽しいし、可能性を感じました、、!
CloudVision APIのテキスト認識をpython3から利用する
CloudVision APIのテキスト認識を使うと安価に高精度の画像のOCRが利用できるのですが、pythonのサンプルが公式ドキュメント内で整理されていない感があり、少し手間取ったので自分用のメモとして残しておきます。
やったことは以下です。
# -*- coding: utf_8 -*- import io import os import json import glob from pprint import pprint # Google Cloud client libraryのインポート from google.cloud import vision from google.cloud.vision import types from google.protobuf.json_format import MessageToJson def annotate(basename): # 画像のファイルパス file_name = os.path.join( os.path.dirname(__file__), 'resources/{}'.format(basename)) # 画像のロード with io.open(file_name, 'rb') as image_file: content = image_file.read() image = types.Image(content=content) # 日本語のヒントを与える image_context = types.ImageContext(language_hints=['ja']) response = client.text_detection(image=image,image_context=image_context) # JSON ファイル書き出し serialized = MessageToJson(response) data = json.loads(serialized) f = open('results/{}.json'.format(os.path.splitext(basename)[0]), 'w') f.write(json.dumps(data,ensure_ascii=False)) f.close() # クライアント初期化 client = vision.ImageAnnotatorClient() # resources フォルダ内の画像をすべてAPIに投げる paths = glob.glob("resources/*.jpg") for path in paths: annotate(os.path.basename(path))