読者です 読者をやめる 読者になる 読者になる

Spring Boot開発時に見ると良い記事まとめ

Spring Boot開発時に参考になるドキュメントのまとめです。

general

トランザクションマネージャ

Bean

Docker

Lombok

  • setter/getterを作ってくれるやつ
  • builderパターンをやってくれる

日付

ログ

Gradle

Config

Controller

アノテーションまわり

DockerでNginxをシュッと構築する

フロントエンドでちょっとした作業があった際に、ぱっと確認するためにWebサーバが必要だったのですが、 そこでDockerを利用したところ大変便利だったのでメモを残したいと思います。

やりたいこと

  • ローカルにコマンド一発でWebサーバーを構築したい
  • 手元のファイルを編集したらブラウザを更新するだけで反映されてほしい
  • ポート番号がかぶらないように80番以外のポートで確認したい

解決策

  • docker-composeを使ってnginxを一コマンドで構築する
  • dockerのvolume機能を使ってホストのディレクトリをマウントしリアルタイムで変更を確認できるようにする
  • envsubstで環境変数をコンテナ起動時に埋め込む

DockerでNginxを構築する

上記の解決方法を実際に試してみます。

ちなみに、今回使用したツールのバージョンは以下のとおりです。
docker: 1.13.1
docker-compose: 1.11.1

まず適当なディレクトリを用意します。

$ mkdir nginx
$ cd nginx

次にdocker-compose.ymlファイルを作成し、保存します。

web:
  # 公式のdockerイメージ
  image: nginx 
  volumes:
   # ホスト側のnginxの設定ファイルのテンプレートをコンテナ側にマウント
   - ./mysite.template:/etc/nginx/conf.d/mysite.template
   # コンテンツを含むディレクトリをマウント
   - <表示したいhtmlを含むディレクトリのパス>:/var/www
  ports:
  # ポートを設定(ホスト:ゲストの順)
   - "8080:80"
  environment:
   - ROOT=/var/www/
  command: /bin/sh -c "envsubst '$$ROOT' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"

volumesでホストのディレクトリをマウントすることで、dockerを再起動せずにローカルファイルの変更を反映できるようにしています。
また、commandenvironmentに設定した環境ファイルをテンプレートに埋め込みnginxの設定ファイルを生成した後、nginxの起動を行っています。 ちなみに、'daemon off;'はデーモン化(background実行)をしないようにするための設定です。 dockerはルート・プロセスをフォアグラウンドで動かさないとコンテナが停止してしまうためこの設定が必要になるようです。

ここまでできたら、同じディレクトリにnginxの設定ファイルのテンプレートファイル(mysite.template)を作成します。

server {
    listen 80;
    server_name localhost;
    root    ${ROOT};
    index index.html; 
}

これで準備完了です。 docker-composeを実行してnginxを起動してみましょう。

$ docker-compose up

これで、nginxが起動しブラウザから確認できるようになったと思います。 ポートを変更したい場合はdocker-compose.ymlのportsのホスト側を変更すれば任意のポートでアクセスできます。

まとめ

dockerを使ってnginxをシュッと構築する方法を試してみました。 一度configファイル・テンプレートを作成しておくと次回からは少し修正するだけで簡単にwebサーバを作成できますので大変便利だと思います。

参考文献

Firebaseでチャットアプリのサンプルを作った

TL;DR

チャット機能があるアプリをAWSで作ろうとしたが意外と難しそうだったのでFirebaseを試してみた

モチベーション

AWS導入事例では ALBの下にEC2やコンテナを並べてRedisのpub/subで…みたいなことをしていて結構大掛かりになりそうでした。 これは大規模な例ですが、AWSでチャット機能を実装しようとするとどうしてもSocket.io・WebSocket等を使うことになります。

今作りたいアプリではチャットはメインの機能ではないしフルスクラッチで開発するのは工数的にも厳しいので、 出来合いのものを埋め込むかPaaSを利用してもうすこし簡単に作りたい。 少し調べたところLayerというものを見つけましたが、 まだ完全にビジネスに耐えれるものでは無さそうでしたので諦めて、FirebaseのRealtimeDBを使ってみることにしました。

やったこと

チャットを実装するチュートリアルが公開されていたのでそれをやってみます。

https://codelabs.developers.google.com/codelabs/firebase-web/index.html#0

このチュートリアルでは以下の内容を網羅できるので今回のアプリにはぴったりでした。

  • Firebaseのプロジェクト作成
  • Googleアカウント認証機能
  • Firebase Realtime DBでメッセージの送受信
  • 画像の送受信
  • notificationの実装
  • デプロイ

所感

ちょっと機能がたりてない感がありますが、思ってた以上に簡単にチャット機能を実装でました。
本当はサーバーサイドでメッセージを受信したらイベントドリブンでプッシュ通知を相手側に送るみたいなことをやりたかったのですが、 Firebaseだけでは完結できませんでした。やるとしたらサーバー立ててRealtimeDBの全トピックをListenしてmessageがあったらプッシュ通知API叩くみたいなことをやらないといけない気がします。
pushイベントをhookできればLambdaでサーバレスできそうなので少し残念。 料金は高いですが初期のフェーズはFirebase Realtime Databaseを使用してスケールしてきたらチャット基盤を構築するということにしておくとそれほど問題にはならなさそうです。
圧倒的な速度でチャット機能を実現できるのでとりあえず迷ったらこれで作ってみるのが良さそうです。

Amazon Cognitoの認証フローを調べた

Amazon Cognitoを使う機会があったので調べたことをまとめました。

Amazon Cognitoとは

Amazon Cognitoはユーザの認証やデータ同期を提供するサービスです。

以下の3つの機能があります。

  • Cognito User Pool
    • AWSが提供する認証システム
  • Cognito Federated Identities
    • 任意の認証システムをつかったサインアップ機能の提供
  • Cognito Sync
    • ユーザデータ同期

今回はFederated Identitiesについて調べました。

Cognito Federated Identities

Cognito フェデレーテッドアイデンティティでは次の様なことができます。

  • ユーザの一意のIDを生成
  • Cognito User Poolや外部の認証システム(Facebook, Twitter等)と連携しユーザを認証
  • 権限が制限された一時的なAWS認証情報をクライアントに提供
  • 未認証ユーザにもIDを発行し一時的な認証を提供することができる

仕組み

Facebookを認証システムとして利用する場合、 iOSAndroidSDKのメソッド名等の細かい部分は異なるが大まかなフローは以下の通りです

https://github.com/takatori/blog/raw/master/entries/20170405/img/Cognito.png

  1. AWS SDKFacebookとの認証を行う
  2. FacebookがOAuthトークンをSDKに返す
  3. 取得したOAuthトークンをパラメータとしてCognitoのGetIdを呼び出す
  4. Cognitoは受け取ったトークンからidを生成もしくは既にある存在するidを取得して返す
  5. SDKが受け取ったidを指定してクレデンシャル情報取得APIを呼び出し
  6. Cognitoが一時的なクレデンシャル情報を返す

他にも認証フローがありますが、上記の方法が最も一般的なやり方のようです。

まとめ

Cognitoは機能がたくさんあり、ドキュメント分量が多いので一見複雑なことをしているように見えますが、 整理してまとめてみると意外とシンプルなフローで認証が行われていることがわかりました。 ドキュメントに書いて有ることを自分でかきなおしてみるのも結構勉強になりますね。

参考

2016年振り返り

大晦日なので2016年を振り返りたいと思います。

仕事

2016年で一番大きいかったのはやはり社会人になって東京に移動したことです。 以下仕事内容を時系列に従って振り返ってみます。

4月に入社すると二週間研修が行われ、その後すぐに案件に配属されました。 そこで、メインのエンジニアとしてServerlessの新規Webサイトの設計・開発を行うことになりました。 レビューを頂きながらですがサーバーサイドを一人で開発し、戸惑いながらもなんとか9月にリリースすることができました。 9月からは再び新規案件を任されここでもServerlessで開発を行うことになりました。 また、並行してインターン生の指導と内定者のメンターに任命されました。 10月からはJava・Play Frameworkの案件も始まり現在は2つの案件を同時に進めています。 11月にはTechLeadに任命されました。TechLeadとしてはまだ何もできていませんが、来年度は社内の若手で行う勉強会を企画しようと思っています。 12月に二つ目のServerless案件の第一弾をリリースしました。

新卒ですが様々なことを経験できて非常に勉強になった一年でした。趣味でWebサービスを開発するだけでは身につかなかった知識をたくさん身につけることができたと思います。 一方で実力不足を痛感した年でもありました。特にインフラ周りの知識が足り低なさすぎてとても一人で案件をまわせる段階ではないです。 来年はプロのエンジニアとして案件の技術的判断をひとりですべてできるように努力していかなければならないと反省しました。

つかった技術

読んだ本

Github

f:id:takatorix:20161231210529p:plain

4月から毎日コミットを心がけていましたが、途中途切れている箇所がいくつもある上に、内容のないdotfileの更新だけという日が多々ありました。 また、自分のリポジトリに対するコントリビュートしかなくOSSに全く貢献できていないです。

ブログ

hatenaブログ -> hexoで生成したブログをgithub pageで公開 -> hatenaブログと遷移したこともあり、ブログの内容より見た目やサービスにこだわりすぎて投稿数を増やすことができませんでした。来年はまず内容を充実することを目指します。

失敗したこと

失敗したことは数え切れないぐらいあるのですが、思いついたものを適当にあげます。

  • 朝起きる時間が遅い

    • 朝はやく起きれた日は一日緊張感を持って作業ができますが、遅くなってしまった日は全く集中できていなかったことが多かったです
    • 特に休日は昼間で寝過ごすと何も作業ができないので気をつけていきたいです
  • 部屋選び

    • 生活しやすい街の駅から徒歩5分圏内で綺麗で安いと割といい感じの物件を選んだはずだったのですが、いかんせん狭すぎました。
    • ロフトを含めると普通の広さぐらいなのですが、ロフトは使いづらすぎました。
    • 机を置けないと家で作業しづらすぎる...
  • Mac Book Air

    • 仕事でMBPを支給されるのに購入してしまった
    • 殆ど使っていないのでもったいないことをした
    • 時間があればArchをインストールして遊びたい

来年の目標

  • ブログを毎月書く
  • 勉強会で1回以上発表する
  • OSSに1回以上コントリビュートする
  • 毎日commit
  • 国内旅行3回

まとめ

東京に来てから様々な勉強会でいろんなエンジニアと関わって自分の技術力が足りていないことを痛感しました。 来年は最低でもここに上げた目標を達成し、まともなエンジニアになりたいです。

crateをcrates.ioに公開してみる

これはRust その2 Advent Calendar 2016 - Qiita11日目の記事です。

このエントリではcrateをcrates.ioに公開する方法を紹介します。

crates.ioとは

Cargo用のセントラルパッケージリポジトリです。

https://crates.io/

Cargoはこちらから依存するcrateを取得します。 また、作成したcrateの公開もCargoから実行可能です。

crates.ioでは一度公開されたcrateが非公開化・削除されないようcrateのバージョン管理を行っています。 発行できるバージョン数に制限はありませんが、 一度発行したバージョンを上書き・削除することはできないので公開する際には注意が必要です。

それでは、crates.ioにcrateを公開する方法を紹介していきます。

crates.ioのアカウントを作成する

crateを公開するためにはcrates.ioにGithubアカウントでログインし、 APIトークン取得する必要があります。

cargo.ioのページからGithubアカウントでログインします f:id:takatorix:20161210213626p:plain

Account Settingsページに移動し、APIトークンを取得します f:id:takatorix:20161210213622p:plain

f:id:takatorix:20161210213633p:plain

取得したAPIトークンをCargoに登録するために、以下のコマンドを実行します。

$ cargo login <APIトークン>

このコマンドはローカルの~/.cargo/configにトークンを保存しています。

Cargo.tomlに情報を追加する

cargo new で生成されたCargo.tomlファイルには以下の情報が記載されます。

[package]
name = "rawst"
version = "0.1.0"
authors = ["takatori <takatorix@gmail.com>"]

上記の情報のみでもcrateを公開することが可能ですが、 より検索に引っかかりやすいようメタデータを追加していきます。

[package]
name = "rawst"
version = "0.1.0"
authors = ["takatori <takatorix@gmail.com>"]

license = "MIT"
description = "The interactive tool for AWS CLI written in Rust"
repository = "https://github.com/takatori/rawst"
readme = "README.md"
keywords = ["rawst", "aws"]

この他に、homeページやdocumentページを指定することもできます。

また、バージョン管理システムでignoreされているファイルは自動的にパッケージから除外されますが、 excludeで除外するファイル・ディレクトリを明示的に指定することもできます。

[package]
# ...
exclude = [
    "public/assets/*",
    "videos/*",
]

逆に、includeでpackageに含めるものを指定することもできます。

crateの名前は先着順に割り当てられるため、すでに使用されているものは使えないので気をつけてください。

パッケージング

次にcrate.ioにアップロードできるフォーマットにcrateをパッケージングします。

$ cargo package

このコマンドを実行するとtarget/packageディレクトリに.crateファイルが生成されます。

.crateファイルは現在のとろこ、最大10MBまでしかアップロードできないのでサイズの大きな画像ファイルなどはexclude指定すると良いでしょう。

また、コミットされていないファイルがある場合以下のようなエラーが出ます。

error: 1 dirty files found in the working directory:

すべてのファイルをcommitまたはstashするか--allow-dirtyフラグを付けることでパッケージングできるようになります。

公開する

それではcrateをcrates.ioにアップロードします。

$ cargo publish

この段階で依存crateのバージョンをワイルドカードで指定している場合、以下のようなエラーが発生します。

error: api errors: wildcard (`*`) dependency constraints are not allowed on crates.io. 

ワイルドカードは許可されていないので、明示的にバージョンを指定する必要があります。

publishが成功すると以下のようにcrates.io-indexリポジトリにindexが登録されていることが確認できます。

https://github.com/rust-lang/crates.io-index/blob/master/ra/ws/rawst#L1

発行したバージョンを取り下げる

誤ってバージョンを発行してしまった場合yankコマンドで取り下げることができます。

$ cargo yank --vers 1.0.1

このコマンドはcrates.ioに公開されたデータを削除するのではなく、 指定したバージョンを新たに使用できないようにします。 すでにこのバージョンを指定しているプログラムからは引き続き使用することができます。

一度発行してしまったバージョンはどうあがいても変更できませんので、 誤ってクレデンシャル等の情報を含めて発行してしまった場合、クレデンシャルの方を即座に変更する必要があります。

まとめ

cargoを使ってcrateをcrates.ioに公開する方法を紹介しました。 簡単にパッケージを公開できるのでどんどん開発していきましょう!

参考

Rustの勉強をはじめました

最近よく聞くようになったプログラミング言語Rustの勉強をはじめました。

Rustとは

なぜRust?

  • システムプログラミングを勉強したかったので
  • 関数型っぽくもかけそう

勉強題材

最近、いろんな言語をちょっとだけ触ってやめる、みたいなことを繰り返しているけど今回はガチ