зеркало из https://github.com/docker/labs.git
Merge pull request #342 from PaulSandoz/master
Chapter for Docker and Java 9
This commit is contained in:
Коммит
1d6ad9f684
|
@ -68,11 +68,13 @@ NOTE: `--parallel` switch will not work for Docker Compose version prior to 1.12
|
|||
NOTE: For Linux, `docker-compose` and `docker` commands need `sudo` access. So prefix all commands with `sudo`.
|
||||
|
||||
=== Other Software
|
||||
|
||||
. Install https://git-scm.com//[git].
|
||||
. Install Docker Cloud CLI following the https://docs.docker.com/docker-cloud/installing-cli/[instructions].
|
||||
. Download Java IDE based upon your choice and install.
|
||||
.. https://netbeans.org/downloads/[NetBeans 8.2] (`"Java SE"` version)
|
||||
.. https://www.jetbrains.com/idea/download/[IntelliJ IDEA Community or Ultimate]
|
||||
.. http://www.eclipse.org/downloads/eclipse-packages/[Eclipse IDE for Java EE Developers]
|
||||
. Download https://maven.apache.org/download.cgi[Maven] and install.
|
||||
. Install Docker Cloud CLI following the https://docs.docker.com/docker-cloud/installing-cli/[instructions].
|
||||
|
||||
. Download the OpenJDK build of http://download.java.net/java/GA/jdk9/9/binaries/openjdk-9_linux-x64_bin.tar.gz/[JDK 9 for Linux x64].
|
||||
(See also the http://jdk.java.net/9/[OpenJDK JDK 9 download page].)
|
||||
. Download the early-access Open JDK build of http://jdk.java.net/9/ea[JDK 9 for Alpine Linux].
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
:imagesdir: images
|
||||
|
||||
== Build a Docker Image with JDK 9
|
||||
|
||||
*PURPOSE*: This chapter explains how to create a Docker image with JDK 9.
|
||||
|
||||
The prior chapter explained how, in general, to build a Docker image with Java.
|
||||
This chapter expands on this topic and focuses on JDK 9 features.
|
||||
|
||||
=== Create a Docker Image using JDK 9
|
||||
|
||||
Create a new directory, for example `docker-jdk9`.
|
||||
|
||||
In that directory, create a new text file `jdk-9-debian-slim.Dockerfile`.
|
||||
Use the following contents:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
# A JDK 9 with Debian slim
|
||||
FROM debian:stable-slim
|
||||
# Download from http://jdk.java.net/9/
|
||||
# ADD http://download.java.net/java/GA/jdk9/9/binaries/openjdk-9_linux-x64_bin.tar.gz
|
||||
ADD openjdk-9_linux-x64_bin.tar.gz /opt
|
||||
# Set up env variables
|
||||
ENV JAVA_HOME=/opt/jdk-9
|
||||
ENV PATH=$PATH:$JAVA_HOME/bin
|
||||
CMD ["jshell", "-J-XX:+UnlockExperimentalVMOptions", \
|
||||
"-J-XX:+UseCGroupMemoryLimitForHeap", \
|
||||
"-R-XX:+UnlockExperimentalVMOptions", \
|
||||
"-R-XX:+UseCGroupMemoryLimitForHeap"]
|
||||
----
|
||||
|
||||
This image uses `debian` slim as the base image and installs the OpenJDK build
|
||||
of JDK for linux x64 (see the setup section for how to download this into the
|
||||
current directory).
|
||||
|
||||
The image is configured by default to run `jshell` the Java REPL. The
|
||||
experimental flag `-XX:+UseCGroupMemoryLimitForHeap` is passed to the REPL
|
||||
process (the frontend Java process managing user input and the backend Java
|
||||
process managing compilation). This option will ensure container memory
|
||||
constraints are honored.
|
||||
|
||||
Build the image using the command:
|
||||
|
||||
docker build -t jdk-9-debian-slim -f jdk-9-debian-slim.Dockerfile .
|
||||
|
||||
List the images available using `docker image ls`:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
jdk-9-debian-slim latest 023f6999d94a 4 hours ago 400MB
|
||||
debian stable-slim d30525fb4ed2 4 days ago 55.3MB
|
||||
----
|
||||
|
||||
Other images may be shown as well but we are interested in these two images for
|
||||
now. The large difference in size is attributed to JDK 9, which is larger
|
||||
in size than JDK 8 because it also explicitly provides Java modules that we
|
||||
shall see more of later on in this chapter.
|
||||
|
||||
Run the container using the command:
|
||||
|
||||
docker container run -m=200M -it --rm jdk-9-debian-slim
|
||||
|
||||
to see the output:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
INFO: Created user preferences directory.
|
||||
| Welcome to JShell -- Version 9
|
||||
| For an introduction type: /help intro
|
||||
|
||||
jshell>
|
||||
----
|
||||
|
||||
Query the available memory of the Java process by typing the following
|
||||
expression into the Java REPL:
|
||||
|
||||
Runtime.getRuntime().maxMemory() / (1 << 20)
|
||||
|
||||
to see the output:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
jshell> Runtime.getRuntime().maxMemory() / (1 << 20)
|
||||
$1 ==> 100
|
||||
----
|
||||
|
||||
Notice that the Java process is honoring memory constraints (see the `--memory`
|
||||
of `docker run`) and will not allocate memory beyond that specified for the
|
||||
container.
|
||||
|
||||
In a future release of the JDK it will no longer be necessary to specify an
|
||||
experimental flag (`-XX:+UnlockExperimentalVMOptions`) once the mechanism by
|
||||
which memory constraints are efficiently detected is stable.
|
||||
|
||||
JDK 9 supports the set CPUs constraint (see the `----cpuset-cpus` of
|
||||
`docker run`) but does not currently support other CPU constraints such as
|
||||
CPU shares. This is ongoing work http://openjdk.java.net/jeps/8182070[tracked]
|
||||
in the OpenJDK project.
|
||||
|
||||
Note: the support for CPU sets and memory constraints have also been backported
|
||||
to JDK 8 release 8u131 and above.
|
||||
|
||||
To list all the Java modules distributed with JDK 9 run the following command:
|
||||
|
||||
docker container run -m=200M -it --rm jdk-9-debian-slim java --list-modules
|
||||
|
||||
In total there should be 75 modules:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
$ docker container run -m=200M -it --rm jdk-9-debian-slim java --list-modules | wc -l
|
||||
75
|
||||
----
|
||||
|
||||
=== Create a Docker Image using JDK 9 and Alpine Linux
|
||||
|
||||
Instead of `debian` as the base image it is possible to use Alpine Linux
|
||||
with an early access build of JDK 9 that is compatible with the muslc library
|
||||
shipped with Alpine Linux.
|
||||
|
||||
Create a new text file `jdk-9-alpine.Dockerfile`.
|
||||
Use the following contents:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
# A JDK 9 with Alpine Linux
|
||||
FROM alpine:3.6
|
||||
# Add the musl-based JDK 9 distribution
|
||||
RUN mkdir /opt
|
||||
# Download from http://jdk.java.net/9/
|
||||
# ADD http://download.java.net/java/jdk9-alpine/archive/181/binaries/jdk-9-ea+181_linux-x64-musl_bin.tar.gz
|
||||
ADD jdk-9-ea+181_linux-x64-musl_bin.tar.gz /opt
|
||||
# Set up env variables
|
||||
ENV JAVA_HOME=/opt/jdk-9
|
||||
ENV PATH=$PATH:$JAVA_HOME/bin
|
||||
CMD ["jshell", "-J-XX:+UnlockExperimentalVMOptions", \
|
||||
"-J-XX:+UseCGroupMemoryLimitForHeap", \
|
||||
"-R-XX:+UnlockExperimentalVMOptions", \
|
||||
"-R-XX:+UseCGroupMemoryLimitForHeap"]
|
||||
----
|
||||
|
||||
This image uses `alpine` 3.6 as the base image and installs the OpenJDK build
|
||||
of JDK for Alpine Linux x64 (see the link:ch01-setup.adoc[Setup Environments]
|
||||
chapter for how to download this into the current directory).
|
||||
|
||||
The image is configured in the same manner as for the `debian`-based image.
|
||||
|
||||
Build the image using the command:
|
||||
|
||||
docker build -t jdk-9-alpine -f jdk-9-alpine.Dockerfile .
|
||||
|
||||
List the images available using `docker image ls`:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
jdk-9-debian-slim latest 023f6999d94a 4 hours ago 400MB
|
||||
jdk-9-alpine latest f5a57382f240 4 hours ago 356MB
|
||||
debian stable-slim d30525fb4ed2 4 days ago 55.3MB
|
||||
alpine 3.6 7328f6f8b418 3 months ago 3.97MB
|
||||
----
|
||||
|
||||
Notice the difference in image sizes. Alpine Linux by design has been carefully
|
||||
crafted to produce a minimal running OS image. A cost of such a design is
|
||||
an alternative standard library https://www.musl-libc.org/[musl libc] that is
|
||||
not compatible with the C standard library (libc). As a result the JDK requires
|
||||
modifications to run on Alpine Linux. Such modifications have been proposed
|
||||
by the OpenJDK http://openjdk.java.net/projects/portola/[Portola Project].
|
||||
|
||||
|
||||
=== Create a Docker Image using JDK 9 and a Java application
|
||||
|
||||
Clone the GitHib project https://github.com/PaulSandoz/helloworld-java-9 that
|
||||
contains a simple Java 9-based project:
|
||||
|
||||
git clone https://github.com/PaulSandoz/helloworld-java-9.git
|
||||
|
||||
(If you have a github account you may wish to fork it and then clone the fork
|
||||
so you can make modifications.)
|
||||
|
||||
Enter the directory `helloworld-java-9` and build the project from within a
|
||||
running Docker container with JDK 9 installed:
|
||||
|
||||
docker run --volume $PWD:/helloworld-java-9 --workdir /helloworld-java-9 \
|
||||
-it --rm openjdk:9-jdk-slim \
|
||||
./mvnw package
|
||||
|
||||
(If you have JDK 9 installed locally on the host system you can build directly
|
||||
with `./mvnw package`.)
|
||||
|
||||
In this case we are using the `openjdk:9-jdk-slim` on Docker hub that has been
|
||||
configured to work with SSL certificates so that the maven wrapper tool can
|
||||
successfully download the maven tool. This image is not produced or in anyway
|
||||
endorsed by the OpenJDK project (unlike the JDK 9 distributions that were
|
||||
previously required). It is anticipated that future releases of the JDK from
|
||||
the OpenJDK project will have root CA certificates (see issue
|
||||
https://bugs.openjdk.java.net/browse/JDK-8189131[JDK-8189131])
|
||||
|
||||
To build Docker image for this application create a new text file
|
||||
`helloworld-jdk-9.Dockerfile` with the following contents:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
# Hello world application with JDK 9 and Debian slim
|
||||
FROM jdk-9-debian-slim
|
||||
COPY target/helloworld-1.0-SNAPSHOT.jar /opt/helloworld/helloworld-1.0-SNAPSHOT.jar
|
||||
# Set up env variables
|
||||
CMD java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap \
|
||||
-cp /opt/helloworld/helloworld-1.0-SNAPSHOT.jar org.examples.java.App
|
||||
----
|
||||
|
||||
Build a Docker image containing the simple Java application based of the Docker
|
||||
image `jdk-9-debian-slim`:
|
||||
|
||||
docker build -t helloworld-jdk-9 -f helloworld-jdk-9.Dockerfile .
|
||||
|
||||
List the images available using `docker image ls`:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
helloworld-jdk-9 latest eb0539e9529a 19 seconds ago 400MB
|
||||
jdk-9-debian-slim latest 023f6999d94a 5 hours ago 400MB
|
||||
jdk-9-alpine latest f5a57382f240 5 hours ago 356MB
|
||||
openjdk 9-jdk-slim 6dca67f4790e 3 days ago 372MB
|
||||
debian stable-slim d30525fb4ed2 4 days ago 55.3MB
|
||||
alpine 3.6 7328f6f8b418 3 months ago 3.97MB
|
||||
----
|
||||
|
||||
Notice how large the application image `helloworld-jdk-9`.
|
||||
|
||||
Run the `jdeps` tool to see what modules the application depends on:
|
||||
|
||||
docker run -it --rm helloworld-jdk-9 jdeps --list-deps /opt/helloworld/helloworld-1.0-SNAPSHOT.jar
|
||||
|
||||
and observe that the application only depends on the `java.base` module.
|
||||
|
||||
=== Reduce the size of a Docker Image using JDK 9 and a Java application
|
||||
|
||||
The Java application is extremely simple and as a result uses very little of the
|
||||
functionality shipped with JDK 9 distribution, specifically the application
|
||||
only depends on functionality present in the `java.base` module. We can create
|
||||
a custom Java runtime that only contains the `java.base` module and include
|
||||
that in application Docker image.
|
||||
|
||||
Create a custom Java runtime that is small and only contains the `java.base`
|
||||
module:
|
||||
|
||||
docker run --rm \
|
||||
--volume $PWD:/out \
|
||||
jdk-9-debian-slim \
|
||||
jlink --module-path /opt/jdk-9/jmods \
|
||||
--verbose \
|
||||
--add-modules java.base \
|
||||
--compress 2 \
|
||||
--no-header-files \
|
||||
--output /out/target/openjdk-9-base_linux-x64
|
||||
|
||||
The JDK 9 tool `jlink` is used to create the custom Java runtime. The tool
|
||||
is executed from with the container containing JDK 9 and directory where the
|
||||
modules reside, `/opt/jdk-9/jmods`, is declared in the module path. Only the
|
||||
`java.base` module is selected.
|
||||
|
||||
The custom runtime is output to the `target` directory:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
$ du -k target/openjdk-9-base_linux-x64/
|
||||
24 target/openjdk-9-base_linux-x64//bin
|
||||
12 target/openjdk-9-base_linux-x64//conf/security/policy/limited
|
||||
8 target/openjdk-9-base_linux-x64//conf/security/policy/unlimited
|
||||
24 target/openjdk-9-base_linux-x64//conf/security/policy
|
||||
68 target/openjdk-9-base_linux-x64//conf/security
|
||||
76 target/openjdk-9-base_linux-x64//conf
|
||||
44 target/openjdk-9-base_linux-x64//legal/java.base
|
||||
44 target/openjdk-9-base_linux-x64//legal
|
||||
72 target/openjdk-9-base_linux-x64//lib/jli
|
||||
16 target/openjdk-9-base_linux-x64//lib/security
|
||||
19824 target/openjdk-9-base_linux-x64//lib/server
|
||||
31656 target/openjdk-9-base_linux-x64//lib
|
||||
31804 target/openjdk-9-base_linux-x64/
|
||||
----
|
||||
|
||||
To build Docker image for this application with the custom Java runtime create a
|
||||
new text file `helloworld-jdk-9-base.Dockerfile` with the following contents:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
# Hello world application with custom Java runtime with just the base module and Debian slim
|
||||
FROM debian:stable-slim
|
||||
COPY target/openjdk-9-base_linux-x64 /opt/jdk-9
|
||||
COPY target/helloworld-1.0-SNAPSHOT.jar /opt/helloworld/helloworld-1.0-SNAPSHOT.jar
|
||||
# Set up env variables
|
||||
ENV JAVA_HOME=/opt/jdk-9
|
||||
ENV PATH=$PATH:$JAVA_HOME/bin
|
||||
CMD java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap \
|
||||
-cp /opt/helloworld/helloworld-1.0-SNAPSHOT.jar org.examples.java.App
|
||||
----
|
||||
|
||||
Build a Docker image containing the simple Java application based of the Docker
|
||||
image `debian:stable-slim`:
|
||||
|
||||
docker build -t helloworld-jdk-9-base -f helloworld-jdk-9-base.Dockerfile .
|
||||
|
||||
List the images available using `docker image ls`:
|
||||
|
||||
[source, text]
|
||||
----
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
helloworld-jdk-9-base latest 7052483fdb77 24 seconds ago 87.7MB
|
||||
helloworld-jdk9 latest eb0539e9529a 17 minutes ago 400MB
|
||||
jdk-9-debian-slim latest 023f6999d94a 5 hours ago 400MB
|
||||
jdk-9-alpine latest f5a57382f240 5 hours ago 356MB
|
||||
openjdk 9-jdk-slim 6dca67f4790e 3 days ago 372MB
|
||||
debian stable-slim d30525fb4ed2 4 days ago 55.3MB
|
||||
alpine 3.6 7328f6f8b418 3 months ago 3.97MB
|
||||
[source, text]
|
||||
----
|
||||
|
||||
The `helloworld-jdk-9-base` is much smaller and could be reduced further if
|
||||
Alpine Linux was used instead of Debian Slim.
|
||||
|
||||
A realistic application will depend on more JDK modules but it's still possible
|
||||
to significantly reduce the Java runtime to only the required modules (for
|
||||
example many applications will not require Corba or RMI nor the compiler tools).
|
|
@ -4,7 +4,9 @@ This tutorial offers Java developers an intro-level and self-paced hands-on work
|
|||
|
||||
* link:chapters/ch01-setup.adoc[Setup Environments]
|
||||
* link:chapters/ch02-basic-concepts.adoc[Docker Basic Concepts]
|
||||
* link:chapters/ch03-build-image.adoc[Build a Docker Image]
|
||||
* Building
|
||||
** link:chapters/ch03-build-image.adoc[Build a Docker Image]
|
||||
** link:chapters/ch03-build-image-java-9.adoc[Build a Docker Image for Java 9]
|
||||
* link:chapters/ch04-run-container.adoc[Run a Docker Container]
|
||||
* link:chapters/ch05-compose.adoc[Multi-container application using Docker Compose]
|
||||
* link:chapters/ch06-swarm.adoc[Multi-container application using Compose and Swarm Mode]
|
||||
|
|
Загрузка…
Ссылка в новой задаче