macosでVimライクなキーバインディングを使う

macosではemacsライクなキーバインディングをデフォルトで使用できます。 Ctrl+F, B, P, Nで上下左右に移動できるので、十字キーに指を持っていく必要がありません。

www.capa.co.jp

しかし、vimで作業するときは当然Ctrl+H, J, K, Lで移動するため、無意識の誤操作が増えてきました。 またサーバサイドエンジニアとなると、どうしてもviで作業することもあります。

そこで、通常のバインディングVimライクに変更することにしました。

Karabinerをインストールします。

pqrs.org

Complex ModificationsからAdd ruleをクリック。

KarabinerPreference1
KarabinerPreference1

Import more rules from the Internetでブラウザが開きます。

KarabinerPreference2
KarabinerPreference2

Vi Style Arrows を検索して、 Import します。

KarabinerPreference3
KarabinerPreference3

Karabinerに戻ったら、有効にしたいRuleをEnableにします(Ctrl以外にもありますね)。

KarabinerPreference4
KarabinerPreference4

これでViと同じ上下左右の移動ができるようになりました。 ただし、当然これをするとデフォルトのCtrl+Kによるカーソルから右を切り取り がオーバーライドされるので、多用していた場合は注意が必要です。

Visual Studio for Macでデバッグできないとき

LeetCodeやAtCoderが流行っているので久々にC#を書こうとしたら詰まったのでメモ。

  1. Visual Studio for Macをダウンロード
  2. .NET Coreをダウンロード
  3. Visual Studioで適当にConsole Appを作成
  4. Console.WriteLineにBreakPointを置いてデバッグ実行
Debugger operation failed 
launch: program '' does not exist.

f:id:suzusin:20190326194844p:plain

調べたところ、dotnetへのpathが通っていないとのことだった。

$ dotnet
zsh: correct 'dotnet' to 'done' [nyae]? n
zsh: command not found: dotnet
$ ln -s /usr/local/share/dotnet/dotnet /usr/local/bin
$ dotnet
zsh: correct 'dotnet' to 'done' [nyae]? n

Usage: dotnet [options]
Usage: dotnet [path-to-application]

Options:
  -h|--help         Display help.
  --info            Display .NET Core information.
  --list-sdks       Display the installed SDKs.
  --list-runtimes   Display the installed runtimes.

path-to-application:
  The path to an application .dll file to execute.

linkを貼ることで無事デバッグできるようになった。

docker-composeのProjectという概念について

大本のディレクトリを分けても、同名フォルダ配下にあるymlを元に docker-compose up するとRecreating されてしまう。

例えばmyProjectに開発用のymlがあるとする(volumes等々だいぶ記述を省いている)。 フォルダ名をmyProjectとする。

myProject/docker-compose.yml

version: '2'

services:
  nginx:
    image: nginx
    container_name: "nginx-dev"
    ports:
      - "8080:80"

  app:
    build: ./php
    container_name: "app-dev"

普通に起動すると、こうなる。

$ docker-compose up -d
Creating network "compose_default" with the default driver
Creating app-dev   ... done
Creating nginx-dev ... done
$ docker-compose ps
  Name                 Command              State          Ports
------------------------------------------------------------------------
app-dev     docker-php-entrypoint php-fpm   Up      9000/tcp
nginx-dev   nginx -g daemon off;            Up      0.0.0.0:8080->80/tcp

あまり使うことはないが、docker ps でも見てみる。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
3e845fb43f2e        nginx               "nginx -g 'daemon of…"   53 seconds ago      Up 52 seconds       0.0.0.0:8080->80/tcp   nginx-dev
d60726667f0e        myproject_app         "docker-php-entrypoi…"   53 seconds ago      Up 52 seconds       9000/tcp               app-dev

コンテナ名はそれぞれ、ymlのcontainer_nameで指定したものになっている。 ただ気にしていなかったのは、appコンテナはDockerfileから作っているので、myproject_appというIMAGE名になっている点。

この環境を検証環境やステージングで使おうとしたとき、2環境欲しいなと思うことがある。 1つの環境はチームメンバーが通常開発に使用する安定的なもので、もう1つは設定や構成を変更する開発案件で使用するもの。

そこで、ymlを分けて以下のように管理することにした。

/myProject
|--docker-compose.yml
|--php
| |--Dockerfile
|--ymlfiles
| |--docker-compose.staging.develop.yml
| |--docker-compose.staging.stable.yml

ポートフォワーディングでホスト側を分ければ2環境同時に使うことができると考えた。

myProjectはgit cloneしてきた同じものだが、その上の階層で分けている。

  • /home/webmaster/stable/myProject/ymlfiles
  • /home/webmaster/develop/myProject/ymlfiles

そしてコンテナ名もそれぞれ変更した。これで問題ないように思えた。

version: '2'

services:
  nginx:
    image: nginx
    container_name: "nginx-staging-stable"
    ports:
      - "8080:80"

  app:
    build: ../php
    container_name: "app-staging-stable"
version: '2'

services:
  nginx:
    image: nginx
    container_name: "nginx-staging-develop"
    ports:
      - "8080:80"

  app:
    build: ../php
    container_name: "app-staging-develop"

stableを立ち上げる。

$ docker-compose -f docker-compose.staging.stable.yml up -d
app-staging-stable is up-to-date
Starting nginx-staging-stable ... done

$ docker-compose -f docker-compose.staging.stable.yml ps
        Name                      Command              State          Ports
-----------------------------------------------------------------------------------
app-staging-stable     docker-php-entrypoint php-fpm   Up      9000/tcp
nginx-staging-stable   nginx -g daemon off;            Up      0.0.0.0:8080->80/tcp

developを立ち上げる。

$ docker-compose -f docker-compose.staging.develop.yml up -d
Recreating app-staging-stable   ... done
Recreating nginx-staging-stable ... done
szk416s-MacBook-Pro:~/study/myProject/ymlfiles szk416 $ docker-compose -f docker-compose.staging.develop.yml ps
        Name                       Command              State          Ports
------------------------------------------------------------------------------------
app-staging-develop     docker-php-entrypoint php-fpm   Up      9000/tcp
nginx-staging-develop   nginx -g daemon off;            Up      0.0.0.0:8080->80/tcp

なんと、 Recreatingされてしまい、先に作ったapp-staging-stableとnginx-staging-stableは消えてしまった。

docker ps で見ても同じ。

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
d569715fafaf        nginx               "nginx -g 'daemon of…"   56 seconds ago      Up 54 seconds       0.0.0.0:8080->80/tcp   nginx-staging-develop
159d41b57e5b        ymlfiles_app        "docker-php-entrypoi…"   56 seconds ago      Up 54 seconds       9000/tcp               app-staging-develop

何が起こったのか?

docker-compose にはProjectという概念がある

公式ドキュメントにはちゃんと書いてあるし、確認するコマンドもある

-p, --project-name NAME 別のプロジェクト名を指定 (デフォルト: directory name)

各設定ファイルはプロジェクト名を持っています。 -p フラグでプロジェクト名を指定できます。フラグを指定しなければ、Compose は現在のディレクトリの名前を使います。詳細は COMPOSE_PROJECT 環境変数 をご覧ください。

cf. docker-compose コマンド概要 — Docker-docs-ja 17.06.Beta ドキュメント

ここでいう、 フラグを指定しなければ、Compose は現在のディレクトリの名前を使います というのが重要で、 docker ps の結果の方を見ると、 ymlfiles_app と、ディレクトリ名 + サービス名になっていることがわかる。

つまり、いくら大本のディレクトリから分けていたとしても、親ディレクトリが ymlfiles なので同じプロジェクトとして扱われてしまっていた。 基本的にはない話だが、本番環境などであればシャレにならない。

そもそも、環境変数にymlを指定する手段があるところを見ると、複数立てるようなことはしない方が良いのだろう。

suin.io

フォルダごとに.envを置いてPROJECT_NAMEを指定する手段もあるようだが、こういうのは後からチームに加わった人が気付きづらいので良くないと考えている。

結局、ymlfiles-stable, ymlfiles_develop のように分けて管理することにした。 愚直だが一番わかり易いと思う。

安全なcron書き換え方法のメモ

  • 備忘録
  • いくつか宗派があるらしい

はじめに

オススメの手順

  1. sudo crontab -l > crontab.bak
  2. cp -p crontab.bak crontab.new
  3. vi crontab.new
  4. sudo crontab -l | diff crontab.new -
  5. sudo crontab crontab.new
  6. sudo crontab -l | diff crontab.bak -

説明

  1. 現在のcron 設定一覧を bakファイルに書き出し
  2. それを newにコピー(存在する場合は上書きとなる)
  3. 作成した newを書き換える(ここで本来行いたかった変更)
  4. 現在の設定と newを比較
  5. 作成した newファイルを食わせて反映
  6. 変更箇所を念のため確認

その他

  • これらの手順でも、結局typoで -r を打ったらしょうもないのでコピペで行きましょう。
  • すぐに走らせたくても余裕を持って2分先くらいを指定しましょう。

モバイルオーダーサービスのO:derでラーメンを食べてきた

O:derはスマホで飲食店の注文を行い、並ばずに受け取れるというサービスです。

スマホ注文ならモバイルオーダーアプリの「O:der(オーダー)」 www.oderapp.jp

興味を持った理由は、前職のオフィスで願っていたことを実現する仕組みだったためです。

当時のオフィスは30階建てのオフィスビルで、1〜3階に飲食店などが入居しているというよくあるパターン。 御昼時はオフィスワーカーで長蛇の列という、こちらもよくあるパターン。 自席から注文を行い、飲食店に着いた頃に料理を受け取ることができたら、と考えていたものでした。

時は流れ私はそのオフィスから去りましたが、そんな考えを実現しているアプリがあると知り、早速使ってきました。

アプリを開くと、現在位置から近い順に利用可能店舗が表示されました。 うーん、まだ店舗数はそんなに多くないようです。 今回は通勤経路にあり、現在地からも近かった大崎のラーメン屋さんに行くことにしました。

f:id:suzusin:20181218215757p:plain:w250

お店の前に行くと、券売機が煌々と光を放っているので若干怯みます。

f:id:suzusin:20181218220401j:plain:w250

この店舗は先程の画像にもあったとおり、着席後に店内で使わなければいけないようです。 店内を見ると席数が限られていることがわかり、席の確保までは担保できないよ、ということが察せました。やむ無し。

さて、いざ入店するわけですが、「先に券売機で食券をお求めください!」と言われるのかどうか問題が残っています。

少し考えた結果、スマホを触りつつ(あ、わたしO:derで注文中です。。。)という雰囲気を出しながら着席することにしました。

店員さんはこちらを一瞥すると「お好きな席にどうぞ」と声をかけてきました。

やりました。成功したようです。

席について、メニューを選びます。

f:id:suzusin:20181218221310p:plain:w250

確認画面に移ります。座席の確認はここでありました。

f:id:suzusin:20181218221350p:plain:w250

購入します! ちなみに事前にクレジットカードを登録してあります。

f:id:suzusin:20181218221443p:plain:w250

注文後はアプリで進捗を見守ります。

f:id:suzusin:20181218221549p:plain:w250

待つこと数分...

ついに誰とも会話せず、券売機に触れることもなく、ラーメンが届けられました🎉

f:id:suzusin:20181218221733j:plain:w250

料理が完成するとプッシュ通知が来るとのことでしたが、先に店員さんが来て、その後に通知が来ました。

これはたまたま店内の人数からして、私の注文だと特定できたためと思われます。

また料理の注文・完成はメールでも来ていたので、あとから確認もできます。

ポイントも貯まるようです。

f:id:suzusin:20181218222134p:plain:w250

まとめ

  • モバイルオーダーサービスのO:derを使ってみました
  • 店舗によってはスマホから事前注文できるので混雑時間帯等かなり便利になりそうです
  • 導入店舗がまだ少ないので今後に期待したいです

Microservicesの有償の勉強会に参加した話

昨日、下記の勉強会に参加しました。

reedex.connpass.com

無料の勉強会は山程ありますが、有償のものは結構めずらしいです。 そういった会だけに、メモを全部ここに書くのはよろしくなさそうなので、気になったトピックと感想を残すまでにします。

まずは以下の記事を元に、アーキテクチャについてのお話がありました。 クラサバとかの話はSI時代を思い出して懐かしかったですが、マイクロサービス登場までの流れは個人的には今更メモするまでもないのでスルーしました。

オーケストレーションとコレオグラフィについて

書籍『マイクロサービスアーキテクチャ』でも触れられています。

マイクロサービスアーキテクチャにおけるオーケストレーションとコレオグラフィ - Qiita )

この事例を元に説明を受けると、とてもわかりやすかったです。

RESTful APIの設計の話

  • Entity Service Anti-Patternに気をつけましょうという話

Entity Services is an Antipattern

API as a Product というコンセプト

https://restful-api-guidelines-ja.netlify.com/

  • Zalandoはzozoのようなヨーロッパのサービス
  • APIを提供してサーボパーティに売ってもらうビジネスモデルらしい

とてもしっかりまとまっていて参考になります。 ちょうど先月、またマイクロサービスを考慮したうえでAPIを設計・実装する機会があっただけに、もう少し早くこれを知れていたら…

最後のメッセージは、つい忘れがちな話。

APIの設計はその先に利用者がいてそれを使って商売するのであることを忘れずに

講師の川島さんはとても穏やかな口調で、またところどころで考え、解釈する時間の余白があって良かったです。

Markdownでスライドを作れるMarpを使って、社内勉強会でDockerの話をしました

毎週末の社内勉強会、弊社は若手の子が思い思いの発表をすることが多いです。 それはそれで良いのですが、そもそも自分たちが開発に使っているものの理解を深めるのも良い機会かなと思い、話をすることにしました。

また弊社のサービスはマイクロサービス化の道半ばであるため、コンシューマサービスのみがECSを使ったモダンな環境。 それ故に同じ開発部のエンジニアであっても担当業務によってスキル差があることが気になっており、 とりわけDockerは“なんとなく”使っている人が多いと感じられたので、今回のテーマに選出しました。

当初は勉強会駆動で自分でも学習をして、k8sの話をしようと思っていたのですが、前述の理由から順番に攻めることにしたのです。

それともう1つ、今回はMarkdownでスライドを作成できるMarp を使って時短でスライドを作成しました。 これまではKeynoteを多用してきており、凝り性の性格と相まってスライドが綺麗と言って頂くことも多かったのですが、 綺麗でも中身が薄くなるよりは、確実に時間を割いて来てくれた人に価値を届けたいと思い、時間のかけ方を変えました。

f:id:suzusin:20181117200332p:plain

今回はみんなが“なんとなく”使っていることを課題として設定したので、 なぜ便利で使うのかを理解してもらうことと、 日頃の業務ではあまり触れる機会がない(が、今後マイクロサービス化が進むと触れなければならない人たちに)触れる機会を増やしてもらうことを目標にしました。

やはりハンズオンは楽しいという声があったので、swarm, docker-compose, k8sと連続モノとして続けていければ理解が深まるかなと思いました。

また、Markdownで書いたことで、こうしてこのままblogにも貼り付けることができるのでアウトプットにもしやすいので良かったです。

続きを読む