Running Java inside a Windows container on a Windows server

TL;DR

You can run .NET/Java/Node.js/Whatever inside native Windows containers hosted on Windows servers. All you need is: Windows Server 2016 (or Windows 10), install Docker, install the Windows base image, create/run a docker image from a registry.

A new era?

There was(is?) a hype around Microsoft and .NET: C# language, .NET Framework and CLR Runtime have been open-sourced. They got Linux support. People exulted at running .NET Core applications inside Linux containers on Linux servers. Which is very cool, I’m sure. But let’s put .NET Core and tools aside otherwise I’ll end up crying (early adopters would understand).

There is an idea stuck in my head since: can we do the completely opposite act? Can we run Java inside a Windows container hosted on a Windows server? I don’t mean tools like Boot2Docker, Kitematic or new Docker Toolbox. They are all essentially a Linux VM. What I mean is native Docker experience on Windows where containers run natively without any virtualization layer.

Let’s figure it out!

Windows and Docker

We need a system running Windows Server 2016 which is Technical Preview 5 at the moment. BTW, It works on Windows 10 too, see the references below. Virtual machine works fine. In next steps we are going to enable the Container feature, install Docker and the base image. We need elevated PowerShell session on the system for that. Let’s go!

1. Install Container Feature

Install-WindowsFeature containers
Restart-Computer -Force # Yeah, it's still Windows ¯\_(ツ)_/¯

2. Install Docker

Microsoft has its own fork of Docker. They ship their own versions of the docker daemon and the docker client. Let’s get them:

# Create a directory
New-Item -Type Directory -Path 'C:\Program Files\Docker\'
# Download the Docker daemon
Invoke-WebRequest https://aka.ms/tp5/b/dockerd -OutFile $env:ProgramFiles\Docker\dockerd.exe
# Download the Docker client
Invoke-WebRequest https://aka.ms/tp5/b/docker -OutFile $env:ProgramFiles\Docker\docker.exe
# Add the Docker directory to the system path
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\Docker", [EnvironmentVariableTarget]::Machine)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
# Install as a Windows service
dockerd --register-service
Start-Service Docker

3. Install Base Container Image

Next we need to install the Windows Server Core base image which is provided by Microsoft and includes the core OS components. It is used as a base image by other Windows-based images.

Install-PackageProvider ContainerImage -Force
Install-ContainerImage -Name WindowsServerCore -Version 10.0.14300.1000
Restart-Service docker
docker tag windowsservercore:10.0.14300.1000 windowsservercore:latest

If we check installed images we will see the following picture. (Please, don’t look at the images’ sizes otherwise you’ll be scared.)

PS C:\Windows\system32> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
windowsservercore   10.0.14300.1000     dbfee88ee9fd        11 weeks ago        9.344 GB
windowsservercore   latest              dbfee88ee9fd        11 weeks ago        9.344 GB

If the command executed successfully and we see the images then we are good. That’s all we need to start with container images.

Windows container images

Let’s have a look at the images that Microsoft provides:

PS C:\Windows\system32> docker search microsoft
NAME                                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
microsoft/sample-django:windowsservercore    Django installed in a Windows Server Core ...   1                    [OK]
microsoft/dotnet35:windowsservercore         .NET 3.5 Runtime installed in a Windows Se...   1         [OK]       [OK]
microsoft/sample-golang:windowsservercore    Go Programming Language installed in a Win...   1                    [OK]
microsoft/sample-httpd:windowsservercore     Apache httpd installed in a Windows Server...   1                    [OK]
microsoft/iis:windowsservercore              Internet Information Services (IIS) instal...   1         [OK]       [OK]
microsoft/sample-mongodb:windowsservercore   MongoDB installed in a Windows Server Core...   1                    [OK]
microsoft/sample-mysql:windowsservercore     MySQL installed in a Windows Server Core b...   1                    [OK]
microsoft/sample-nginx:windowsservercore     Nginx installed in a Windows Server Core b...   1                    [OK]
microsoft/sample-python:windowsservercore    Python installed in a Windows Server Core ...   1                    [OK]
microsoft/sample-rails:windowsservercore     Ruby on Rails installed in a Windows Serve...   1                    [OK]
microsoft/sample-redis:windowsservercore     Redis installed in a Windows Server Core b...   1                    [OK]
microsoft/sample-ruby:windowsservercore      Ruby installed in a Windows Server Core ba...   1                    [OK]
microsoft/sample-sqlite:windowsservercore    SQLite installed in a Windows Server Core ...   1                    [OK]

It’s long enough for the start: .NET, IIS, Go, Python, Ruby, MySQL, … Wait! Where’s Java? How come??? Okaaay, Let’s create it by ourselves.

4. Create an image with Java

Create a Dockerfile, c:\java-windows-docker\Dockerfile, and put the following lines inside:

FROM windowsservercore

RUN powershell (new-object System.Net.WebClient).Downloadfile('http://javadl.oracle.com/webapps/download/AutoDL?BundleId=210185', 'C:\jre-8u91-windows-x64.exe')
RUN powershell start-process -filepath C:\jre-8u91-windows-x64.exe -passthru -wait -argumentlist "/s,INSTALLDIR=c:\Java\jre1.8.0_91,/L,install64.log"
RUN del C:\jre-8u91-windows-x64.exe

CMD [ "c:\\Java\\jre1.8.0_91\\bin\\java.exe", "-version"]

It downloads the Java 8 Update 91 Windows installer and silently installs it to c:\Java\jre1.8.0_91. After start, the container launches Java and prints out its version.
Let’s build the image:

docker build -t java-windows-docker c:\java-windows-docker

And if we run it…

PS C:\Windows\system32> docker run java-windows-docker
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b15, mixed mode)

We have Java running. Wow! Amazing!! We have Java running inside a Windows docker container which is hosted on a Windows server. Frankly, I wouldn’t believe this a couple of years ago. But things got real now!

What about Linux containers on Windows server? Unfortunately they aren’t supported. You will get an error if you try to pull/run one. But, it won’t surprise me if we could run .NET Core inside a Linux container on a Windows server sometime. Such a crazy time to code!

References

MSDN: Windows Containers Documentation

MSDN: Quick Start: Windows Containers on Windows Server

Channel 9: Containers 101 with Microsoft and Docker

MSDN: Windows Containers on Windows 10

GitHub: .NET Core Docker Images

GitHub: Windows Containers samples

Leave a Comment