/ English

Getting Started with Spring Boot in Native Docker Containers on Windows Server 2016

As you might already know, in Windows Server 2016, Microsoft is hopping on the container bandwagon and offering support for both Linux-based Docker-containers running with Hyper-V and native Windows-based Docker-containers (called Windows Containers).

Most of the existing documentation uses .NET-based applications as an example, but it can just as well be used for Java-based applications. In this guide we will show you how to get started with Docker in Windows Server 2016 and get an "Hello World" Spring Boot application running in a container with a minimal Windows installation (Nano Server).

Spring Boot is a way to kick-start the development of applications based on the popular Spring framework and converts your web application into a self-contained executable JAR-file with a Tomcat servlet-container. This makes it easy to configure and migrate to other servers and containers.

Installing Docker on Windows Server 2016

There are several ways you can try out Docker on Windows Server 2016. The technology works inside of VMs, so some options for running it are:

  • A VM on your local machine
  • Installing directly to bare-metal
  • Accessing a remote VM in the cloud (Azure, Amazon AWS etc.)

There are evaluation licenses available for Windows Server if you do not have an MSDN-license available and want to try it locally. If you do want to enable Hyper-V isolation for containers, you need to run on a machine that exposes virtualization features from the CPU to Windows.

Before you start, you need to make sure that the machine is up to date, an all the Windows Updates have been run. Then start a Powershell-window as administrator and run the following commands:

Install-Module -Name DockerMsftProvider -Force
Install-Package -Name docker -ProviderName DockerMsftProvider -Force
Restart-Computer -Force

The last command will reboot the computer/VM and finish the installation. After it has rebooted, try running "docker" by itself in a Powershell-window to make sure that it has been installed and is available on path.

Run Your First Container

To verify that the engine works as intended, run the following from a Powershell-window to start a hello world container from Microsoft:

docker run microsoft/sample-dotnet

This will output a nice ASCII-art image in your Window to verify that it is running.
Output from the hello world container

Create the Java Image

Before we start packaging a Spring application inside of a Docker-container, we need an image that contains a Java runtime. At the time of writing, there are no official images (for Windows) with a JRE or JDK provided, so instead we need to create our own. Due to the way Java is downloaded, the easiest way to build an image is simply to download it from the Oracle website using a regular web browser and then use a COPY command in the Dockerfile to copy it into a container. In this example we use the Java 8 JDK update 112, adapt this to the newest update when you create the image.

Before we can add Java to the image, we need a Windows base image. Since we are not really depending on any specific Windows features or roles to be installed, we can use the Nano Server image that Microsoft makes available on Docker Hub. This base image is only in the order of a few hundred MBs in size, compared to GBs for the "full" Windows Server Core image. See https://hub.docker.com/u/microsoft/ for a full overview of the images that Microsoft make available.

Do the following to create the image:

  1. Create a new empty folder, in this example we use c:\docker\java-windows-docker

  2. Download the JDK/JRE from Oracle. If it is in archive form, extract it to a subfolder of java-windows-docker. If it is an installer, run it and copy the resulting directory instead.

  3. Inside the java-windows-docker folder, place a textfile simply called Dockerfile (no file extension), with the following content (adapt to the version of Java that you are using):

     FROM microsoft/nanoserver
     COPY jdk1.8.0_112 c:\jdk1.8.0_112
     CMD [ "c:\\jdk1.8.0_112\\bin\\java.exe", "-version"]
  4. Open a Powershell-window and navigate to the java-windows-docker folder.

  5. Run the following Docker-command to build the image:

     docker build -t java-windows-docker:jdk1.8-112 c:\docker\java-windows-docker
  6. Try to run the image in a container with:

     docker run -it java-windows-docker:jdk1.8-112 cmd
  7. Navigate to the path c:\jdk1.8.0_112\bin in the container and try to run:

     java -version
  8. Verify that Java runs and reports the correct version.

  9. Just run exit to stop the container.

This section was based on https://alexandrnikitin.github.io/blog/running-java-inside-windows-container-on-windows-server/.

Prepare the Demo Application

Now that we have a container running Java, it is time to prepare and application to run inside it. For this, we are going to use a Spring Boot demo application for Docker on Linux, and convert it over to a Windows-based image. It already has an Apache Maven based build process for the Docker image pre-configured.

The guide on how to build the Linux-image is available here: https://spring.io/guides/gs/spring-boot-docker/

Before you start, it is assumed that you have the Java 8 JDK and Apache Maven 3.3 already installed and that they are available on path on the host machine. In this case, we are going to build the JAR-file and the Docker-image on the same machine, but the JAR-file could be built on another system, and simply included in the Docker image on the server.

Do the following to create the image:

  1. Clone the Spring Boot example with the following command (in a Git Bash window):

     git clone https://github.com/spring-guides/gs-spring-boot-docker.git
  2. Open the file complete\pom.xml, change the docker.image.prefix property to your liking, for instance "acntech".

  3. Open the file complete\src\main\docker\Dockerfile and replace the content with the following to use the right base image and path to the Java runtime inside the container:

     FROM java-windows-docker:jdk1.8-112
     ADD gs-spring-boot-docker-0.1.0.jar app.jar
     ENTRYPOINT ["C:\\jdk1.8.0_112\\bin\\java.exe","-jar","/app.jar"]
  4. Now open a CMD or Powershell prompt and run the following in the "complete"-folder:

     mvn package docker:build
  5. You now have a Docker-image called acntech/gs-spring-boot-docker (if the prefix was set to acntech).

Building the Docker image is integrated directly into the Maven build process using docker-maven-plugin which builds a container on each build of the application.

Run the Finished Container

To actually test the demo application, we need to run the image we just created as a container. It can be started with the following command in a Powershell-window:

docker run -p 8080:8080 -it acntech/gs-spring-boot-docker

This will start the container in an interactive prompt where you can see the log of the Tomcat server. When it has started, it reports "Started Application in x seconds (JVM running for y)" (where x and y will depend on the startup time).

The container is assigned its own IP address, which we need to find to access the exposed service. First, run docker ps to find all the running containers and their names. Use that name into the following command to find the IP address:

docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" name_of_the_container.

When you know the address, open port 8080 in a web browser, for instance You should see a web page simply containing "Hello Docker World".
Hello Docker World web page

Implement your application

This Spring Boot application can easily be extended into a full-fledged Java application to enjoy all the benefits that containers have to offer. It also makes it easier to have the same toolchain in both the Linux and Windows runtime environments, even if the containers have to be rebuilt for each. Note that Docker-support has also been introduced into Windows 10 Pro, both for Windows and Linux containers, but the installation procedure is slightly different (an installer can be downloaded from the Docker website). This makes it possible to develop the application inside a container on the client and then reuse the same container in a production system on the server for a smoother continuous delivery workflow.

The next step would be to look at ways of orchestrating several containers to make it easier to bring up an instance of a complete solution instead of individual containers. Several other Docker tools are already available for Windows to make this happen.