In our previous example, when we built a Docker image, we published it into our local system repository so we can execute Docker run. Docker will be able to find them; this local repository exists only on our system, and most likely we need to have this access to wherever we like to run our Docker.
For example, we may create our Docker in a pipeline that runs on a machine that creates our builds, but the application itself may run in our pre production or production environments, so the Docker image should be available on any system that we need.
One of the great advantages of Docker is that any developer building an image can run it from their own system exactly as they would on any server. This will minimize the risk of having something different in each environment, or not being able to reproduce production when you try to find the source of a problem.
Docker provides a public repository, Docker Hub, that we can use to publish and pull images, but of course, you can use private Docker repositories such as Sonatype Nexus, VMware Harbor, or JFrog Artifactory. To learn how to configure additional repositories refer to the repositories documentation.
Docker Hub registration
After registering, we need to log into our account, so we can publish our Dockers using the Docker tool from the command line using Docker login:
docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.Docker.com to create one.
Username: mydockerhubuser
Password:
Login Succeeded
When we need to publish a Docker, we must always be logged into the registry that we are working with; remember to log into Docker.
Now we'd like to publish our Docker image to Docker Hub; but before we can, we need to build our images for our repository. When we create an account in Docker Hub, a repository with our username will be created; in this example, it will be mydockerhubuser. In order to build the Docker for our repository, we can use this command from our microservice directory:
docker build . -t mydockerhubuser/chapter07
This should be quite a fast process since all the different layers are cached:
Sending build context to Docker daemon 21.58MB
Step 1/3 : FROM openjdk:8-jdk-alpine
---> a2a00e606b82
Step 2/3 : ADD target/*.jar microservice.jar
---> Using cache
---> 4ae1b12e61aa
Step 3/3 : ENTRYPOINT java -jar microservice.jar
---> Using cache
---> 70d76cbf7fb2
Successfully built 70d76cbf7fb2
Successfully tagged mydockerhubuser/chapter07:latest
Now that our Docker is built, we can push it to Docker Hub with the following command:
docker push mydockerhubuser/chapter07
This command will take several minutes since the whole image needs to be uploaded. With our Docker published, we can now run it from any Docker system with the following command:
docker run mydockerhubuser/chapter07
Or else, we can run it as a daemon, with:
docker run -d mydockerhubuser/chapter07
Now that we know most of the Docker concepts, we can integrate Docker with Maven using the Docker-Maven-plugin created by fabric8, so we can create Docker as part of our Maven builds. First, we will move our Dockerfile to a different folder. In the IntelliJ Project window, right-click on the src folder and choose New | Directory. We will name it Docker. Now, drag and drop the existing Dockerfile into this new directory, and we will change it to the following:
FROM openjdk:8-jdk-alpine
ADD maven/*.jar microservice.jar
ENTRYPOINT ["java","-jar", "microservice.jar"]
To manage the Dockerfile better, we just move into our project folders. When our Docker is built using the plugin, the contents of our application will be created in a folder named Maven, so we change the Dockerfile to reference that folder.
Now, we will modify our Maven pom.xml, and add the Dockerfile-Maven-plugin in the build | plugins section:
<build>
....
<plugins>
....
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>Docker-maven-plugin</artifactId>
<version>0.23.0</version>
<configuration>
<verbose>true</verbose>
<images>
<image>
<name>mydockerhubuser/chapter07</name>
<build>
<dockerFileDir>${project.basedir}/src/Docker</dockerFileDir>
<assembly>
<descriptorRef>artifact</descriptorRef>
</assembly>
<tags>
<tag>latest</tag>
<tag>${project.version}</tag>
</tags>
</build>
<run>
<ports>
<port>8080:8080</port>
</ports>
</run>
</image>
</images>
</configuration>
</plugin>
</plugins>
</build>
Here, we are specifying how to create our Docker, where the Dockerfile is, and even which version of the Docker we are building. Additionally, we specify some parameters when our Docker runs, such as the port that it exposes. If we need IntelliJ to reload the Maven changes, we may need to click on the Reimport all maven projects button in the Maven Project window.
For building our Docker using Maven, we can use the Maven Project window by running the task Docker: build, or by running the following command:
mvnw docker:build
This will build the Docker image, but we require to have it before it's packaged, so we can perform the following command:
mvnw package docker:build
We can also publish our Docker using Maven, either with the Maven Project window to run the Docker: push task, or by running the following command:
mvnw docker:push
This will push our Docker into the Docker Hub, but if we'd like to do everything in just one command, we can just use the following code:
mvnw package docker:build docker:push
Finally, the plugin provides other tasks such as Docker: run, Docker: start, and Docker: stop, which we can use in the commands that we've already learned on the command line.
With this, we learned how to publish docker manually and integrate them into the Maven lifecycle. Do check out the book Hands-On Microservices with Kotlin to start simplifying development of microservices and building high quality service environment.
The key differences between Kubernetes and Docker Swarm
How to publish Microservice as a service onto a Docker