Sunday, September 4, 2022

Docker

 Why Docker

While creating an application stack with components like Ansible, Nodejs, MongoDB. We need to check the compatibility with the OS for each component and then check the libraries and dependencies between each other. The same is true when there is an upgrade required on any of the components. Compatibility matrix issue. Long setup time. Different Dev/ QA/ Perf / Prod environments and if the application stack would work identical in each setup.

Solution - Docker (Runs each component in different containers on a single VM).
Containerize application, Run each service in its own dependencies in separate containers.
 
Containers are completely isolated environments with their own process, network, services, mounts except they share the same OS.

Docker uses lxc containers.

Docker does not support Windows container on a Linux host. It needs a Windows host.

Containers vs Virtual Machines
1. Utilization is less for docker
2. Size required is less
3. Boot up time is less.
4. Containers have less isolation compared to the VMs.

It can be a mix of docker on the VMs.

Docker image is a template like we have in a VM which is used to create containers.

2 versions -
1. Community Edition - Free
2. Enterprise Edition - Certified and supported comes with image management, image security.

Community Edition is available on -
1. Linux
2. MAC
3. Windows
4. Cloud Platforms

Docker Install

curl -fsSL https://get.docker.com -o getdocker.sh
sudo sh get-docker.sh

Checking Docker version
docker version

Docker Hub

Start the Docker service and validate
systemctl start docker
systemctl status docker

Install a docker module and run
docker run docker/whalesay cowsay Hello-World

Docker Commands
List containers
docker ps

List all containers including stopped
docker ps -a

To stop docker container
docker stop <container ID> / <container name>

Remove a container completely
docker rm <container name>

To see list of images
docker images

Remove image
docker rmi <image name>
(You must stop any container if it is using this image)

Command to only download the image
docker pull nginx

Append a command
docker run ubuntu sleep 5
(This will install nginx and then keep it running for 5 sec before sleeping)

Execute a command on the container
docker exec distracted_mcclintock cat /etc/hosts

Run - attach and detach
docker run kodekloud/simple-webapp
(This will show the output in the screen without letting you to do anything further)

We can run a container in detached mode
docker run -d kodekloud/simple-webapp

To attach the container
docker attach <container ID>

Installing centos
docker run centos
docker run -it centos bash (This will log you in the centos container)

docker run -d centos sleep 20
docker ps

docker run -d centos sleep 2000
docker stop <container name>
docker ps
docker ps -a

Exited code (0) means they exited under normal conditions
Exited code (137) means it was stopped by the user.

Removing docker container
docker rm <container name> / <container ID>
docker ps -a
(This need to be done to reclaim disk space)
(Multiple container name / ID can be provided while removing containers)

busybox is a small image to do a quick test.

docker images
docker rmi busybox

(If there are any container using the image it need to be removed first before removing the docker image otherwise it will fail)

docker pull ubuntu
(This is to just pull the image and keep it to save the time for downloading during running the docker container)

docker run -d ubuntu sleep 100
docker ps
docker exec <container id> cat /etc/hosts

Docker run commands
docker run redis
docker run redis:4.0

Here :4.0 is the tag. 
If no tag is attached, then the tag used is "latest".

You can find all the available tags for a image from Docker hub

By default, the docker container does not listen to standard input. 
docker run kodekloud/simple-prompt-docker
Hello and Welcome!

docker run -i kodekloud/simple-prompt-docker
Mainak
Hello and Welcome Mainak!

docker run -it kodekloud/simple-prompt-docker
Welcome! Enter your name: Mainak
Hello and Welcome Mainak!

A terminal needs to be attached to get the input prompt. 

Port mapping
Underlying host where docker is installed docker host or docker engine. (192.168.1.5)
Let's say I have configured a webapp and it is running on port 5000.(http://0.0.0.0:5000)

Now how a user can access it. 
1. Users can use the IP of the docker container. 
172.17.0.2 - However, it is an internal IP and only can be accessed from the docker host.

2. For users outside of docker host,  they can use the IP of the docker host but for that a port mapping needs to be done between the container and docker host.

docker run -p 80:5000 kodekloud/simple-prompt-docker

Multiple instances of the application can be run on multiple ports.
docker run -p 8080:5000 kodekloud/simple-prompt-docker

However, using the same port on the docker host is not possible.
docker run -p 8080:5000 kodekloud/simple-prompt-docker
docker run -p 8080:5000 kodekloud/simple-prompt-docker

Docker - Volume mapping
/var/lib/mysql - Data volume (Docker container file-system)
Let's say we have a mysql container and we need to delete the container and re-build it then all data will be lost.

To avoid this, we can map a volume between docker container file-system and docker host file-system. 
docker run -v /opt/datadir:/var/lib/mysql mysql
Here /opt/datadir is the file-system on the docker host.

Inspect Container to check all container information
docker inspect <container id> / <container name>

Container Logs
docker logs <container id> / <container name>

docker run -d ubuntu sleep 1500
docker ps
docker attach <container id>
This cause hang and had to close the terminal
You need to open a separate terminal and stop the docker container
docker stop <container id> / <container name>

docker run timer
(This runs infinitely and prints date / time)
This runs in the attach mode.
docker run -d timer
docker ps
docker attach <container id> / <container name>
It works.

docker run jenkins/jenkins
Check the IP of the docker container from different terminal
docker ps -a
docker inspect <container id> | grep -i ip
Now check from the GUI of the docker host opening Mozilla
http://<container IP>:8080

Now try to access from the browser to the IP of the docker host
This will not open.

docker run -p 8080:8080 jenkins/jenkins
Now try to access from the browser and it works.

Provide the admin password and proceed with the default package installation. 
Create the admin user and finish installation.

Create a job -> TestJob -> Freestyle project -> Ok.

Come out of the docker container and it will stop. Browser refresh will no longer show jenkins.

If we re-run the jenkins installer, it creates a new container and takes back on the initial config page. 

mkdir my-jenkins-data
docker run -p 8080:8080 -v /root/my-jenkins-data:/var/jenkins_home -u root jenkins/jenkins
Complete jenkins config from the browser and create a job

Now exit from the container and create a new container.
Re-run the last run docker command to recreate jenkins container.

As the volume is mapped it will not ask for any configuration and once you login you will be able to see the pre-configured job which was created during the last container install. 

Creating custom docker images
Let's say to deploy a app written in flash python

1. OS-Ubuntu
2. Update opt repo
3. Install dependencies using opt
4. Install python dependencies using pip
5. Copy source code to /opt folder
6. Run the web server using flask command.

Create a file called Dockerfile

FROM Ubuntu
RUN apt-get update && apt-get -y install python
RUN pip install flask flask-mysql
COPY . /opt/source-code
ENTRYPOINT FLASK-APP=/opt/source-code/app.py flask run

docker build . -f Dockerfile -t mainak/my-custom-app

docker push mainak/my-custom-app

Anything on the left is an instruction and on the right are the arguments.

To see the space allocated to run the custom image and even each steps / layers
docker history mainak/my-custom-app

All layers in docker are cached, so even if it fails and rebuild done it starts from the layer it failed and thus improves the processing time.


docker run -it ubuntu bash
apt-get update

No comments: