Docker for devs with hands-on| Part-3
In case you are landing here directly, it’s recommended to read through this documentation first.
Following are the topics, which we shall be touching through this blog :-
- Need of the docker.
- Delivery of Apps in traditional & modern world.
- Basics of docker, images, containers.
- Enhancing docker container by installing custom softwares.
- Launch custom Docker-Image from an existing docker container.
Question:- What are the issues, which makes us to think towards Docker?
Answer:- As developers of cross-functional teams, we might not have the thorough system expertise to build & run the micro-services :-
- Sometimes, we might end up using different spring profiles like development, qa, uat, etc for different environments.
- Sometimes, the application needs Tomcat to run, but Tomcat won’t start because it’s not correctly configured for your machine.
- Sometimes, you realize that you haven’t installed the correct Java development kit or you’ve got the wrong version of the JDK. E.g. The application was originally developed on Java 7 and yet we’ve installed Java 1.8.5_12 and the two versions are a mismatch.
- Say, the application depends on MySQL being installed on this machine. And so you have to install MySQL and then you’ve got to configure the security in the ports.
- And I’m going on and on and on.
In this entire process, I might lose an entire day of development just messing about, trying to get my computer in the same states that it was on the original development machine.
Question:- Traditionally, what do we deliver and how is that different from Docker world ?
Answer:- Traditionally as Java developers, we think of the Java file or the war file, same thing really as being the final deliverable, the end result of our build process. And that’s typically the item that we hand over to whoever is going to be responsible for deploying the system into production.
Docker changes the way that you think about delivering and deploying software to production. Instead of deploying a jar file, which we would run as an isolated application, we instead run containers and you can think of a container as being a complete, self-contained and complete environment inside a docker. A container would include following :-
- A fully configured Java virtual machine.
- A configured tomcat.
- Some kind of front end proxy server such as Nginx or Apache.
- A war file inside that container.
- And the container can also contain all of the necessary environment variables and configurations that container needs to run.
So this container is a totally self-contained, self-sufficient environment.
Question:- How does container is defined ?
Answer:- To define a docker container, you need to, first of all, build an image. And an image is a really important concept. In Docker, an image is a definition of the container. So, where previously a developer would have built a jar file or a war file here in an Integrated development environment such as IntelliJ, instead the developer is going to build an image. And that image, as described previously, is going to contain the definition of a complete environments, environment variables, the warfile, any supporting software needed, such as the Java, JDK Tomcats and so on.
Question:- Whats the difference between an Image and a Container ?
Answer:-
- A container is an instance of an image and you instantiate one of these images by simply running. The difference between an image and a container, the image is the entity that we build. And when we run that image, it will become a container at runtime.
- So, that means you could take a single image and you could run it multiple times, in which case you would end up with multiple containers all running the same image.
So, then the important thing about this then is that, instead of handing over a war file to a deployer, we’re going to hand over a docker image. And because the Docker image contains a complete environment that needs no further configuration, it’s much easier to deploy and to get it up and running.
Question:- What is the difference between Container and Virtual Machine?
Answer:- A container does not contain a full operating system and therefore it’s much lighter and much more efficient than running virtual machines. Let’s say, for example, that you’re running on a Linux based operating system.
Question:- What are the main parts of any Operating System ?
Answer:- The main parts of the operating system, which handles the low level services, such as memory management, device drivers and so on, is called the kernel.
Question:- Whats the relationship between Kernel and Container?
Answer:-
- When we launch a container, the container is running on top of your host operating systems kernel. And actually, the container is actually just a process running on your kernel.
- So, although a container might feel like a full virtual machine. It’s not a full virtual machine because it doesn’t contain its own operating system.
Question:- I want to download the Docker-Image containing Ubuntu. How can I do the same ?
Answer:-
Step #1.) Let’s first go and search for the various Docker-Images being available on the DockerHub regards to the ‘Ubuntu’.
Step #2.) Let’s now download the above docker-image of ‘Ubuntu’ to our local machine :-
docker image pull ubuntu
Question:- How do I run the container from the afore-downloaded Docker-Image ?
docker container run ubuntu
Question:- Though we started the docker-container with ‘Ubuntu’ image, but it was not active even for a minute. Why so ?
Answer:- Well, what’s going on here is that every single container when it started will run a command and your container will exist and will live and survive for as long as that command is running. The problem with the Ubuntu container is it’s running the command called bash. Now, you might be familiar with bash, the shell. It’s one of the shells available on Linux environments. The problem with bash is if it’s not connected to a terminal, bash assumes it’s just going to be running a script. And if there’s no script there, it just immediately exits.
Therefore, we could see that in the above snapshot, container did started with the ‘Ubuntu’ image, but it immediately exited.
Question:- Can I interact with our Docker container ? If possible, can you show the same ?
docker container run -it ubuntu
Above one is the interactive command. The “-i” means interactive & “-t”means connects the container to the terminal. But just think of it as being where running this container interactively and results of it is, You can see that that it’s dropping me onto a command line.
Therefore, we could see that in the above snapshot, container did started with the ‘Ubuntu’ image and even we are now inside this container.
Question:- I want to install GIT inside the above Docker-container that we have spawned. Pl show the same.
apt-get update && apt-get install git
Question:- Let’s now exit this container and observe :
Note that, as soon as we do an exit here, it means that bash command has now exited. We can also observe that, our Docker-container exited 11 seconds ago.
Question:- Each time, when we start a Container in a fresh way, Is it the same container which is started ?
Answer: No, each time, when we start a container in a fresh way, we are trigger-ring the fresh container. Observe from the below snapshot that, because we started the container 2 times so far, there exists 2 containers (each having different container-id. We can observe all (active + dead) containers using this command :-
docker container ls -a
Question:- How do I re-start the older container ?
docker container start 98ff2ff01546
Question:- How do I see the logs of the particular container ?
docker container logs 98ff2ff01546
Note that, we can also perform tailing on the logs of the particular container too.
docker container logs -f 98ff2ff01546
Question:- How do I peep-inside this container ?
docker container exec -it <container_id> bash
So, we are now, inside a bash shell inside that container.
Question:- How do I install JDK inside this container ?
Step #1.) Let’s first search (inside our container), what all variants of JDK are available :-
apt-cache search jdk
Step #2.) Next, let’s install any good version of JDK within our container :-
apt-get update && apt-get install -y openjdk-8-jdk
Step #3.) Next, let’s verify whether the JDK got installed successfully or not :-
javac -version
Let’s exit from our container now and see, whether our container is still active. Note that, we have yet not stopped / removed it. Just that, we have exited from the container.
Question :- Now that, we have installed “git” & “jdk” software on top of the base image of “Ubuntu”, Is there a way, we can preserve those changes ?
Answer:-
- The changes we make, if any, in this container are going to be transient when we stop and remove that container. Those changes would be gone.
- But actually, you can take a snapshot of a running container i.e. we’ll take an image from that running container. Below is the command to form the brand new image from the enhanced container.
docker container commit -a “Ubuntu + JDK + Git image” 98 ubuJdkGitAdityaImage
Note that, 98 is the container-id from which we are forming our new image.
Question :- Let’s now remove our original container and start a fresh container from our newly formed image ?
Step #1.) Let’s first stop our original container :-
docker container stop 98
Step #2.) Let’s see that, this container (that we recently exited) exists in the list or not :-
docker container ls -a
Step #3.) Let’s now go ahead and remove the containers completely from our history :-
docker container rm <container_id>
Step #4.) Let’s now observe, which all containers we have right now (post we remove 4 containers from previous command) :-
docker container ls -a
Step #5.) Let’s now see, what all images we have with us :-
docker images
Note that, we have this image, which we recently formed by our own in above part of the blog.
Step #6.) Let’s now launch a fresh container from the image :-
docker container run -it ubu-jdk-git-aditya-image
Please note below crucial points :-
- We had ran the container with “-i” option which means interactive mode.
- We had ran the container with “-t” option which means, we shall connect to the container’s terminal as well.
- In the fresh container that we just launched, observe that both GIT & JDK are already installed, as we did the same in it’s previous container from which we formed this image.
Step #7.) Let’s now exit from our container and observe whether this container really shows up in the list anymore :-
docker container ls -a
Step #8.) Let’s now re-start our container again :-
docker container start <container_id>
Step #9.) Let’s now connect to our afore-started container. We shall log inside a bash shell inside this freshly launched container. :-
docker container exec -it <container_id> bash
That’s all in this section. If you liked reading this blog, kindly do press on clap button multiple times, to indicate your appreciation. We would see you in next series.
References :-
- https://adityagoel123.medium.com/sneak-view-into-docker-for-devs-part-2-2884dc04fae4
- https://adityagoel123.medium.com/sneak-view-into-docker-for-java-devs-part-1-b0388ecd5974
- https://adityagoel123.medium.com/sneak-view-into-docker-for-web-devs-part-2-eac68e3226
- https://adityagoel123.medium.com/sneak-view-into-docker-for-web-devs-45b4d1aff63
- https://stackoverflow.com/questions/42218237/tomcat-java-lang-illegalargumentexception-invalid-character-found-in-method-na