まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

自作のマークダウン CMS を一週間ほど自分だけで使ってみて、まあまあな感じだったので一般公開します。

"My info" を略して "Mynfo" と名付けています。ソースコードは GitHub に公開してます。自分でも使ってみたい場合はフォークして使ってください(フォーク先は public でも private でも構いませんが、public の場合は GitHub 上のコンテンツが公開される点に注意してください):
https://github.com/dotnsf/mynfo


また、サンプルとして(皆さんには編集権限はありませんが)この公開ソースコードで作ったコンテンツサービスを以下で公開しています:
https://mynfo.herokuapp.com/


実際にみなさんもこの仕組みを使ってコンテンツサービスを公開する場合、必須ではありませんが heroku のアカウントを所有している場合は自分の GitHub リポジトリにコンテンツをコミットすることで CI/CD で最新コンテンツに更新できる仕組みがあります(しかもこの方法だとコンテンツの更新履歴が Git 側に残る、という大きなメリットがあります)。この機能を使う想定で設定方法を README.md 内で解説しているので、heroku アカウントと併せて使うことを推奨します(試しにローカルホストで動かしてみる、程度であれば不要です)。


【ローカルホストで動かしてみる】
試しにローカルホストで動かすには Node.js 環境が必要です。事前にセットアップしておきましょう。

フォークしたコードを git clone して、npm install してから node app で実行します:
$ git clone https://github.com/dotnsf/mynfo.git ("dotnsf" 部分はあなたの Github アカウント名に読み替えてください)

$ cd mynfo

$ npm install

$ node app

デフォルトでは 8080 番ポートで HTTP リクエストを待ち受けます。ウェブブラウザで localhost:8080 にアクセスします。以下のような画面が表示されれば起動成功です(初期状態では README.md にシンボリックリンクした md/index.md の内容が(マークダウンが HTML に変換されて)表示されています。英語で一通りの使い方が紹介されています):
2022021901

(↑皆さんが使うときには md/index.md と README.md とのシンボリックリンクは切っちゃって構いません)


画面右上のハンバーガーメニューをクリックすると、リポジトリ内の md/ フォルダ以下を対象フォルダとするファイル選択画面が表示されます(デフォルト状態では md/ フォルダ以下に about_markdown.md, index.md, sample.md の3つのマークダウンファイルが存在しており、それらが(.md 拡張子が省略された形で)一覧表示されています:
2022021902


試しに一番上の about_markdown を選択すると md/about_markdown.md ファイルの内容が HTML に変換されて表示されます:
2022021901


また初期画面で表示されている README.md の最初にも記述していますが、実行時の環境変数や settings.js ファイル内で値を指定することで挙動を変えることができます。例えばサービスを不特定多数の人に公開するのではなく、一部の人向けにクローズドな形で公開したい場合は環境変数 BASIC_USERNAME と BASIC_PASSWORD を指定して実行することでベーシック認証が有効になり、正しい ユーザー ID とパスワードを入力しないとコンテンツは見ることができません。

見栄えに関しては環境変数 CONTENTS_TITLE でサイトの題名(デフォルト値は "Mynfo")を、BOOTSTRAP_THEME で Bootstrap のテーマ(デフォルト値は "warning")を指定できます。例えば前者を ".NSF Mynfo"、後者を "info" に指定するとこのような見栄えになります:
2022021904


基本機能としてはこのような感じです。プロジェクトフォルダ内の md/ フォルダ内にあるマークダウン(.md)ファイルを参照することができる、というものです。ただこのサービス自体にはマークダウンの編集機能はありません。このままサーバー上で(普通に)公開する場合は、別途 md/ フォルダ内のマークダウンファイルを編集する仕組み(サーバー上で直接編集するなど)が必要です。

動くか動かないかでは動くのですが、個人的にはこのような使い方はあまり想定していません。あくまで後述のような、GitHub リポジトリと連携する使い方を想定して開発しています。


【heroku のデプロイパイプラインを使う】
サーバー上の .md ファイルを直接編集するような使い方は本来想定したものではありません。この Mynfo の最大の特徴は以下のような使い方ができることです:

・ローカルホストで(好きなマークダウンエディタで).md ファイルを編集して、
・Github にコミット&プッシュすると、
・デプロイパイプラインによって、サービス側のコンテンツも更新される

この流れを heroku を使って実現する方法も README.md に(英語で)記載していますが、このブログでは同じ内容を日本語で紹介します。

まず heroku のアカウントを作成します。heroku には複数種類のアカウントが存在していますが、ただ動かすだけであれば(容量や可用性などを考慮せずに、小規模1インスタンスだけで動かす前提であれば)無料プランで構いません。

※なお heroku の無料プランで作成するアプリは 30 分間アクセスがないと止まってしまい、次にアクセスした時に再起動してからアプリが稼働します(この場合、アプリ画面が表示されるまで再起動のぶん少し時間がかかります)。24 時間ずっと稼働状態をキープしたい場合は有料プランで運用することを推奨します。

そして heroku にログインし、画面右上から New - Create new app を選択します:



次にアプリケーション名(下図では "mynfo")を入力し、サービスを作成する地域(下図では "United States")を指定します。そして次に(Create app ではなく) Add to pipeline を選択します:



Choose a pipeline と書かれた箇所をクリックし、Create new pipeline を選択します:



そして作成するパイプラインの名称(下図では "mynfo-pipeline")を適当に入力し、デプロイ先のステージを指定します。例えば「一度ステージング環境にデプロイし、動作確認ができたらプロダクション環境へデプロイ」するようなケースも想定できますが、今回はそのままプロダクション環境へデプロイするシンプルな例を紹介します。というわけでここではパイプラインのデプロイ先として production を直接指定します。最後に Create app をクリックします:



これでパイプラインそのものは作成されましたが、まだ GitHub リポジトリとの連携ができていません。このまま作業を続けます。

デプロイ方法として GitHub 連携をしたいので Deployment Method に GitHub を選択します:



そして対象となる GitHub リポジトリ(クローンしたリポジトリ)を指定します。Connect to GitHub 欄で自分の GitHub アイコンを選択し、対象リポジトリ名(そのままであれば "mynfo")を入力して Search します:



すると該当の GitHub リポジトリが見つかるので、横にある Connect ボタンをクリックします:



これで GitHub との接続ができました。最後に自動デプロイのための対象ブランチを指定するので、このまま続けます:



Automatic Deploy 欄でパイプラインが参照する GitHub リポジトリのブランチを指定します。特にブランチを作っていない場合は main だけが選択できるので、この main が選択された状態で Enable Automatic Deploy ボタンをクリックします(別途ブランチを作成して、main 以外のブランチを指定することも可能です):



これでフォークした GitHub リポジトリの main ブランチに変更がコミットされると、パイプラインが動いて最新コードが heroku 上のアプリケーションとして https://(アプリ名).herokuapp.com/ という URL で動き出すようになります:



また、この時点で作成したパイプラインの状態を参照すると、GitHub リポジトリの指定したブランチを接続されて、更新時の自動デプロイが有効になっている旨を確認できます:



この状態で試しに1ファイルを追加して動作確認しています。ローカルホスト上で1ファイル追加して git コマンドでコミットしてもいいのですが、今回は GitHub のウェブ画面を使って追加コミットする例を紹介します。

まずはウェブブラウザで該当 GitHub リポジトリのページ(フォークしたリポジトリのページ)を開き、md フォルダを選択します:



ここからファイルを指定して編集することもできますが、今回は新しいファイルを1つ追加することにします。画面右の Add file ボタンをクリックして、表示されるメニューから Create new file を指定します:



GitHub リポジトリに直接ファイルを追加する編集画面が表示されるので、試しにファイル名を test.md 、ファイルの中身には "# テスト" と見出し行だけ入力します:



画面を下にスクロールすると、GitHub に直接コミットする情報を指定する箇所が現れます。ここでコミットコメント(下図では "md/test.md added.")、を指定し、"Commit directly to the main branch" が選択された状態のまま Commit new file ボタンをクリックします:



これで GitHub リポジトリにマークダウンファイルが1つ追加でコミットされました(ローカルホストでも編集する場合はこの状態を git pull して、ローカルホスト側も更新しておいてください)。

そして指定ブランチがコミットされたことで、heroku に作成したパイプラインが自動実行されます。パイプライン実行そのものも数秒で終わってしまいますが、下図はビルド中(デプロイ完了前)のパイプライン画面です。アプリケーションのビルド中である旨が表示されています:



デプロイが完了するとこのような画面になり、ここから最新の(追加コードが反映された状態の)アプリケーションを開くこともできます:



確認のため、アプリケーションを開きます(Open app と書かれたボタンで開きます)。そして画面右上のハンバーガーメニューをクリックします:



すると存在していなかった test.md というファイルが確認できます。試しにこのファイルを選択します:



作成した通りの内容( "# テスト")であることが確認できます:



このように GitHub リポジトリと連携して、ローカルホストや GitHub 画面でマークダウンファイルを追加・更新・削除してサーバーにコミットすると、自動で公開アプリにも反映される仕組みができました。こうしておくことでローカルホストでは VSCode など好きなマークダウンエディタで編集することができるようになって、後は編集後にコミット&プッシュすればアプリにも反映される、という仕組みになりました。

冒頭でも書きましたが、このコンテンツサービスそのものはベーシック認証を有効にすることで一部の人だけに公開することもできます。ただそれとは別に GitHub リポジトリを公開するか/しないかを考慮する点があることに注意してください。基本的にベーシック認証をかけるサービスであれば、フォーク先の GitHub リポジトリも private 扱いにするべきだと思っています。

また環境変数 GITHUB_REPO_URL (リポジトリURL)と GITHUB_BRANCH (ブランチ名)を指定して実行すると、コンテンツの各画面内に GitHub のコンテンツメニューが追加され、各ページやファイル選択画面内から GitHub の対象ページ画面に移動したり、直接編集ページに移動したり、フォルダに新しいファイルを追加することも可能です(編集は編集権限を持っているユーザーのみ使えます):
2022021906

2022021905


この GitHub と連携した使い方はちょっとクセがあるので、普段 Git を使っていない人からすると(編集画面も無いし)むしろ不便に感じるかもしれません。が、Git やマークダウンに慣れたエンジニアであれば、むしろこの使い方で(慣れたマークダウンエディタとも連携して)コンテンツを更新情報まで含めて管理ができることになって便利だと思っていて、このようなサービスを作ってみました。

ちなみに、このアプリでブログ的な使い方をする場合は、コンテンツのファイル名を日付(例えば 20220219.md)にして、環境変数 REVERSE_FILES の値を 1 にして実行することで(新しい日付のファイルがリストの上にくるように並ぶので)使いやすいのでは、と思っています。



Git やマークダウンをバッチリ使っている自分からはなかなか便利に使えているサービスなので、同様の属性を持った人に使ってみていただきたいです。

なお現時点では GitHub と heroku のパイプラインを使う想定で README.md を記述していますが、GitLab など GitHub 以外の Git システムや、GitHub Actions など heroku パイプライン以外の自動デプロイ化の仕組みを使って運用することもできると考えています。ぜひ多くのパターンで挑戦していただきたいです。

無料でウェブアプリケーションをデプロイできる数少ない環境となった Heroku ですが、この無料環境内で GitHub 連携による自動デプロイ(いわゆる "GitOps" っぽいデプロイ)を簡単に実現できそうなことがわかりました。手順を以下に紹介しますが、前提条件として以下の環境が揃っていることを事前に確認してください:

(1) Heroku アカウント取得&セットアップ済み
(2) GitHub アカウント取得&セットアップ済み
(3) 自分の PC に git コマンドと Node.js がインストール済み※

※ (3) は手元での動作確認が不要であればインストールされていなくても可


【アプリケーションの準備】
まず自動デプロイを行う対象となるウェブアプリケーションを GitHub に用意します。これは Heroku の dyno で動かせる状態になっていれば何でもいいのですが、以下ではこちらで用意したシンプルなウェブアプリケーションを使って紹介します(自分のアプリを使う場合は、そのアプリを GitHub のリポジトリとして登録してください)。

用意したサンプルはこちらです:
https://github.com/dotnsf/simpleweb

2022020601



内容は後述する動作確認時にも再度紹介しますが、シンプルなメッセージを表示するだけのウェブアプリケーションです:
20220206


このサンプルを使う場合は GitHub リポジトリのページ右上のボタンから "fork" して使ってください:
2022020602


fork すると、用意したサンプルアプリケーションが fork した人のリポジトリとして利用できるようになります。以下では fork 先のリポジトリ URL が https://github.com/yourname/simpleweb となったと仮定して説明を続けます(yourname の部分を自分のものに読み替えてください)。なおパイプライン連携の対象となるリポジトリは public でも private でも以下の作業はできます。

実はこの状態から heroku 側の設定に進むこともできるのですが、このアプリケーションを一度手元で動かしてみることにします(上述の (3) の準備ができていれば可能です。できていない人は読み飛ばしてください)。ターミナルから以下のコマンドを実行して、fork した自分のリポジトリを clone します:
$ git clone https://github.com/yourname/simpleweb

そして依存ライブラリを導入後に node コマンドで実行します:
$ cd simpleweb

$ npm install

$ node app

アプリケーションが起動すると 8080 番ポートで HTTP リクエストを待ち受けます。最後にウェブブラウザで http://localhost:8080/ にアクセスします:
2022020701

↑こんな感じの「ハローワールド!」が表示されれば成功です。機能としてはこれだけの、ごくシンプルなウェブアプリケーションです。このアプリケーションが GitHub のリポジトリに登録された状態になっています。


【heroku 連携】
ではこのアプリケーション(自分で用意したアプリケーションを使う場合はそのアプリケーション)の GitHub リポジトリを heroku のパイプラインやデプロイ先と連携して動くように設定します。

大まかな流れとしては、
1. heroku に(空の)アプリを登録
2. 1. のアプリにデプロイするためのパイプラインを作成
3. GitHub リポジトリとパイプラインを連携(GitHub が変更されたら自動的にパイプラインが実行されるようにする)

のようになります。1. から順に行っていきます。

1. まずは heroku にログインします。heroku アカウント未取得の場合は "Sign Up" リンクから作成することもできます:
https://www.heroku.com/

2022020702


ログインに成功すると以下のような画面になります。過去にアプリケーションを登録したことがあると初期画面にアプリケーション一覧が表示されますが、初めての場合はアプリケーションは表示されず、このような登録画面になります:
2022020703


では先程 GitHub に用意(fork)したアプリケーションが heroku 上で動かすことができるように登録します。画面右上のボタンから "New" - "Create new app" を選択します:
2022020704


そしてアプリの名前とデプロイ先リージョンを指定します。名前は他に使われていないものを指定する必要があります(下図では "dotnsf-simpleweb" という名称を指定しています)。リージョンは(無料版の場合は)United States か Europe のどちらかを選択します。単にアプリを作るだけならここで "Create app" ボタンを押せばいいのですが、今回はアプリと同時にパイプラインも作ってしまいましょう。というわけで "Add to pipeline" ボタンをクリックします:
2022020705


2. 続けてパイプラインの作成を行います。上の続きで "Add to pipeline" ボタンをクリックすると "Choose a pipeline" という選択エリアが現れるので、ここで "+ Create new pipeline" を選択します(このアプリ用の新しいパイプラインを作る、という意味です):
2022020706


するとパイプラインの名前(下図では "dotnsf-simpleweb-pipeline" としています)と、デプロイ先ステージを指定する画面が現れます。名前は好きな名前でいいのですが、デプロイ先ステージは "staging"(検証用) か "production" (本番用)かを選択します。下図ではそのまま本番環境にデプロイする想定で "production" を選択しています※。 最後に "Create app" ボタンをクリックします:
2022020707

※別のアプリケーションをもう1つ作って staging に指定し、GitHub → Staging(検証用アプリ) → Production(本番運用アプリ) というパイプラインを作ることもできますが、今回は割愛します。


するとこのような画面になります。ここまでで 1. のアプリにデプロイするための 2. のパイプラインができあがりました:
2022020708


そして最後の 3. の連携設定を行います。「GitHub のリポジトリが更新された」というタイミングに合わせて、同リポジトリの main ブランチの内容をパイプラインで指定されたアプリにデプロイする、というものです。

まず同じブラウザで GitHub にログインしておきましょう。GitHub のセッションがある状態ですすめることで面倒な認証部分を省略できます:
https://github.com/

そして先程の画面の続きです。まずはデプロイ方法として "GitHub" と書かれたアイコンをクリックします:
2022020701


すると画面下部が変わり、"Connect to Github" と書かれたボタンが現れます。このボタンをクリックします:
2022020702


するとどのリポジトリと連携するかを指定する画面に切り替わります。上部で GitHub へのログインを済ませていれば、後は自分のリポジトリを指定するだけです。自分の GitHub ID が指定されている状態で、対象リポジトリ(fork したリポジトリ)を指定するので "simpleweb" と入力して "Search" ボタンをクリックします:
2022020703


すると自分のリポジトリ内の simpleweb リポジトリ(fork したリポジトリ)が見つかります。その横の "Connect" ボタンをクリック:
2022020704


ここまでの作業でパイプラインと GitHub の simpleweb リポジトリとがつながりました。後は対象ブランチを選択しての自動デプロイ機能の設定だけです:
2022020705


画面下にスクロールすると、GitHub リポジトリのどのブランチからアプリケーションをビルドして自動デプロイするか、という選択画面になります。今回は main ブランチをそのまま使うことにして(つまり main ブランチに直接変更を加えることにして)"main" を指定したまま "Enable Automatic Deploys" ボタンをクリックします:
2022020706


すると画面の表示内容が切り替わり、main ブランチからの自動デプロイが有効になったことがわかります。これで事前準備が整いました:
2022020707


ちなみに、この時点で heroku のパイプライン画面を表示すると、このように GitHub から連携したパイプラインが自分の simpleweb アプリ(Production)につながっている様子が確認できます:
2022020705



【動作確認】
ではここまで設定した内容が正しく動作することを確認してみます。ある程度 git コマンドの操作がわかる人であれば、ローカルリポジトリの内容を変更して、git add して、git commit して、git push する・・・という一連の流れを実施いただいてもいいのですが、今回はウェブ画面だけで同じことを行ってみます。

改めて GitHub の(自分の)デプロイ対象リポジトリ(https://github.com/yourname/simpleweb)をウェブブラウザで開きます:
2022020701


ここに変更を加えます。見た目で変更がわかりやすいのは web/ フォルダ以下にファイルを追加したり、既存の index.html を変更したりすることですが、今回は後者でいきましょう。web/ フォルダを選択後に index.html ファイルを選択し、画面右上の鉛筆マークをクリックして編集画面に切り替えます:
2022020702


index.html をブラウザで編集する画面に切り替わるので、何か変更を加えてみます。以下の例では見た目にもわかりやすそうな所で、26 行目の「ハローワールド!」と表示されていた部分を「ハロー heroku ワールド!」と書き換えてみました:
2022020703


画面を下にスクロールすると、git commit のオプション入力画面になります。コミットメッセージ(下の例では "index.html メッセージ変更")を入力し、対象ブランチはデフォルトの "Commit directly to the main branch" が選択されたままにします。最後に "Commit changes" ボタンをクリックして git commit します(サーバー側を直接 git commit するので、 git push は不要です):
2022020704


コミットしました:
2022020706


先程のパイプライン画面を表示すると、GitHub リポジトリのコミットが行われたことを検知して、パイプラインが稼働している様子が確認できます(シンプルなパイプラインなのですぐに稼働後、つまりデプロイ後の状態に切り替わってしまいます・・。下図はデプロイ後の画面です):
2022020707


では heroku 上にデプロイされた変更後のアプリケーションを確認してみます。https://(アプリ名).herokuapp.com/ を開くか、またはパイプライン画面右下の "Open app" と書かれた箇所をクリックして、heroku 上のアプリケーションをウェブブラウザで開きます:
2022020707


heroku 上で稼働しているアプリケーションが開き、先程加えた変更が有効になっていることを確認します:
2022020708


これで GitHub リポジトリと連携した heroku デプロイ用パイプラインが作れて、かつ自動実行も有効になり、GitHub リポジトリに変更が加わればウェブアプリケーションにも反映される、という仕組みの構築ができました。

現実的にはステージング環境やローカル環境で動作確認してから反映、という流れになると思いますが、もちろんその方法(手動で git コマンドを使ってコミット&プッシュ)でも自動的に新しいアプリケーションに切り替えることもできます。またそもそもの Git ブランチ戦略をどうするか?という課題も出てくると思っています。

一方で、CLI を使わなくても(Git リポジトリをウェブで更新さえすれば)公開アプリケーションの更新ができるので、普段 CLI を使わないような、あまり詳しくない人でも(直接アプリケーションの挙動に影響しない範囲での変更であれば)コンテンツの変更管理ができる仕組みが構築できたと思っています。こういう仕組みが簡単に作れてしまう点は heroku の強みだと思います。

備忘録的なブログエントリです。

高速なメモリストアである RedisNode.js から使う場合に多く利用されるライブラリの代表が node-redis です:
2022013000


自分もこれまでに開発した多くのアプリの中で Redis を利用し、Node.js で実装していた場合はほぼ全てで node-redis を使っていました。いわゆる Key-Value 型のデータベースで、高速なデータストア用途だけでなく、ログインセッションの共有保管場所としても使っていました。

これまで使ってきた中でこのような用途がなかったからではあるのですが、今回「登録されている全てのデータのキー」を取得したい、ということがあり、すぐにわからなかったので調べてみました。要は全データを取り出したいのですが、そのためには全キーが必要で、その取得方法を知りたかったのでした。本ブログエントリはその調査結果でもあります。

結論としては RedisClient の keys() というメソッドを使うことで全キーを取得できます。以下サンプルです:
var redis = require( 'redis' );
var redisClient = redis.createClient( "redis://localhost:6379", {} );
redisClient.keys( '*', function( err, results ){
  if( err ){
  }else{
    :
  (results に全キーが配列で格納されている)
    :
  }
});


keys() メソッドを '*'(全て)というパラメータを付けて実行することで全てのキーを取得することができます。

redis CLI でも、
> keys *

のように実行してキー一覧を取得できることは知っていたのですが、node-redis ライブラリで取得する場合の方法を調べるのに手間取ったこともあって、自分でまとめておきました。

このページのトップヘ