2020年7月8日に実施された 初夏のIBM Dojo #9 Kabaneroを使ったクラウド・ネイティブなアプリ開発を体験 ワークショップに参加してきました。講師 @osonoi さんです。
以前に翻訳した Kabanero と、それと関連する Developer Experience にある「VS Code を使用して Kabanero を試す」を体験できるオンラインセッションでした。セッション資料 がわかりやすいので、ぜひ参照してください。
VSCode + codewind の環境、とっても手軽で便利。監視、ビルド、実行など全て Docker 環境で実行され、処理系のインストール無しでさくさく試せる。いろんな言語/環境を試してみたい。
と、Twitter で呟きましたが、すごく参考になったので、ちょっと自分でも中身を確認してみました。自分なりに迷いつつのメモなので、間違えていたり、意味不明だったらスミマセン。
お手軽に開発環境をセットアップ
セッション資料に従い、アプリケーション開発環境をセットアップしてみます。前提となるソフトウェアは以下の2つだけ。
VSCode の 拡張機能 (Extension) で Codewind
を探してインストールします。
新規プロジェクト作成で、Kabanero リポジトリにある Kabanero Node.js Express scaffold template
を選択します。
後は開発環境などが自動でセットアップされます。ビルド環境も実行環境も Docker コンテナ化されているため、Node.js など開発に必要なツールがインストールされていなくても問題ありません。今回のセットアップも Docker 上にコンテナが追加されるだけで、ローカルにインストールされないため、気軽に試すことができます。
アプリを起動すると Node.js Express が動作し、シンプルな Webページが表示されます。
さあ、後はサンプルコードを修正して、いろいろ試すだけ。ソースコードに修正を保存すれば、ビルドが実施され、すぐにWebページに反映されます。
以上、ここまでの手順の詳細は IBM Dojo の セッション資料 をご参照ください。IBM Developer Dojo のどれかに参加すると、Dojo サポート用の Slack チャネルに招待されるので、そこで質問もできます。
生成された環境を眺めてみる
さてこのまま、環境はブラックボックスとして、Node.js + Express のアプリ開発を開始してもいいのですが… せっかくですから、自動生成された環境を少し眺めてみましょう。
VSCode のワークスペース
まず VSCode のワークスペースを見てみると、以下のような構成になっています。
ページを表示しているのは routes/index.js
ですね。
表示に利用されている Pug 形式のテンプレート views/index.pug
は以下のように非常にシンプルでした。
これらなのですが、探してみると GitHub の appsody アカウントにある stacks リポジトリ 配下にある /incubator/nodejs-express/templates/scaffold フォルダが元になっているようです。
Docker で動作するコンテナについて
さて、上記の Web ページを表示中、Docker は以下のように3つのコンテナを実行していました。
最初のコンテナ (イメージは kabanero/nodejs-express:0.4) がアプリを実行している環境のようですので、コンテナに sh アクセスして、動作しているプロセスの状態を見てみます。
自身の /bin/sh と ps コマンド以外のプロセスは以下のような感じ。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
default 1 1.8 0.3 105308 7492 pts/0 Ssl+ 09:43 7:34 /.appsody/appsody-controller --mode=run
default 42 0.0 2.2 743756 45576 ? Ssl 09:43 0:00 npm
default 58 0.2 4.2 1268880 86480 ? Sl 09:43 1:08 node server.js
ついでに真ん中のコンテナ(イメージは eclipse/codewind-performance-amd64:0.13.0) のプロセスはこちらで、ちょっと何やっているか不明なのですが、実行しているイメージ名から Codewind 本体のような気がします。アプリのビルド前から居ましたし。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1000 1 0.0 1.5 741756 30936 ? Ssl 07:20 0:00 npm
1000 16 0.0 2.5 680096 52572 ? Sl 07:20 0:00 node server.js
三番目のコンテナ (イメージは eclipse/codewind-pfe-amd64:0.13.0) のプロセスはこちらで、こちらはソースコードの更新をチェックしたり、最初のコンテナを起動してたり、いろいろ働いているようです。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 11892 2652 ? Ss 07:20 0:00 sh -c /file-watcher/scripts/root-watcher.sh ${HOST_WORKSPACE_DIRECTORY} ${CONTAINER_WORKSPACE_DIRECTORY}
root 33 0.0 2.1 676736 43460 ? Sl 07:20 0:00 npm
root 61 0.0 0.1 11896 2916 ? S 07:20 0:00 /bin/bash ./npm-start.sh
root 62 0.0 2.1 676368 44708 ? Sl 07:20 0:00 npm
root 73 0.0 5.6 972028 115352 ? Sl 07:20 0:16 node server.js
root 535 0.0 0.1 11896 2760 ? S 09:43 0:00 /bin/bash /codewind-workspace/.extensions/codewind-appsody-extension/appsody run --name cw-dojoyamacha
root 536 0.0 0.0 23032 1408 ? S 09:43 0:00 /usr/bin/coreutils --coreutils-prog-shebang=tee /usr/bin/tee -a /codewind-workspace/.logs/dojo-yamacha
root 542 0.0 0.5 116632 11840 ? Sl 09:43 0:00 /codewind-workspace/.extensions/codewind-appsody-extension/bin/appsody run --name cw-dojoyamachan-df39
root 603 0.0 1.4 45688 29636 ? Sl 09:43 0:00 docker run --rm -P --name cw-dojoyamachan-df39b4d0-c0eb-11ea-97e7-d775ccf52e96 --network codewind_netw
root 620 0.0 0.0 23032 1320 ? S 16:11 0:00 /usr/bin/coreutils --coreutils-prog-shebang=tail /usr/bin/tail -q -F -c +0 /codewind-workspace/.logs/d
三番目のコンテナ内の環境変数に、幾つか興味深い値がありましたので、転記します。
CODEWIND_VERSION=0.13.0
CONTAINER_WORKSPACE_DIRECTORY=/codewind-workspace
ENABLE_CODE_COVERAGE=false
HELM_HOME=/root/.helm
HOSTNAME=72958642fbc6
HOST_HOME=C:\Users\z
HOST_MAVEN_OPTS=
HOST_OS=windows
HOST_WORKSPACE_DIRECTORY=C:\codewind-data
IMAGE_BUILD_TIME=20200612-133352
JAVA_HOME=/opt/java/jre
LOG_LEVEL=info
NODE_ENV=production
PATH=/opt/java/jre/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PERFORMANCE_CONTAINER=codewind-performance-amd64:0.13.0
そして気がついていませんでしたが、ローカルPCに C:\codewind-data
なんてフォルダが生成されていました… 作業ディレクトリとほぼ同じ構成ですが、.vscode
フォルダが無いかわりに空の node_modules
フォルダが存在します。
試しに c:\ ドライブ全体を対象に appsody
でファイル名検索した結果がこちら。c:\work\codewind\dojo-yamachan
がプロジェクト作成時に自身で指定した作業フォルダです。
ふーむ、なかなか興味深いですね。
実際の起動プロセス
さて、作成したアプリがどう起動されるか追ってみましょう。実行用コンテナで node server.js
とあるので、sh でコンテナの中に入り、server.js
ファイルの中でそれっぽい部分を探してみます。
// Register the user's app.
const basePath = __dirname + '/user-app/';
function getEntryPoint() {
let rawPackage = fs.readFileSync(basePath + 'package.json');
let package = JSON.parse(rawPackage);
if (!package.main) {
console.error("Please define a primary entrypoint of your application by adding 'main: <entrypoint>' to package.json.")
process.exit(1)
}
return package.main;
}
const userApp = require(basePath + getEntryPoint());
app.use('/', userApp({
server: server,
app: app,
log: pino,
}));
まずわかるのが、作成した自身のアプリが /project/user-app/
ディレクトリに配置されているということです。
そしてこのディレクトリですが、Docker ランタイムにより、さきほど発見したローカルPCの C:\codewind-data
配下のフォルダがマウントされ、永続化されていることがわかります。
たぶんですが、作業フォルダの内容をビルドした結果 (今回は Node.js で webpack など前処理もないので単にファイルコピーのみ?) がこのローカルPC上のフォルダに配置され、それを実行環境の Docker コンテナの /project/user-app/
ディレクトリにマウントすることで、即時反映できている、という仕組みのようです。
で、さきほどの server.js
ファイルのコードにある getEntryPoint()
関数の中を見ると、package.json
のなかの main
エントリがアプリの本体を指定しているようで、今回だと app.js
が指定されています。
"main": "app.js",
そしてこの app.js
を見ると、これが Express アプリの本体で、これでようやく最初に出てきた routes/index.js
や views/index.pug
ファイルに繋がります。
module.exports = (/*options*/) => {
// Use options.server to access http.Server. Example of socket.io:
// const io = require('socket.io')(options.server)
const app = require('express')()
app.set('views', __dirname + "/views");
app.set('view engine', 'pug');
app.use('/', require('./routes'));
return app;
};
起動順としては、以下のような感じですかね。
- Appsody が用意した実行用コンテナの
/project/user-app
にローカルPCのc\codewind-data
配下のプロジェクト用フォルダがマウントされる 【Appsody共通】 - Appsody が用意した実行用コンテナ内の
/project/server.js
が/project/user-app/package.json
ファイルの main エントリを参照する【Appsody Node.js 系共通】 - main エントリに指定された
/project/user-app/app.js
が実行される【Appsody Node.js Express 系共通?】 - app.js によって Pug テンプレートエンジンがセットされ、
views/index.pug
をテンプレートとしてroute/index.js
が表示される。【今回の Stack 固有】
うん、これでやっとスッキリしました。
というわけで
Appsody (VSCode + Codewind) で作成した Node.js + Express サンプルアプリの起動の仕組みをざっくり調べてみました。なかなか良く出来た仕組みだなー、と感心してみたり。
ただ、時間の関係もあり、ソースコードの変更をウォッチしているところ、ビルドしているところ、などはまだ調べていません。また時間を作って、コンパイルする Java などの環境(変化がわかりやすいので)を対象に調べてみたいな、などと思っています。なにかわかったら、メモ公開するかもしれません。
それではまた!