Be an Engineer.

社会人からWEBエンジニアになった人間の備忘録的勉強記録

ファイル保存毎にコマンドの自動実行ができる modd が便利

modd、あまり多くその存在を聞くことがなかったのですがとても便利なツールだったので、個人的なまとめの意味も込めて紹介します。

moddとは

github.com

moddとは ファイル変更を検知して何かしらのコマンドを実行するためのツール です。 例えば、

  • コードを変更したら都度テストを実行させたい
  • Webアプリケーションのコードを書いているときに、変更を追加したのでサーバを再起動する(livereload)

これらの操作をmoddを使うことによって自動的に行うことができるようになります。

利用例のイメージ

参考までにイメージしやすくなるかもしれないので、moddを利用している時の動きを以下に載せます。

https://raw.githubusercontent.com/shirakiya/modd-sample/main/docs/sample.gif

このサンプルは以下のリポジトリに置いています。

github.com

インストール

moddの README に書かれています。要点をかい摘むと、

  1. go get
  2. Homebrew(macOS
  3. releaseパッケージをダウンロード

の3つの方法でmoddを取得することができます。modd自体はGoで書かれているため利用者側も楽で良いですね。

Dockerコンテナで使ってみる

例えば以下のようなDockerfileでビルドするとmoddが使えるイメージを用意できます。
これは主に開発向けのイメージを作ることを意識したDockerfileであり、これはあくまで一つの例であることはご留意ください。

# moddコマンドだけ欲しい状況なので、
# tgzからmoddを取り出すことができるようなstepを入れておくとgoodか
FROM alpine:3.12.3 as builder
WORKDIR /opt
ADD https://github.com/cortesi/modd/releases/download/v0.8/modd-0.8-linux64.tgz .
RUN tar xvf modd-0.8-linux64.tgz

# goが入っていないイメージの例としてpythonイメージを利用している
FROM python:3.9.1
COPY --from=builder /opt/modd-0.8-linux64/modd /usr/local/bin/

# 他の準備...

CMD ["modd"]

設定してみる

使うには「どのファイルを検出対象として、どのコマンドを実行するか」の設定をする必要があり、modd.conf ファイルに書きます。( modd.conf はmoddで決められた設定ファイル名のデフォルトであり、modd実行時に --file={file} と指定することで任意のファイル名にすることができます。)

以下にいくつか例を挙げます。しっかり README に書いてくださっているので、詳細についてはそちらを見てみるのがよいです。

ファイル変更を検知してコマンドを実行したい時

*.py {
    prep: python -m unittest
}

この例であれば、*.py に該当するファイルが保存されると python -m unittest が実行されます。

コマンドをlivereloadしたい時

*.py {
    prep: python -m unittest
    daemon: python main.py
}

この例であれば、*.py に該当するファイルが保存されると、その都度 python -m unittest が実行された後に、moddプロセスが管理している子プロセス python [main.py](http://main.py) にSIGHUPシグナルが発行され、再起動します。

※ この設定を使っているのが上記のGIFのものとなります。

起動時に一度だけあるコマンドを実行したい時

{
    prep: echo hello
}

この例であれば、 modd の起動時に一度だけ echo hello が実行されます。


このツールの作者でもコントリビュータでもないですが、非常に便利だったので紹介しました。livereloadが実装されたWeb Application Frameworkも多いですが、開発するものはその限りではなく適用できる場面が意外にありとても重宝しているので、作者の方には本当に感謝です。

Google Mapsで任意の場所に指定の距離の円を置けるWebサービスを作った

作ったものはこちらです。名前は「尺々(しゃくしゃく)」と言います。

syakusyaku.shirakiya.com

きっかけ

私が現在働いている会社でもそうなのですが、家賃補助で「会社から〇〇km圏内で××円支給」というのがよくあるかと思います(今まで働いてきた会社ではこうした福利厚生があったのでよくあると言ってますが、世の中的によくあるのかは...?)。

そのときに 会社の住所から〇〇km県内の場所をGoogle Mapsで調べる ことは多々あるかと思いますが、そのときにブラウザで使えるツールで使いやすいものがないなーと常々思っていました。そこで決定版的なツールを作ろうと思ったのがきっかけです。

使い方

尺々は2つの機能があります。以下にそれぞれの機能について軽く説明します。

任意の距離の円を地図に置く

これが基本的なこのサービスの使い道だと思います。会社等の中心を選んで円を落とすことができます。

使い方の流れはこちらの動画をご覧ください。

youtu.be

2住所間の距離を測る

実はGoogle Mapsでもできることではあるのですが、2つの住所間の距離も測定できるようにしてします。会社の住所とこれから借りようとしている部屋の住所の正確な距離を知りたいというような欲求が生まれるかなと思ったためです。

こちらも使い方の流れを動画にしたのでご覧ください。

youtu.be

UIパーツが散らばってないだったり使いやすさ重視で作ってみました。
とのたまっていますが、なにぶん画面デザイン力に乏しいので決定版にはなれてるかは甚だ疑問ですね(自虐)

機能についてなど、なにかご意見等がございましたら @shirakiya831 までお願いします。

Amazon ECSのScheduling tasksのターゲットの設定変更を行う場合はCloudWatch EventsのAPIを叩かないといけない話

タイトルだけでもう話は終わっていますね(汗)

shirakiya.hatenablog.com

Amazon ECS + CodeDeploy でタスク定義を更新するにはCodeDeployのAPIを叩かないといけないよと、この記事を昨日投稿したばかりですが、同様にAmazon ECSのScheduling tasks(以下スケジューリングタスク)でタスク定義を更新しようとした時に少しだけハマったことを書きます。

したかったこと

Amazon ECS(以下ECS)利用中、コードの変更を行いデプロイするためにECSのタスク定義だけ更新することはよくあると思います。流れで書くと以下のような感じでしょうか。

  1. 機能追加やバグ修正等で、コードを変更
  2. 最新コード用いてDocker imageをbuild
  3. ECRにimageをpush
  4. 最新imageを使った新しいrevisionのタスク定義を作成
  5. スケジューリングタスクのターゲットに設定しているタスク定義を最新のタスク定義を使うように変更

3のECRへのpushや、4のタスク定義の更新などはECR/ECSのそれぞれのAPIを叩けばいいのですが、5のスケジューリングタスクのターゲットを変更するにはECSのAPIにはそれらしいものがなく、どのAPIを使うべきかパッとわかりませんでした。

で、色々調べたところ、結論としてCloudWatch EventsPutTargetsを叩けばいいようです。

CloudWatch Events のターゲット

ECSのスケジューリングタスクに出てくるターゲットは「CloudWatch Events」の中に出てくるターゲットのことを指しています。そもそもCloudWatch Events ターゲットとは、cron記法等で記述されるルールがトリガーされた時にCloudWatch Eventsがinvokeするものを指す用語で、利用可能なAWSサービスは以下のページにズラッと記載されてます。

docs.aws.amazon.com

この中に「ECS タスク」が含まれており、スケジューリングタスクはこれを利用するわけです。

ターゲットの更新

実際にターゲットの更新を行うには、AWS CLIだと以下のようなコマンドです。

$ aws events put-targets \
  --rule test-schedule \
  --targets='[{"Id": "test-target", "Arn": "<クラスターのARM>", "RoleArn": "<ターゲットロールのARN>", "EcsParameters": {"TaskDefinitionArn": "<タスク定義のARM>", "TaskCount": 1, "LaunchType": "FARGATE", "NetworkConfiguration": {"awsvpcConfiguration": {"Subnets": ["subnet-xxx"], "SecurityGroups": ["sg-xxx"], "AssignPublicIp": "ENABLED"}}, "PlatformVersion": "LATEST"}}]'

{
    "FailedEntryCount": 0,
    "FailedEntries": []
}

タスク定義を最新のものを使いたい場合は TaskDefinitionArn の内容だけを更新すればいいというお話でございました。

まとめ

Amazon ECSのスケジューリングタスクのターゲットを更新したい場合に叩くべきAPICloudWatch EventsのPutTargets でした。

熟達者だと「スケジュール + ターゲット」という用語の組み合わせからCloudWatch Eventsのターゲットのことかな、と察することもできるのでしょうね。
とはいえ何かのご参考になれば幸いです。

AWS ECS/FargateのデプロイタイプをBlue/Green(CodeDeploy)にしたときにデプロイ実行で叩くべきAPI

久しぶりにこちらに書きます。(関係ないですけど、QiitaとBlogの使い分けって難しいですよね。

主に自分のスキルアップを目的としてサンプルアプリ的に稼働させている https://jaaxman.shirakiya.com/ というWebサイトのFargate化を進めていたときにデプロイで少しハマったことを書きます。

したかったこと

Web appの実行環境をEC2からFargateに載せ替えるにあたり、デプロイの自動化も進めていました。

f:id:shirakiya:20190210221322p:plain:w600
CircleCI+ECSのデプロイフロー

Web appのデプロイの手順は上の図のような形で作戦を練っていました。

  1. productionブランチにpush
  2. テスト通過後にdocker image作成・ECRにpush
  3. タスク定義を更新(2のimageを使う)
  4. サービスを更新(3のタスク定義を使う)し、既存タスクを最新のサービスを使ったタスクに入れ替える

1はGitの操作なので除きますが、2〜4の操作はCI上(今回はCircleCIを使っています)で行う操作なので、AWSAPIを叩く必要があります。
2と3は普通にECRにpushし、タスク定義をupdateするためのAPIを叩くことで実現できます。公式にもドキュメントがあるのでこれらが参考になります。

イメージのプッシュ - Amazon ECR
RegisterTaskDefinition - Amazon EC2 Container Service

サービスのデプロイはデプロイタイプによって利用するAPIが異なる

今回の話題の中心は4のデプロイについてです。
Amazon ECSではサービスのデプロイ方法(=デプロイタイプ)は2種類の方法が利用できます。

  1. ローリング更新
    • サービスを更新すると最新版のサービスを使ったタスクを自動で入れ替える
  2. Amazon CodeDeployを利用したBlue/Greenデプロイ
    • 最新版サービスを使ったBlue環境を稼働し、その後に本番用トラフィックを流す
    • 本番用トラフィックを流す前に検証したりすることが可能

実はこの2種類のデプロイタイプのそれぞれで叩くべきAPIが異なります。

  1. ローリング更新 ⇒ ECSのUpdateService
  2. Blue/Greenデプロイによる更新 => CodeDeployのCreateDeployment

ズバリここでハマってしまいました。
勉強がてら進めていたためローリング更新を試してからCodeDeployのBlue/Greenを試すという流れで作業をしていたのですが、CodeDeployを利用した場合はサービスを更新したいのに サービスを更新するAPIを叩く必要は無い のです。

もう少し具体的に見ていきましょう。

デプロイタイプ「ローリング更新」の場合

デプロイタイプを ローリング更新 にしている場合はAWS CLIを用いると以下のような操作でデプロイを行うことができます。(最小限のオプションです)

$ aws ecs update-service \
  --cluster test-cluster \
  --service test-rolling \
  --task-definition test:2

これを叩いた後にサービスのイベントタブを開くと、以下のようにタスクが ea8369c11af3441e9128970e8f4562d6 から 4cd48c97bd3c4f55bc40b6e4a576d892 に入れ替わっていることが見て取れます。

f:id:shirakiya:20190210221445p:plain

つまり「サービスをデプロイするにはサービスを更新(=update-service)すればよい」のです。まぁなんかイメージ通りですね。

デプロイタイプ「Blue/Greenデプロイによる更新」の場合

さて、デプロイタイプを Blue/Greenデプロイによる更新 にしている場合に上記のように update-service を叩くとどうなるでしょうか。

$ aws ecs update-service \
  --cluster test-cluster \
  --service test-codedeploy \
  --task-definition test:2

An error occurred (InvalidParameterException) when calling the UpdateService operation: Unable to update task definition on services with a CODE_DEPLOY deployment controller. Please use Code Deploy to trigger a new deployment.

結果、InvalidParameterExceptionで怒られてしまいました。デプロイするならCodeDeployのdeploymentをトリガーしろと言っていますね。
このようにCodeDeployを使っていると、UpdateServiceを叩いたところでデプロイすることはできません。デプロイする場合は以下のようにCodeDeployの create-deployment を叩く必要があります。(一部マスクしてます)

$ aws deploy create-deployment \
  --application-name AppECS-test-cluster-test-codedeploy \
  --deployment-group-name DgpECS-test-cluster-test-codedeploy \
  --revision '{"revisionType": "AppSpecContent", "appSpecContent": {"content": "{\"version\": 1, \"Resources\": [{\"TargetService\": {\"Type\": \"AWS::ECS::Service\", \"Properties\": {\"TaskDefinition\": \"<タスク定義ARN>\", \"LoadBalancerInfo\": {\"ContainerName\": \"nginx\", \"ContainerPort\": 80}}}}]}", "sha256": "192a44b8191ec68bb5bd4861d4960065bdb148d98e9ef74a5b4d9b6930f179b0"}}'

{
    "deploymentId": "d-XXXXXXXXX"
}

これでCodeDeployによるデプロイプロセスが開始されました。

まとめ

ECSのデプロイはデプロイタイプによって叩くべきAPIが異なります。

  • ローリング更新
    • Amazon ECS の UpdateService(=aws ecs update-service
  • Amazon CodeDeployを利用したBlue/Greenデプロイ
    • AWS CodeDeploy の CreateDeployment(=aws deploy create-deployment

以上、何かのご参考になれば幸いです。

【Jaaxman】日本語に翻訳した論文の検索機能をつけました

jaaxman.shirakiya.com

当ブログでのJaaxmanの紹介記事はこちら↓

shirakiya.hatenablog.com

そのJaaxmanに本日、検索機能をつけたものをリリースしました。

改めてJaaxmanの説明を簡単にしますと、arXiv.orgstat.ML/cs.AI の2カテゴリの論文のタイトルとAbstractをGoogle翻訳で日本語化したものが一覧で見れるWEBアプリです。

元々、日付やカテゴリなどで表示される論文情報のフィルタリングができるようにはしていましたが、記事数も多くなりやはり検索機能はほしいと思い、今回のアップデートを進めました。

使い方

論文情報のタイトル検索を行うための入力欄が右上近くにあるので、こちらから検索したい単語を入れ、「検索」のボタンを押すと検索にヒットした論文情報のみを表示します。

f:id:shirakiya:20180722221516g:plain

検索の対象は、

  1. タイトル - 日本語版
  2. タイトル - 原文(英語)

の2つで、日本語の検索ワードで検索すると日本語版のタイトルを、英語の検索ワードでは英語版のタイトルを対象として検索を行います。上のGIFのように混合の場合でも日本語・英語それぞれの検索ワードでタイトルの検索を行います。 一方、Abstractは検索対象には含まれませんので、ご注意ください。

完全に作者都合の不定期なアップデートとはなりますが、お役に立ちましたら嬉しいですね。

arXiv.orgの人工知能に関する論文を日本語で一覧できるサイト Jaaxman を作った

f:id:shirakiya:20180107214410p:plain:w300

jaaxman.shirakiya.com

Jaaxmanという名前です。
人工知能関連の論文は専ら arXiv.org に掲載されており、特に stat.MLcs.AI というカテゴリが付けられてSubmitされていることが多いです。

普段それらの論文で新しいものを拾い読みするときは、FeedlyarXiv.orgのRSSを連携させてリスト化したものを見ていました。しかし、恥ずかしながら英語を見て脳にダイレクトに情報が入ってこず、情報を脳に入れるためには英語読むモードに切り替えないといけず、英語読むモードはかなり脳のスタミナを消費してしまうので、気軽さに欠けるものがありました。(慣れの問題とはわかっていますが...)

そこで「タイトルとAbstractだけでも日本語化したらスッと脳に入ってくるのでは?」と思ったのが制作のきっかけでした。

できること

f:id:shirakiya:20180107214214g:plain

arXiv.org の stat.ML/cs.AI の2カテゴリの論文のタイトルとAbstractをGoogle翻訳で日本語化したものが一覧で見れる

これに尽きます。基本的に「更新された論文を通勤中の電車内で流し見する」ことを最も重要なユースケースとしていたため、凝った検索などの機能は特別用意していません。
逆に気になった論文はPocketやTwitterなどのシェアができるようにパーマリンクを用意しました(シェアボタンは重たくなるので置きたくなかった)。他にも新規Submitだけのものをフィルタリングできたりします。
ホントは更新があったら通知があれば良いのになぁと思っていたりしますが、それはおいおい。

やっていること

朝の6時に arXiv.org の stat.ML/cs.AI の2カテゴリのRSSの更新分のタイトルとAbstractをGoogle Translate APIにかけて保存してします。
WEBサイトは普段仕事でPythonでサーバサイドのコードしか書いてなかったので、久しぶりにJavaScript書きたいと思い Vue.js でSPAとして構築しています。

一応コードはこちら。

github.com

あと、別にロゴとかいらんでしょとか思ってたのですが、少し調べてみるとLOGASTERというサービスでそれっぽいロゴが1000円ほどで買えたので、1000円ぐらいなら出すかと思い、買いました。1000円だろうが、ロゴがあるのとないのとでは製作時のやる気アップ度が全然違ったのでいい買い物したと思います。(ちなみに .aiなどのイラストレーション用ソフトに対応したファイルは1000円のプランだと含まれていないのですが、そもそも使えないので必要ありませんでした。)

作ってみて気づいたこと

アカデミックな文章に対するGoogle翻訳の精度はそこそこ高いという印象を持っていて、実際にAbstractの翻訳を読んでみるとめちゃめちゃいい精度で翻訳されていてGoogle様すごいという気持ちになりました。しかしながら、コンピュータサイエンスにおいて「英語で言われた方がわかる(というか誤訳?)」ということがままあることに気づきました。

  • 「bandit algorithms」→「盗賊アルゴリズム
  • 「butterfly effect」→「蝶効果」

これはあくまで一例ですが、逆にGoogle翻訳のクセを見抜いて日本語を見たときに何を言っているのかを少し考えるということが必要だというのは若干の本末転倒感があり、残念ポイントでした。

メンテナンス頻度

自分が使っていく中で不都合なりが発生した場合は対応しおうかなと思っていますが、めちゃめちゃ丹精込めて機能改善を行う予定はあまりないです。ですが、強い要望などがあれば対応できる範囲で行おうとも思っています。
一方で、オープンソースとしていますので(誰も興味がないとは思いますが)ご興味のある方は見ていただいても構わないと思っています。

基本的に自分のために作ったものではありますが、誰かのためにお役に立てれば幸いです。

Boostnoteは良いMarkdownエディタ

f:id:shirakiya:20171115031019p:plain

めっちゃ久しぶりの更新。

当方エンジニアで、日々手順やメモを取ることが多いが、これまで理想とするMarkdownエディタには巡り会えていなかった。

これまでのMarkdownエディタ遍歴

  1. Kobito
  2. Dropbox Paper
  3. Atom

どれも満足はしていない中で使い続けてきて、そろそろ個人的な決定版が欲しかった。
Markdownエディタに求めるものは以下の点。

  1. 「フォルダ」のような概念があること
  2. 異なるPC間でメモが同期できること
  3. 一覧性が高いこと
  4. 安い(月額料金は払いたくない)
  5. データのexportができること

「フォルダ」

ここでフォルダと言っているのは、例えばEvernoteのノートブックに対応するイメージで、中にあるメモがある分類でまとめられるものとしている。このフォルダのようなものがあれば、例えばMySQLに関するメモを作成するときは「MySQLフォルダ」にメモを保存しておけば、MySQLのメモを探すときにまず「MySQL」フォルダに見にいけばいい。
メモを見返すときにフォルダがあれば圧倒的に楽になると思っている。(何かを思い出すときや探すときに、そういう階層構造のようにインデックスを作って、思い出している気がする。)

残念ながらKobitoにはフォルダはなく、編集した順序でメモが並ぶというのが不満足だった。
また、Dropbox Paperはフォルダはあるものの、メモの編集画面とは異なる画面にフォルダの一覧画面があるため、別タブに表示している一覧にタブ移動しないといけないのが煩わしかった。
Atomは左カラムにディレクトリの階層構造が常に表示することができるのでGood。

異なるPCでの同期

当然ながら、自分の作業メモであったり何かのライブラリに関するメモは、いつでもどのPCでも見れるような状態にしておきたい。

Kobitoで同期をしようと思うと月額480円のプレミアムプランに入らないといけない。
Dropbox Paperなんかはそもそもクラウドの保存しているメモをブラウザ上で編集するのでこの点は良かった。

一覧性が高いこと

メモを探す時にとても重要。
Dropbox Paperはフォルダ毎にメモ一覧ページがあり、別のフォルダのメモ一覧を見ようと思うと一度フォルダ一覧ページに戻ってから再び見たいフォルダからメモ一覧ページに遷移しないといけず、なかなか煩わしい。(フォルダ毎だけでなく全メモ一覧ページがあるものの、それだとフォルダ毎にまとまらないのでNG)

安い

一般的な庶民なもので、やはり安いにこしたことはなく、ただ良いMarkdownエディタなのであれば多少の金額は払うつもりでいた。

データのexportができること

あまり優先度が高いわけではなかったが、やはりデータのexportができる方が嬉しい。いつそのエディタがサービス・開発中止になるともしれないので、いざとなったときに簡単に移行できるような備えはあった方が安心。

以上のような観点でエディタを探したときに巡り合ったのがBoostnoteだった。

Boostnote

BoostnoteOSS製のプログラマ向けMarkdownエディタで、無料で利用可能である。
Electronをベースにしているが故にMacWindowsLinuxと使えるプラットフォームの幅も広く、またiOSAndroidでもネイティブアプリがある。すごい。

基本的に使い方はGithubWikiといくつか使い方に関する記事があるので、それらを見るとだいたいわかる。

上に記した求める点に対してBoostnoteの良さをつらっと書いていく。

「フォルダ」

Boostnoteでは「Storage」と呼ばれるものがフォルダに相当するもので、好きなようにラベルが付けられて言うことなし。

異なるPCでの同期

Dropbox や GoogleDrive を使えば可能。
Boostnoteは初期設定の中で、メモのrawデータ(CSONデータ)を格納するディレクトリを指定する。このディレクトリを例えば Dropbox や GoogleDrive などの同期ディレクトリ内に指定することによって、同期しているデバイス同士ではデータを共有することが可能になる。
https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing

一覧性が高い

特に気に入っているところだが、Boostnoteは様々な観点からメモを一覧にして閲覧することができる。

  1. 全メモ一覧(All Notes)
  2. スター付きメモ一覧(Starred)
  3. 各Storage毎のメモ一覧(Folders)
  4. 各タグ毎のメモ一覧(Tags)

これだけ一覧で見る方法があると、メモも見つけやすい。(あとElectronアプリの割に動作がサクサクでそれも見つけやすさに遠からず寄与している気がする。が、メモが増えると遅くなるなどの検証はしていないのでここは何とも言えない。)

安い

無料。最高。ありがとうございます。

データのexportができること

メモ一件毎にプレーンテキストファイルあるいはMarkdownファイルにexportすることは可能。ただし、全件一度にexportすることはできない。(最悪CSONをパースしてどうにかするというスクリプトを書けばいいか、とも思っている。)

まとめ

総じてとても使いやすいと思っているMarkdownエディタで、かなりライフチェンジングな思いをしている。文字ばかりで伝わらないよなぁと思いつつ非常にオススメなので一度使ってみてはいかが?