スクラムマスターがDockerを使った帳票作成環境の構築で、直面した2つの課題とその解決方法
この記事は「BEMALab アドベントカレンダー 2024」16日目の記事です。
はじめに
こんにちは。シニアスクラムマスターの板原です。
普段私はアジャイルコーチやスクラムマスターとして活動しているため、今年のアドベントカレンダーもアジャイルやスクラムに関連する記事を書くつもりでいました。
そんなある日、ひょんなことからプライベートでDocker環境を構築することになり、盛大につまずいてしまったので、今回は備忘録も兼ねて技術記事を書いてみます。
Dockerで帳票作成環境を構築することになったきっかけ
(私のところに相談が来るまでの細かい経緯については本題とはズレるので省略します)
とあるWebサービスはNode.jsで開発されており、領収書などの印刷処理をpdfmeというOSSの帳票エンジンを利用して行っていました。
pdfmeは、帳票テンプレートの作成をpdfmeのサイト上でお手軽に行うことができるため、とあるWebサービスもpdfmeのサイト上で帳票テンプレートの作成を行っていました。
pdfmeは日々進化を続けている非常にアクティブなOSSなのですが、とあるWebサービスはライブラリのバージョンアップが疎かになっており、気がついた頃には時すでに遅し、帳票テンプレートの互換性がなくなってたようです。
セキュリティリスク等を考えると、とあるWebサービスのライブラリのバージョンを上げるのが正しいやり方だと思いますが、諸事情によりすぐにバージョンを上げるのは困難な状況だったため、暫定的に古いバージョンの帳票テンプレートが作れる環境をDockerで構築することになりました。
まずはローカル環境で構築してみる
いきなりDockerfileを作成できるほどのスキルは持ち合わせてないので、まずはローカル環境で構築してみます。
とあるWebサービスで使用しているpdfmeのライブラリのバージョンを確認したところ、約2年前にリリースされた「1.0.17」でした。執筆時点のpdfmeの最新バージョンは「5.2.7」なので、メジャーバージョンが4つも上がってました。流石に4つも上がれば互換性なくなってても不思議ではありませんね。。
気を取り直して、構築を進めます。
pdfmeのgitリポジトリのREADMEを読むと、次のような記載がありました。
The operating requirements should be the node environment >=14. Please see the note at the end of this section for usage on Node.js <16. |
動作要件はNode.jsのv14以上で、v16未満は注意が必要です。
注意事項の記載は見つからなかったのですが、とあるWebサイトはv14で特に問題なく動作しているようでした。
手元のPCのNode.jsのバージョンを確認してみると、v16がインストールされていました。
v14をインストールして確認しようとも思ったのですが、構築手順の確認が目的だったので、v16のまま構築してみることにしました。(※この安易な判断が後のつまずきポイント①に...)
ビルドして、開発サーバーを起動してみます。
$ git clone https://github.com/pdfme/pdfme.git -b 1.0.17 --depth 1
$ cd pdfme
$ npm install
$ npm run build
$ cd website
$ npm install
$ npm run start
無事にブラウザで動作確認できました!(ここまではスムーズ)
Dockerで構築してみる
構築手順が確認できたので、Dockerで構築してみます。
Dockerfileなどを準備
まずは、Dockerfileを作成します。今回は帳票作成環境が作れれば良いので、軽量なAlpineイメージ(とあるWebサイトのNodeのバージョンは14だったので、node:14-alpineを使用)で作成してみました。
FROM node:14-alpine
RUN apk update && \
apk add git
RUN git clone https://github.com/pdfme/pdfme.git -b 1.0.17 --depth 1
WORKDIR /pdfme
RUN npm install
RUN npm run build
WORKDIR /pdfme/website
RUN npm install
EXPOSE 3000
次に docker-compose.yml を作成します。
version: '3'
services: pdfme:
build: .
container_name: pdfme
command: "npm run start"
ports:
- "3000:3000"
つまずきポイント①: ビルド実行時に該当npmバージョンに無い機能を使ってしまい、不具合が発生する
準備が完了したので、ビルドを実行してみます。
$ docker-compose build --progress plain
あれ?ビルドが全く終わらない...。
・・・
ログを確認するとどうやらビルド途中で無限ループが発生してるようです。
・・・ #9 0.825 > root@0.0.0 build /pdfme #9 0.825 > npm run --workspaces clean && npm run --workspaces build #9 0.825 #9 1.264 #9 1.264 > root@0.0.0 clean /pdfme #9 1.264 > npm run --workspaces clean #9 1.264 #9 1.706 #9 1.706 > root@0.0.0 clean /pdfme #9 1.706 > npm run --workspaces clean #9 1.706 #9 2.164 #9 2.164 > root@0.0.0 clean /pdfme #9 2.164 > npm run --workspaces clean ・・・ |
色々と調査してみると、npmのworkspace機能はv7から追加された機能であることが分かりました。
Node.jsのv14には、デフォルトでnpmのv6が対応しているので、workspace機能が使えず無限ループに陥ってしまったようです。
最初はnpmのバージョンが原因とはわからず結構手間取ってしまったので、ローカル環境で構築した際に面倒くさがらずNode.jsのv14で確認するべきでした。
Dockerfileを修正して再度ビルド
DockerfileのNodeのバージョンをv16に変更します。
FROM node:16-alpine ←v16に修正
RUN apk update && \
apk add git
RUN git clone https://github.com/pdfme/pdfme.git -b 1.0.17 --depth 1
WORKDIR /pdfme
RUN npm install
RUN npm run build
WORKDIR /pdfme/website
RUN npm install
EXPOSE 3000
再度ビルドを実行してみたところ、無事に完了したようです。
つまずきポイント②: Dockerコンテナ内で立ち上げたサービスにホスト側から接続できない
無事ビルドが完了したので、Dockerを起動してみます。
$ docker-compose up ・・・ pdfme | > @pdfme/website@0.0.0 start pdfme | > docusaurus start pdfme | pdfme | [INFO] Starting the development server... pdfme | Info: Documentation generated at ./docs/api/common pdfme | Info: Documentation generated at ./docs/api/generator pdfme | Info: Documentation generated at ./docs/api/ui pdfme | [SUCCESS] Docusaurus website is running at http://localhost:3000/. |
Dockerが起動したのでブラウザで確認してみます。
あれ?動かないぞ...。
・・・
コンテナの中に入って調査してみると、localhostで立ち上がっちゃってました。
/pdfme/website # netstat -a Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 127.0.0.11:38009 0.0.0.0:* LISTEN tcp 0 0 localhost:3000 0.0.0.0:* LISTEN ・・・ |
これだと、コンテナ内部からしか接続できないので、ホストから接続するためには「0.0.0.0」で立ち上げる必要がありそうです。
docker-compose.ymlを修正してDockerを再起動
pdfmeではDocusaurusを使用しており、普通に起動するとlocalhostで立ち上がってしまうようでした。
色々と調査してみると、hostオプションをつけて起動してあげれば良いことが分かったので、docker-compose.yml を修正してみます。
version: '3'
services:
pdfme:
build: .
container_name: pdfme
command: "npm run start -- --host 0.0.0.0" ← hostオプションを追加
ports:
- "3000:3000"
Dockerを起動してみます。
$ docker-compose up ・・・ pdfme | > @pdfme/website@0.0.0 start pdfme | > docusaurus start --host 0.0.0.0 pdfme | pdfme | [INFO] Starting the development server... pdfme | Info: Documentation generated at ./docs/api/common pdfme | Info: Documentation generated at ./docs/api/generator pdfme | Info: Documentation generated at ./docs/api/ui pdfme | [SUCCESS] Docusaurus website is running at http://localhost:3000/. |
Dockerが起動したのでブラウザで確認してみます。
今度は無事に動きました!
実際に帳票テンプレートも作成してみましたが、特に問題なさそうです。
おわりに
エンジニアからスクラムマスターに転身して4年の年月が経ち、エンジニアとしての腕も多少鈍ってきた感は否めませんが、つまずきながらも無事にミッションを果たすことができた点については良かったです。
今回の経験を共有したことで、少しでも多くの方のお役に立てれば幸いです。
これからもエンジニアの端くれとして地道に技術力を高めて行こうと思いますので、技術に疎遠となった元エンジニアのみなさんも一緒に頑張りましょう。
この記事を書いた人
関連記事
- OutSystems始めました
宮内 祥多
- AWSのコスト見積もりのポイント
Hideki Ikemoto