第2の人生の構築ログ

自分の好きなことをやりつつ、インカムもしっかりと。FIRA60 (Financial Independence, Retire Around 60) の実現を目指します。SE を生業としていますが、自分でプログラミングしながら自分が欲しいと思うアプリケーションを作ることが楽しみです。旅行と温泉、音楽と読書は欠かすことができません。

Javaの異なる環境をDockerを使ってサクッと用意する

f:id:dr_taka_n:20191109170224p:plain:w400

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 もありますが、以下のページに纏めてくれている方がおりましたので、参照だけここに記載しておきます。

k11i.biz