Introduction to Dockers and Containers

Overview

  • Containerization is an approach to software development in which an application or service, its dependencies, and its configuration (abstracted as deployment manifest files) are packaged together as a container image. The containerized application can be tested as a unit and deployed as a container image instance to the host operating system (OS).
  • Just as shipping containers allow goods to be transported by ship, train, or truck regardless of the cargo inside, software containers act as a standard unit of software deployment that can contain different code and dependencies. Containerizing software this way enables developers and IT professionals to deploy them across environments with little or no modification.
  • Containers also isolate applications from each other on a shared OS. Containerized applications run on top of a container host that in turn runs on the OS (Linux or Windows). Containers therefore have a significantly smaller footprint than virtual machine (VM) images

Benefits

  • Another benefit of containerization is scalability. You can scale out quickly by creating new containers for short-term tasks. From an application point of view, instantiating an image (creating a container) is similar to instantiating a process like a service or web app.
  • For reliability, however, when you run multiple instances of the same image across multiple host servers, you typically want each container (image instance) to run in a different host server or VM in different fault domains.
  • In short, containers offer the benefits of isolation, portability, agility, scalability, and control across the whole application lifecycle workflow. The most important benefit is the environment’s isolation provided between Dev and Ops

Features of Containers

1. Containers are PORTABLE across different types of infrastructure ,viz, they can run in AWS just as easily as they can on bare-metal servers 

2.  Containers make DEPLOYMENT of code extremely convenient

3. Linux containers make use of kernel interfaces such as cnames and namespaces, which allow multiple containers to share the same kernel while running in complete isolation from one another. The Docker execution environment uses a module called libcontainer, which standardizes these interfaces

4. Containers also help with the efficient utilization of resources on a host. If a given service isn’t using all the resources on an Amazon EC2 instance, additional services can be launched in containers on that instance that make use of the idle resources

What is Monolithic

Many of these applications used a monolithic architecture. The application is deployed as a single file (i.e. Java) or a collection of files rooted at the same directory (i.e. Rails) All the application code runs in the same process Scaling requires deploying multiple copies of the exact same application code to multiple servers

Docker:Simple Microservice with Springboot

1. Sign up with docker

Open docker

Login to docker: docker login

1.2. Git Clone

1.3. Install Maven

2. Building the docker image

  • Open docker and login
  • Navigate to the build-scm-containers/Build-SCM-Containers/
  • This folder already has a Dockerfile
  • Build a tagged docker image: mvn install dockerfile:build
    • Logs
[←[1;34mINFO←[m] Building Docker context C:\Users\user\java_j2ee_training\Docker
_SBoot
[←[1;34mINFO←[m]
[←[1;34mINFO←[m] Image will be built as docker.springboot/docker.sboot:latest
[←[1;34mINFO←[m]
[←[1;34mINFO←[m] Step 1/5 : FROM openjdk:8-jdk-alpine
[←[1;34mINFO←[m] Pulling from library/openjdk
[←[1;34mINFO←[m] Digest: sha256:bd4030dd52cfb61a61e622fe74483e4e2089a2ef3d782bbf
742a0d99093da119
[←[1;34mINFO←[m] Status: Image is up to date for openjdk:8-jdk-alpine
[←[1;34mINFO←[m]  ---> cc2179b8f042
[←[1;34mINFO←[m] Step 2/5 : VOLUME /tmp
[←[1;34mINFO←[m]  ---> Using cache
[←[1;34mINFO←[m]  ---> d250cc529d86
[←[1;34mINFO←[m] Step 3/5 : ARG JAR_FILE
[←[1;34mINFO←[m]  ---> Using cache
[←[1;34mINFO←[m]  ---> 8a843ac60e13
[←[1;34mINFO←[m] Step 4/5 : COPY ${JAR_FILE} app.jar
[←[1;34mINFO←[m]  ---> eed6fe73ce56
[←[1;34mINFO←[m] Removing intermediate container 24826b960be2
[←[1;34mINFO←[m] Step 5/5 : ENTRYPOINT java -Djava.security.egd=file:/dev/./uran
dom -jar /app.jar
[←[1;34mINFO←[m]  ---> Running in e5523f0d20d9
[←[1;34mINFO←[m]  ---> 0545584f5207
[←[1;34mINFO←[m] Removing intermediate container e5523f0d20d9
[←[1;34mINFO←[m] Successfully built 0545584f5207
[←[1;34mINFO←[m] Successfully tagged docker.springboot/docker.sboot:latest
[←[1;34mINFO←[m]
[←[1;34mINFO←[m] Detected build of image with id 0545584f5207
[←[1;34mINFO←[m] Building jar: C:\Users\user\java_j2ee_training\Docker_SBoot\tar
get\docker.sboot-0.0.1-SNAPSHOT-docker-info.jar
[←[1;34mINFO←[m] Successfully built docker.springboot/docker.sboot:latest
[←[1;34mINFO←[m] ←[1m-----------------------------------------------------------
-------------←[m
[←[1;34mINFO←[m] ←[1;32mBUILD SUCCESS←[m
[←[1;34mINFO←[m] ←[1m-----------------------------------------------------------
-------------←[m
[←[1;34mINFO←[m] Total time: 01:05 min
[←[1;34mINFO←[m] Finished at: 2018-06-09T17:54:12+05:30
[←[1;34mINFO←[m] Final Memory: 53M/539M
[←[1;34mINFO←[m] ←[1m-----------------------------------------------------------
-------------←[m

2.2. Code and Explanations

  • 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
  • To reduce Tomcat startup time we added a system property pointing to “/dev/urandom” as a source of entropy
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  • pom.xml is updated with dockerfile-maven-plugin which is a helper to create docker images
  • The configuration specifies 3 things:
    • The repository with the image name, which will end up here as docker.springboot/docker.sboot
    • The name of the jar file, exposing the Maven configuration as a build argument for docker
    • Optionally, the image tag, which ends up as latest if not specified. It can be set to the artifact id if desired
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>docker.sboot</groupId>
	<artifactId>docker.sboot</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>DockerSboot</name>
	<description>Spring boot on docker</description>
	<properties>
		<docker.image.prefix>docker.springboot</docker.image.prefix>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<start-class>com.dockerms.DockerSBootApplication</start-class>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jersey</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-mongodb</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<!-- tag::plugin[] -->
			<plugin>
				<groupId>com.spotify</groupId>
				<artifactId>dockerfile-maven-plugin</artifactId>
				<version>1.3.6</version>
				<configuration>
					<repository>${docker.image.prefix}/${project.artifactId}</repository>
					<buildArgs>
						<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
					</buildArgs>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

3. Run the image

docker run -p 8080:8080 -t docker.springboot/docker.sboot

4. Pushing the image to local registry in docker [Optional]

Ref: https://ropenscilabs.github.io/r-docker-tutorial/04-Dockerhub.html

4.1. Updating the image

  • docker ps
$ docker ps
CONTAINER ID        IMAGE                            COMMAND                  CR
EATED             STATUS              PORTS

                                                  NAMES
b0d52b407984        docker.springboot/docker.sboot   "java -Djava.securit"   7 m
inutes ago       Up 7 minutes        0.0.0.0:8080->8080/tcp

                                                 vibrant_moore
b1d59bbce322        graphiteapp/graphite-statsd      "/entrypoint"            4
weeks ago         Up 2 hours          0.0.0.0:80->80/tcp, 0.0.0.0:2003-2004->200
3-2004/tcp, 2013-2014/tcp, 8080/tcp, 0.0.0.0:2023-2024->2023-2024/tcp, 0.0.0.0:8
126->8126/tcp, 8125/tcp, 0.0.0.0:8125->8125/udp   graphite
  • Stop the microservice image
docker stop b0d52b407984
  • Remove the image from the container
docker rm b0d52b407984
  • Make changes to the source code
  • git pull
  • Rebuild the images

5. Pushing the image to docker hub using docker itself

  • Create an user id in https://hub.docker.com/
  • Create a repository,viz,microservices
  • Build the image
  • docker tag docker.springboot/docker.sboot pvijayakumar6/microservices:springbootv1
    • where springbootv1 is the image name in the docker hub
    • where docker.springboot/docker.sboot is the image name generated locally
  • docker push pvijayakumar6/microservices:springbootv1

where pvijayakumar6 is your user id in the hub.docker.com

5.1. Pushed image

5.2. Pull the image

  • docker run pvijayakumar6/microservices:springbootv1

5.3. Run the image

  • docker run -p 8080:8080 -t pvijayakumar6/microservices:springbootv1

6. Pushing the image using Maven

  • Result: Not working
  • You can push the image to dockerhub with mvn dockerfile:push * You can make dockerfile:push automatically run in the install or deploy lifecycle phases by adding it to the plugin configuration
<executions>
	<execution>
		<id>default</id>
		<phase>install</phase>
		<goals>
			<goal>build</goal>
			<goal>push</goal>
		</goals>
	</execution>
</executions>

6.2. Push error logs

[←[1;34mINFO←[m] ←[1m--- ←[0;32mdockerfile-maven-plugin:1.3.6:push←[m ←[1m(defau
lt-cli)←[m @ ←[36mdocker.sboot←[0;1m ---←[m
[←[1;33mWARNING←[m] The POM for commons-io:commons-io:jar:2.5 is invalid, transi
tive dependencies (if any) will not be available, enable debug logging for more
details
[←[1;34mINFO←[m] The push refers to a repository [docker.springboot/docker.sboot
]
[←[1;31mERROR←[m] Get https://docker.springboot/v1/_ping: dial tcp: lookup docke
r.springboot on 10.0.2.3:53: no such host
[←[1;33mWARNING←[m] An attempt failed, will retry 1 more times

7. Error and Solutions

  • Error encountered [below]
    • Solution: Rename the directory C:\Users\user\.m2\repository\org\eclipse\sisu to someother name
[←[1;31mERROR←[m] Failed to execute goal ←[32morg.springframework.boot:spring-bo
ot-maven-plugin:2.0.2.RELEASE:repackage←[m ←[1m(default)←[m on project ←[36mdock
er.sboot←[m: ←[1;31mExecution default of goal org.springframework.boot:spring-bo
ot-maven-plugin:2.0.2.RELEASE:repackage failed: Plugin org.springframework.boot:
spring-boot-maven-plugin:2.0.2.RELEASE or one of its dependencies could not be resolved: Failed to collect dependencies at org.springframework.boot:spring-boot-
maven-plugin:jar:2.0.2.RELEASE -> org.apache.maven:maven-core:jar:3.1.1 -> org.apache.maven:maven-plugin-api:jar:3.1.1 -> org.eclipse.sisu:org.eclipse.sisu.plex
us:jar:0.0.0.M5←[m: Failed to read artifact descriptor for org.eclipse.sisu:org.
eclipse.sisu.plexus:jar:0.0.0.M5: Could not transfer artifact org.eclipse.sisu:org.eclipse.sisu.plexus:pom:0.0.0.M5 from/to central (https://repo.maven.apache.org/maven2): C:\Users\user\.m2\repository\org\eclipse\sisu\org.eclipse.sisu.plexu
s\0.0.0.M5\org.eclipse.sisu.plexus-0.0.0.M5.pom.part.lock (The file or directory is corrupted and unreadable) -> ←[1m[Help 1]←[m
  • In case of error with maven Build using docker itself: docker build .
  • Logs
Sending build context to Docker daemon  27.14kB
Step 1/5 : FROM openjdk:8-jdk-alpine
 ---> cc2179b8f042
Step 2/5 : VOLUME /tmp
 ---> Using cache
 ---> d250cc529d86
Step 3/5 : ARG JAR_FILE
 ---> Using cache
 ---> 8a843ac60e13
Step 4/5 : COPY ${JAR_FILE} app.jar
 ---> 3f098453fc18
Removing intermediate container 75ab27332685
Step 5/5 : ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
 ---> Running in 7c00c5626adb
 ---> 59ea517f62ef
Removing intermediate container 7c00c5626adb
Successfully built 59ea517f62ef
SECURITY WARNING: You are building a Docker image from Windows against a non-Win
dows Docker host. All files and directories added to build context will have '-r
wxr-xr-x' permissions. It is recommended to double check and reset permissions f
or sensitive files and directories.
  • Observe that the log has a statement ->Successfully built 59ea517f62ef
    • where Successfully built 59ea517f62ef is the image name
  • Tag the built image as useful image name: docker tag 59ea517f62ef localhost:5000/docker.springboot/docker.sboot

where docker.springboot/docker.sboot is the useful image name

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: