OpenClipart-VectorsによるPixabayからの画像
Oracle Java のライセンス変更はやはり影響が大きく、商用プラットフォームにおける Oracle Java のデファクトスタンダードにも変化が出てきているように感じます。
今後更にいろいろな種類の Java が使われ、いろいろなバージョンの Java が使われている状況が発生していきそうです。
個人的なところでは最近古いバージョンでの動作確認が必要になったりしたこともあり、Java の異なる環境を Docker を使ってサクッと用意する方法をメモしておきます。
OpenJDK
OpenJDK の Docker Hub は以下になっています。
OpenJDK 8 を使ってみます。
とても簡単な Java アプリケーションを用意します。
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, world!"); } }
$ ll total 8 -rw-r--r-- 1 hoge staff 116 11 1 18:16 HelloWorld.java
Docker コマンドだけを使ってコンテナに入って作業
Dockerfile を書いて、直接起動する方法もありますが、まずは、Docker のコマンドだけを使って、Docker コンテナに入って作業する方法を試してみます。
$ docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp -it openjdk:8 bash $ root@ecd576520ab2:/usr/src/myapp#
docker コマンドを叩いた後、そのままコンテナに入っています。コマンドを軽く説明しますと、
run
でコンテナを起動します。ちなみに、正確には、ただ起動をするだけでなく、イメージからコンテナを作成して、起動しています。run
の--rm
(クリーンナップ)オプションは、作成して起動したコンテナを上記のコマンドを終えた後に削除します。このオプションを使わない場合は、コンテナは停止しても保持され続けます。-v
は、ボリュームの指定です。ホストのディレクトリをコンテナのディレクトリにバインドします。-v
の後の引数がそのディレクトリの指定です。ここでは、ホストで作成したJavaのファイルをコンテナでビルドして実行したいために起動時のディレクトリをまず指定して($PWD
)、:
コロンの後にコンテナのバインド先のディレクトリ(/usr/src/myapp
)を指定しています。-w
はコンテナ内の作業ディレクトリを指定します。上記の例では、コンテナ起動後、ターミナルでコンテナにそのまま入りますが、入った直後のディレクトリがここで指定しているディレクトリになります。-it
はコンテナのプロセスに対して tty を割り当てる指示です。このコマンドを実行したターミナルでそのままコンテナに入り実行することができます。openjdk:8
はイメージの指定です。Docker はローカルにイメージのコピーがない場合には、Docker Hub をオンラインでチェックし、指定されたイメージをダウンロードします。bash
は bash コマンドです。この記述のところまでで、指定されたイメージが実行中のコンテナとなり、そのコンテナの中でbash
コマンドを実行しています。
起動しているコンテナ内で ls
してみます。
root@ecd576520ab2:/usr/src/myapp# ls -l total 4 -rw-r--r-- 1 root root 116 Nov 1 09:16 HelloWorld.java
ローカルに用意していたHelloWorld.java
が見えています。java のバージョンを確認します。
root@ecd576520ab2:/usr/src/myapp# java -version openjdk version "1.8.0_232" OpenJDK Runtime Environment (build 1.8.0_232-b09) OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)
OpenJDK の8ですね。コンパイルして実行します。
root@ecd576520ab2:/usr/src/myapp# javac HelloWorld.java root@ecd576520ab2:/usr/src/myapp# java HelloWorld Hello, world!
ちゃんとコンパイルできて実行できています。
docker コマンド一発で OpenJDK 環境がすぐに動作しました。便利ですね。このような感じでホストの環境を汚さずにいろいろな Java 環境を試すことができます。
Dockerfile を書いてイメージを作成し、コンテナ起動でアプリを実行する
HelloWorld java アプリをコンパイルして起動するということ自体は先程と同じですが、やり方がちょっと違います。
Dockerfile を書いて、コンパイル、イメージを作成後、コンテナを起動してアプリを実行します。コンテナでアプリを用意する場合は通常こちらの手法が多いでしょう。
Dockerfile の記載は以下の通りです。
FROM openjdk:8 COPY . /usr/src/myapp WORKDIR /usr/src/myapp RUN javac HelloWorld.java CMD ["java", "HelloWorld"]
ファイルの配置は以下の通りとなります。
$ ll total 16 -rw-r--r-- 1 hoge staff 114 11 1 18:16 Dockerfile -rw-r--r-- 1 hoge staff 116 11 1 18:16 HelloWorld.java
Dockerfile の記載を補足します。
COPY
命令でホストのカレントディレクトリファイルをコンテナの/usr/src/myapp
ディレクトリにコピーします。具体的には、HellowWorld.java
をコピーします。WORKDIR
でこれ以降の命令で使われる作業ディレクトリを指定しています。RUN
は指定されたコマンドをコンテナ内で実行します。ここでソースコードのコンパイルを行います。CMD
はコンテナ起動後に実行されるコマンドを指定します。ここではコンパイルされた Java クラスの実行を行います。ちなみに、このCMD
の命令はdocker run
のイメージ名の後の引数(コマンド)で上書きされます。実際に処理されるのは最後のCMD
命令だけです。ベースイメージ中のCMD
命令も同様です。
ビルドします。-t
オプションでイメージに名前を付け、.
(カレントディレクトリ) で Dockerfile
のありかを指定しています。
$ docker build -t my-java-app .
確かに my-java-app
のイメージが作成されています。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE my-java-app latest 9a35e5a55d1b 2 minutes ago 488MB
作成したイメージからコンテナを起動してアプリを実行します。
$ docker run -it --rm my-java-app Hello, world!
OK です。
Oracle Java
JRE であれば、Oracle Java 8 SE (Server JRE) - Docker Hub にありますが、JDK はライセンスの変更があってからなかなか自動化した状態で上記のように実行するのは難しくなっています。
(以前はできていたのですが、ちょっと試してはみましたが、以前やっていた手法は使えなく、諦めました。。)
古いバージョンであれば、大丈夫なものもあります。
最近、なぜか Java 5、6 の動作確認を行わないといけないシチュエーションがあり、以下のイメージが使えました。
Java 6 です。
$ docker run --rm docker.io/apsl/java6 java -version java version "1.6.0_45" Java(TM) SE Runtime Environment (build 1.6.0_45-b06) Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
Java 5 です。
$ docker run --rm docker.io/apsl/java5 java -version java version "1.5.0_22" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03) Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_22-b03, mixed mode)
その他の Java もありますが、以下のページに纏めてくれている方がおりましたので、参照だけここに記載しておきます。