GAミント至上主義

Web Monomaniacal Developer.

公開するサービス名とプロジェクト名を分けててよかった話

現在、ビズオーシャンでは、新しいサービスの開発と公開に向けて動いています。

サービスの公開が近づき、サービス名も部内の投票を参考に責任者によって決められ、ロゴも作って、サブドメインも登録して、SSL証明書(Let's Encrypt)も作って、Djangoの設定も変えて、
いよいよ!な時、念のためサービス名を商標登録しよう、ということになり、担当の人を通して弁理士?さんに確認したところNGが来てしまいました。

そしてもう一回、ちょっと英語の綴りを変えたりして、これなら大丈夫だろうと思って同様な作業を繰り返していたところ、読みが既存のものと一緒だと厳しいと、またNG。

商標取得の難しさを痛感。


でも、よかったこととして、内部的なプロジェクト名は全然別のものにしていたので、GCPのプロジェクト名とかソースコードのフォルダ名とか、Gitのレポジトリ名とかそういう開発に関わるところにはサービス名を使っていなかったので、それは非常に良かったと思います。


特にプロジェクト名は、公開しない前提で、世界の神話から神の名前を付けたり中二病を意識して付けていたので、恥ずかしくてサービス名には使えず、そもそもサービス名の候補にすらならないため、余計な手間も減りました。

今後も新規開発時は、中二病な名前で攻めようと思いました。

GKEでKubernetes 1.8が使えるようになったのでCron Jobsを使う

cron的なバッチ処理をKubernetesで行えるCron Jobsが1.8から使えるようになって、ちょうど他のメンバーの新規プロジェクトで必要になったので使ってもらった。


kubernetes.io

Prerequisites
You need a working Kubernetes cluster at version >= 1.8 (for CronJob). 


gcloudのkubectlも11/1時点ではまだ1.7だったけど、11/2でupdateをかけたら1.8になった。

ヘッドレスChrome + Node.js + express + DockerでPDF生成サーバーを作る

URLを渡すとChromeがPDFを作って返してくれるサーバーを作るお話。


業務用ソフトではよくPDFの帳票が必要になる。今作っているサービスでも必要になった。

WEB系だとHTMLは生成しやすいので、それをPDFに変換するwkhtmltopdfなどのコマンドラインツールや、Ruby製だとThinreportsなどのソフトウェアを使う必要があった。

あと選択肢としては、Google SpreadSheetやDriveのAPIを組み合わせてもできなくはないけど、やってみるとAPIが遅いのでかなり待たされるし、細かい調整は望めない。

wkhtmltopdf

オープンソース PDF 帳票ツール for Ruby, Rails | Thinreports

でも、今年4月に公開されたChrome59以降は、コマンドラインChromeを起動し、PDFを生成することもできるHeadless Chromeという機能が追加された。

ヘッドレス Chrome ことはじめ  |  Web  |  Google Developers


これの何がうれしいかというと、普段使っているChromeの印刷→PDFと同じ出力が得られるし、js、CSSの挙動も普段のChromeと同じになるはずので、それぞれのライブラリの癖を覚える必要もなければ、細かい差異にいら立つこともない。

Chromeなので改善、メンテナンスも継続的に行われるし、Linuxでも安定するだろうと予想できる。

もし、何か表示とかに変なところがあっても、普段お世話になっているChromeがこうなら仕方ないよねと諦められる。

他のHTML→PDF変換ソリューションだとこんな条件はそろわない。



今回はやらないけど、スクリーンショットも取れるので、昔だったら大変だったWEBサイトのサムネイル生成サーバーもすぐ作れそう。


ということで、Dockerに入れてchromeコマンドを使ってみると、問題が多発。

まずDocker内での起動には--no-sandboxが必要で、下記を参考にした。

bufferings.hatenablog.com

次に日本語が表示できないので、Dockerに日本語フォントをインストールした。フォントはGoogleフォントからかき集めた。WEBフォントのままでも使えないことはないが、毎回ダウンロードしてしまうので、サーバーにダウンロードしてしまった方が表示は数百ミリ秒早い。

Chrome自体は、GoogleからDebian用のdebファイルをダウンロードしてきて依存を解決するためにgdebiを使ってインストールした。最初gdebiを使わずに深い沼にはまりかけた。デスクトップ版Ubuntuなどでは特に問題にならないが、DockerだとGUI系のいろんなライブラリが入ってないのでハマる。gdebiすごい。

www.google.co.jp


Dockefileから抜粋すると下記。後でexpressのサーバーを使うのでnodeをベースにしている。抜粋なのでこれだけだと何にもおきないはず。

FROM node:8.6

# Install Chrome
RUN apt-get update && \
    apt-get install -y gdebi

COPY google-chrome-stable_current_amd64.deb ./
RUN gdebi --non-interactive google-chrome-stable_current_amd64.deb

# Install fonts
COPY fonts /usr/share/fonts

やっと動いたと思ったら、今度は上下に日付、タイトルなどの余計なヘッダー、フッターが入ってしまう。

chromeコマンドラインフラグを見ると、そこは現時点では変えられないらしい。

使えるコマンドラインフラグは下記ソースを読めとのこと。

https://cs.chromium.org/chromium/src/headless/app/headless_shell_switches.cc

どうにかならんのかと思ったら、検索していると同じ悩みの人がすでに作ってくれていた。

Nodeを使ってプログラム側から操作すれば、そのオプションも使えるらしい。

www.npmjs.com

Motivation

google-chrome currently have option to render pdf files when used with headless option. But this option contains hardcoded adding header and footer to page rendering it unusable for pdf generation. This module allows to generate it without those elements.

まさに同じ。


これを入れたところ、Dockerには対応していないので一部書き換える。


node_modules/chrome-headless-render-pdf/index.js

async spawnChrome() {
        const chromeExec = this.options.chromeBinary || await this.detectChrome();
        this.log('Using', chromeExec);
        const commandLineOptions = [
             '--headless',
             `--remote-debugging-port=${this.port}`,
             '--disable-gpu',
             '--no-sandbox'
            ];

上記した--no-sandboxを追加

node_modules/chrome-headless-render-pdf/index.js

    generatePdfOptions() {
        const options = {};
        if (this.options.landscape !== undefined) {
            options.landscape = !!this.options.landscape;
        }

        if (this.options.noMargins) {
            options.marginTop = 0;
            options.marginBottom = 0;
            options.marginLeft = 0;
            options.marginRight = 0;
        }

        if (this.options.includeBackground !== undefined) {
            options.printBackground = !!this.options.includeBackground;
        }
        options.paperHeight = 11.70;
        options.paperWidth = 8.26772;

        return options;
    }

デフォルトの出力サイズがアメリカンなレターサイズなのでoptions.paperHeight、options.paperWidthを単位インチのA4縦サイズを指定。

他のオプションは下記ページで確認できる。

Chrome DevTools Protocol Viewer - Page

とりあえず動いたから書き換えて使ってるけど、もうちょっといい感じにしてchrome-headless-render-pdfにプルリクエストを送ってみたいもの。

あとはこいつをexpressから叩いて、一時ファイルに書き出して、それを返しているけど、chromeの初回起動が重いからどうするかとか、たまに止まるとか、まだ非同期の処理の塊であるNodeの開発にも慣れていないし、ぐちゃぐちゃなので落ち着いたらまとめるつもり。


Node.js超入門

Node.js超入門

node.jsで作るWebサーバー

node.jsで作るWebサーバー