Linux系OSのDockerコンテナでJava(JDK)を扱うときの注意点
原因不明のエラーが出る
Dockerコンテナ内でJavaを扱う時に、正体不明のエラーに出くわすことがあります。
通常のOS上では問題が発生しないのに、コンテナ内に展開するとNullPointerExeptionであったり、リフレクション関係のエラーが発生するケースです。
このケースでは、スタックトレースを追ってみて、クラスに*FontManagerが含まれている場合、コンテナ内のOS側のライブラリの不足が原因と考えてよいかと思います。
原因と解消法
Javaが依存しているfontconfigが、コンテナ用のOSイメージでは軽量化のためにインストールされていないことが原因です。
CentOSであれば下記で解決できます。
yum install -y fontconfig
Dockerfileであれば、RUNのコマンドに上記を追加します。
一度お試しください。
上記だけでは解決しない場合
JDKの一部のバージョンでは、フォントがひとつもインストールされていないときにも同様のエラーが発生するようです。
上記で解決しない場合はJDKのバージョンを上げるか、dejavuをインストールしてみてください。
これで無事解決してくれるとよいのですが。
追記
DockerHubで提供されているJavaイメージを利用していればこの現象には出くわさないかと思います。
自作コンテナでハマっている方がいれば、上記を疑ってください。
使用している環境からVagrantのBoxを作成する
現在の環境を保存したい!
ある程度環境内での作業が進んでくると、毎回いちから環境を作り直すのではなく、現在の環境を保存しておきたくなります。
この時に方法はいくつかあるのですが、ここではローカルにBoxファイルを作成してベースBoxにする方法を紹介します。
Boxの作成コマンド
vagrant package
実のところ、Boxの作成には保存したいプロジェクトのフォルダで"vagrant package"を実行するだけです。
”vagrant package --base VM_NAME”を実行します。
ベースボックスとして作成するオプションを指定し、作成するboxの元になる環境のマシン名を指定します。
10月6日追記:"vagrant package"だけではだめです!
大変申し訳ございませんでした。
”vagrant package --base VM_NAME”が正しいです。
この手順でないと作成された.boxファイルをベースにした仮想マシンではsshログインできない環境が作られてしまいます。
6時間ほどハマりました。
生成されるファイル名の指定や同梱するファイルの指定などのオプションがありますが、とりあえず上記だけでも再利用可能な現在の環境を保存した.boxファイルが作成されます。
デフォルトでは、"package.box"というファイル名で生成されます。
別の仮想環境で利用する
VagrantにBoxを追加する
ローカル環境で作成したBoxを再利用するには、VagrantにこのBoxを追加します。
vagrant box add --name BOX_NAME PATH_TO_BOX_FILE
PATH_TO_BOX_FILEはpackageをデフォルトで実行し、フォルダを移動していなければ"./package.box"です。
BOX_NAMEは既存のBoxとと重複をさけて、わかりやすいものを付けましょう。ここでバージョニングをしておく方が良いかと思います。
Vagrant cloudで利用されているようなバージョン管理は、ローカル環境では行うことが出来ません。
--box-version VERSION
"--box-version VERSION"のオプションはクラウド上からBoxをダウンロードするときのバージョンを指定するもので、追加するBoxに対してバージョニングを行うものではありませんので注意してください。
残念ながら、ローカルの.boxファイルから追加されたBoxは常にバージョン0として認識されます。