Skip to content

Latest commit

 

History

History
230 lines (159 loc) · 10.2 KB

README.adoc

File metadata and controls

230 lines (159 loc) · 10.2 KB
tags projects
docker
spring boot
spring-boot

This guide walks you through the process of building a Docker image for running a Spring Boot application.

What you’ll build

Docker is a Linux container management toolkit with a "social" aspect, allowing users to publish container images and consume those published by others. A Docker image is a recipe for running a containerized process, and in this guide we will build one for a simple Spring boot application.

What you’ll need

If you are NOT using a Linux machine, you will need a virtualized server. By installing VirtualBox, other tools like the Mac’s boot2docker, can seamlessly manage it for you. Visit VirtualBox’s download site and pick the version for your machine. Download and install. Don’t worry about actually running it.

You will also need Docker, which only runs on 64-bit machines. See https://docs.docker.com/installation/#installation for details on setting Docker up for your machine. Before proceeding further, verify you can run docker commands from the shell. If you are using boot2docker you need to run that first.

Set up a Spring Boot app

Now you can create a simple application.

src/main/java/hello/Application.java

link:complete/src/main/java/hello/Application.java[role=include]

The class is flagged as a @SpringBootApplication and as a @RestController, meaning it’s ready for use by Spring MVC to handle web requests. @RequestMapping maps / to the home() method which just sends a 'Hello World' response. The main() method uses Spring Boot’s SpringApplication.run() method to launch an application.

Now we can run the application without the Docker container (i.e. in the host OS).

If you are using Gradle, execute:

./gradlew build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar

If you are using Maven, execute:

mvn package && java -jar target/gs-spring-boot-docker-0.1.0.jar

and go to localhost:8080 to see your "Hello Docker World" message.

Containerize It

Docker has a simple "Dockerfile" file format that it uses to specify the "layers" of an image. So let’s go ahead and create a Dockerfile in our Spring Boot project:

src/main/docker/Dockerfile

link:complete/src/main/docker/Dockerfile[role=include]

This Dockerfile is very simple, but that’s all you need to run a Spring Boot app with no frills: just Java and a JAR file. The project JAR file is ADDed to the container as "app.jar" and then executed in the ENTRYPOINT.

Note
We added a VOLUME pointing to "/tmp" because that is where a Spring Boot application creates working directories for Tomcat by default. The effect is to create a temporary file on your host under "/var/lib/docker" and link it to the container under "/tmp". This step is optional for the simple app that we wrote here, but can be necessary for other Spring Boot applications if they need to actually write in the filesystem.
Note
You can use a RUN command to "touch" the jar file so that it has a file modification time (Docker creates all container files in an "unmodified" state by default). This actually isn’t important for the simple app that we wrote, but any static content (e.g. "index.html") would require the file to have a modification time.
Note
To reduce Tomcat startup time we added a system property pointing to "/dev/urandom" as a source of entropy.
Note
if you are using boot2docker you need to run it first before you do anything with the Docker command line or with the build tools (it runs a daemon process that handles the work for you in a virtual machine).

To build the image you can use some tooling for Maven or Gradle from the community (big thanks to Transmode and Spotify for making those tools available).

Build a Docker Image with Maven

In the Maven pom.xml you should add a new plugin like this (see the plugin documentation for more options): :

pom.xml

    <properties>
  	    <docker.image.prefix>springio</docker.image.prefix>
    </properties>
    <build>
        <plugins>
link:complete/pom.xml[role=include]
        </plugins>
    </build>

The configuration specifies 3 things:

  • The image name (or tag), which will end up here as springio/gs-spring-boot-docker

  • The directory in which to find the Dockerfile

  • The resources (files) to copy from the target directory to the docker build (alongside the Dockerfile) - we only need the jar file in this example

Important
Before proceeding with the following steps (which use Docker’s CLI tools), make sure Docker is properly running by typing docker ps. If you get an error message, something may not be set up correctly. Using a Mac? Add $(boot2docker shellinit 2> /dev/null) to the bottom of your .bash_profile (or similar env-setting configuration file) and refresh your shell to ensure proper environment variables are configured.

You can build a tagged docker image and then push it to a remote repository using the "docker" command line like this:

$ mvn package docker:build
$ docker push springio/gs-spring-boot-docker
Note
You don’t have to push your newly minted Docker image to actually run it. Moreover the "push" command will fail if you aren’t a member of the "springio" organization on Dockerhub. Change the build configuration and the command line to your own username instead of "springio" to make it actually work.
Note
package MUST be run before docker:build. Otherwise, it will fail.

Build a Docker Image with Gradle

If you are using Gradle you need to add a new plugin like this:

build.gradle

buildscript {
    ...
    dependencies {
        ...
link:complete/build.gradle[role=include]
    }
}

group = 'springio'

...
link:complete/build.gradle[role=include]

link:complete/build.gradle[role=include]

The configuration specifies 3 things:

  • the image name (or tag) is set up from the jar file properties, which will end up here as springio/gs-spring-boot-docker

  • the directory in which to find the Dockerfile

  • the jar file is copied from the build directory to the docker build (alongside the Dockerfile) - we only need the jar file in this example

You can build a tagged docker image and then push it to a remote repository with Gradle in one command:

$ ./gradlew build buildDocker

After the Push

The "docker push" will fail for you (unless you are part of the "springio" organization at Dockerhub), but if you change the configuration to match your own docker ID then it should succeed, and you will have a new tagged, deployed image.

Note

You do NOT have to register with docker or publish anything to run a docker image. You still have a locally tagged image, and you can run it like this:

$ docker run -p 8080:8080 -t springio/gs-spring-boot-docker
....
2015-03-31 13:25:48.035  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2015-03-31 13:25:48.037  INFO 1 --- [           main] hello.Application                        : Started Application in 5.613 seconds (JVM running for 7.293)

The application is then available on http://localhost:8080 (visit that and it says "Hello Docker World"). To make sure the whole process is really working, change the prefix from "springio" to something else (e.g. ${env.USER}) and go through it again from the build through to the docker run.

Note

When using a Mac with boot2docker, you typically see things like this at startup:

Docker client to the Docker daemon, please set:
    export DOCKER_CERT_PATH=/Users/gturnquist/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1
    export DOCKER_HOST=tcp://192.168.59.103:2376

To see the app, you must visit the IP address in DOCKER_HOST instead of localhost. In this case, http://192.168.59.103:8080, the public facing IP of the VM.

When it is running you can see in the list of containers, e.g:

$ docker ps
CONTAINER ID        IMAGE                             COMMAND                CREATED             STATUS              PORTS                    NAMES
81c723d22865        springio/gs-spring-boot-docker:latest   "java -jar /app.jar"   34 seconds ago      Up 33 seconds       0.0.0.0:8080->8080/tcp   goofy_brown

and to shut it down again you can docker stop with the container ID from the listing above (yours will be different):

$ docker stop 81c723d22865
81c723d22865

If you like you can also delete the container (it is persisted in your filesystem under /var/lib/docker somewhere) when you are finished with it:

$ docker rm 81c723d22865

Using Spring Profiles

Running your freshly minted Docker image with Spring profiles is as easy as passing an environment variable to the Docker run command

$ docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker

or

$ docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker

Summary

Congratulations! You’ve just created a Docker container for a Spring Boot app! Spring Boot apps run on port 8080 inside the container by default and we mapped that to the same port on the host using "-p" on the command line.