In this article I am going to show how to build a Docker image containing a Java application using Maven. As an example, I will use a Spring Boot web application, which will be packaged into a Docker image. The application packaged does not need to be a Java application, but can be anything for which a Docker image can be created. I have, for instance, used the process described to make it possible to build regular Docker images on a Jenkins build server.

The Example Spring Boot Application

The Spring Boot web application I will use as an example Java application is created as follows:

In src/main/resources/templates, create a file named hello.html with the following contents:

hello.html

1

2

3

4

5

6

7

8

9

10

<!DOCTYPE HTML>

<html xmlns:th="http://www.thymeleaf.org">

<head>

<title>Greetings!</title>

<meta http-equiv="Content-Type"content="text/html; charset=UTF-8"/>

</head>

<body>

<pth:text="${greeting}"/>

</body>

</html>

The example application can now be started by running the SpringbootDockerimageApplication class. To test the application, enter the http://localhost:8080/hello?name=Ivan URL in a local browser. There should be a greeting in the browser window on the following format:

1

Hello Ivan, the time is now Sat Feb 11 22:57:33 CET 2017.

Prepare for Docker Image Creation

Setting up to create a Docker image for a Java application consists of two steps; the first step is much like for any Docker image in that a Docker file is created and the static contents of the Docker image is gathered/created. The second part consists of adding a Maven profile to the project’s pom.xml file.

Docker Directory and Its Contents

The Docker file and any additional static contents of the Docker image is created in the source of the project. In this example it is in the src/main/resources/docker directory. The location of this directory can be changed by modifying a property, as we will see later.

Create a directory named “docker” in the src/main/resources directory.

In the src/main/resources/docker directory, create a directory named “application”.

In the src/main/resources/docker/application directory, create two directories named “bin” and “lib”.

In the src/main/resources/docker/application/bin directory, create a file named “start-app.sh” with the following contents:

start-app.sh

Shell

1

2

#! /bin/sh

java-jar${JAR_PATH}

In the src/main/resources/docker directory, create a file name “Dockerfile” with this contents:

Dockerfile

Shell

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

# Docker image that contains a Spring Boot application.

#

FROM anapsix/alpine-java:8_jdk_unlimited

# Absolute path to the JAR file to be launched when a Docker container is started.

ENVJAR_PATH=/application/lib/springboot-webapp.jar

# Create directory to hold the application and all its contents in the Docker image.

RUN mkdir/application

# Copy all the static contents to be included in the Docker image.

COPY./application//application/

# Make all scripts in the bin directory executable. Includes start-script.

RUN chmod+x/application/bin/*.sh

# Web port.

EXPOSE8080

CMD["/application/bin/start-app.sh"]

Modify the Dockerfile accordingly if, for instance, you want to use another base image.

Maven Profile

To create the Docker image containing the Spring Boot application, I’ll use the following Maven plug-ins:

maven-resources-plugin
Copies files to a directory in which the Docker image will be built.
The files needed to build the Docker image are copied to a directory in the target directory of the project.

maven-dependency-plugin
Copies the JAR file containing the application and any additional Maven artifacts to the Docker image build directory.

Spotify’s docker-maven-plugin
Removes the Docker image produced by the project. Needed since, at the time of writing, the Maven plug-in used to build the Docker image will not overwrite an existing Docker image.

In the project’s Maven pom.xml file, I use a Maven profile to contain what is needed to build the Docker image. I have tried to rely on properties in the profile for configuration of the Docker image build in order to make it easier to adapt the profile to different Java applications.

The complete Docker image building Maven profile looks like this:

pom.xml

XHTML

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

<profiles>

<!--

This profile builds a Docker image with the Spring Boot application.

Before being able to build a Docker image using Maven, the environment

variable DOCKER_HOME need to be set to the endpoint of the local

Docker API.

Example *nix: export set DOCKER_HOME=http://localhost:2375

The Docker image is built using the following command:

mvn -Pdockerimage package

If a Docker image with the image name and tag (project version) already

exists then one of the following may happen depending on the

environment in which the build is run:

- The existing image is given the image name and tag <none>.

- No new Docker image is generated, but the existing image is retained.

There is a <dependencies> element.
Add any additional Maven dependencies to, for instance, third party libraries that you want to include in the Docker image in this element.

In the <properties> element, there is a property named docker.image.name.
This property contains the name of the Docker image that will be produced. I expect this property to be modified for each application. The Docker image tag will be the project’s version.

The next property in the <properties> element is docker.image.src.root.
This property holds the relative path to the directory that contains the Dockerfile and any additional static contents that is to be included in the Docker image.

The final property in the <properties> element is docker.build.directory.
This property holds the path to the directory in which the Docker image will be built.

In the <build> section of the profile, the first plug-in is the maven-resources-plugin.
This plug-in is used to copy static contents from the directory pointed at by the docker.image.src.root property to the directory which location is specified by the docker.build.directory property. The entire directory structure is preserved.

The second plug-in in the <build> section is the maven-dependency-plugin.
Using this plug-in, the JAR file that contains the Spring Boot application built by the project is copied to the application/lib directory in the directory in which the Docker image will be built. Recall that the location of the application JAR file is also stored into the environment variable JAR_PATH in the Dockerfile.
Note that a destination filename is specified for the application JAR, in order to have a fixed filename to refer to in the Dockerfile.

The third plug-in in the <build> section is the docker-maven-plugin.
Since the current version of the dockerfile-maven-plugin that we will discuss later does not overwrite existing Docker images, I have included this plug-in to be able to remove any existing Docker image when cleaning the Maven project.

The final plug-in is the dockerfile-maven-plugin.
This is the plug-in that is responsible for building the Docker image. The main reason that I chose this plug-in over the alternatives is that it allows me to create a Docker image from a Dockerfile – just like it works when I am creating Docker images by hand.

Create the Docker Image

If we now open a terminal window and go to the directory that contains the pom.xml file of the example Spring Boot web application, we can build the Docker image using this Maven command:

1

mvn -Pdockerimage package

After some time, the message BUILD SUCCESS should appear in the terminal and if you list the Docker images, you should see the new image listed:

1

2

3

$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

springboot-webapp 0.0.1-SNAPSHOT 16efcb5f8335 3 minutes ago 194.3 MB

Use the Docker Image

To start a Docker container using the newly produced Docker image, I use the command:

1

docker run -p 8080:8080 springboot-webapp:0.0.1-SNAPSHOT

Opening the URL http://localhost:8080/hello?name=Ivan (replace localhost with the appropriate IP if you run Docker in a virtual machine) in a browser, I see the same type of greeting that I saw when I was running the Spring Boot web application outside of the Docker container.