Skip to main content

Command Palette

Search for a command to run...

Docker (Basic)

Updated
10 min readView as Markdown

Let say you have created an application and that application is working fine on your machine. But in Production, this application doesn’t works properly. You will see developer experience this a lot. As a devops engineer we say to developer that your application is not working and the developer says that it works on my machine. The reason could be due to Dependencies, Libraries and versions, Framework, OS Level Features, Microservices.

So we need a standardized way to package the application with dependencies and deploy it on any environment. Docker is a tool designed to make it easier to create, deploy and run the applications by using containers.

Docker packages an application with dependencies in virtual container so that it can run on any Linux server. Each container runs an isolated process with the user space and take up the less spaces as compared to regular VM. So it always works the same regardless of its environment.

In industry, we are getting ticket ID. In that ticket, we have to create a login functionality. Developer develops the code and push it into github. Developer tell DevOps engineer that can you please deploy this code. DevOps engineer will go in production environment, clone from github and they will tell to the developer that how we can run the given code? Developer tell you can read ReadMe file. In that file, we have mentioned the steps. You need to follow those steps to run the code. When DevOps engineer run the code by following those steps, they will get an error like Python not found, Java not found, version incompatibility. They will tell this issue to the developer. Then developer will tell that it is working on my machine, it is not working on client machine. We need to fix this issue.

So we require Containers. Container contains which version you will require, which OS you will require, which code you want. It is like a box. This container will run in any environment. To implement the container, we require Docker. All the things you need to package, manage the package. This thing is done by Docker.

Earlier we are using Virtual Machines like VMware, Virtual Box, HyperV. Consider you are using Linux kernel OS. This kernel communicate to the hardware like network ports, RAM, ROM. We can run any type of Linux distribution, Windows, MacOS through one layer called Hypervisor. Hypervisor creates one layer on any OS (which OS you will require to install). The working process will be started from OS installation > Hypervisor > Linux Kernel > Hardware. The major drawback is that we need to allocate the memory to the OS using Hypervisor.

The solution is Docker. Consider you are using Linux kernel OS. This kernel communicate to the hardware like network ports, RAM, ROM. Then instead of Hypervisor, we are using Docker Engine. At the top of DocIker engine we are using Containers. We will put the code, libraries, packages inside the containers. But the OS kernel is not been present in containers, only it’s image will be available. Then container will loads the kernel from the host (inside OS layer). You will not be facing resource allocation in containers because kernel already supports hardware.

Docker Engine will plays an important role. It contains 2 parts:-

  1. Docker CLI: Here we will enter the commands which is understand by dockerd. Then dockerd sends those command to containerd.

  2. Docker Daemon: It is a background process known as dockerd. dockerd will run the containerd internally. containerd is an open soruce tool. It will give a lot of tools so that you can create the containers using those tools. containerd is a project develop by CNCF (Cloud Native Computing Foundation). CNCF has many tools like Argo, Docker, Kubernetes. Geenerally we don’t the commands to run the containerd. Hence dockerd has been formed. It contains libraries, tools to create a box (container). containerd is a tool to create, manage and destroy the containers.

Mantras: Using Docker file, we will create Docker Image and using docker image, we will create a Docker Container.

How to use Docker on Windows:-

You need to use a tool called Docker Desktop which it internally runs kernel.

Before starting Docker, first get the latest update of Packages from sudo apt-get update and the install the Docker Engine using sudo apt-get install docker.io. The package docker.io will install dockerd, containerd as well as docker CLI. Then run systemctl status docker which means docker is running and docker engine is active. Docker Engine is also known as Docker Application Container Engine.

Check how many containers are running

ubuntu@ip-172-31-33-200:~$ docker ps

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied

My user doesn’t have access to request to dockerd. I’m running docker ds command through docker CLI. You need to run cat /etc/group and you will see there is a group called docker. We need to add user inside docker group so that they can able to access

ubuntu@ip-172-31-33-200:~$ sudo usermod -aG docker $USER

docker:x:113:ubuntu

Sometimes docker engine won’t registered this, we need to restart the machine using sudo reboot. Then run docker ps

If you want to see active and inactive container then run docker ps -a

Container needs to be created by image. Docker has an image of mysql

Syntax: docker run <image-name>:<version-number>

ubuntu@ip-172-31-33-200:~$ docker run mysql:5.7

It downloads the mysql image from Docker Hub

-e is an environment variable

ubuntu@ip-172-31-33-200:~$ docker run -e MYSQL_ROOT_PASSWORD=______ mysql:5.7

Container is created on your screen, not running on your background. Open a new terminal and then run docker ps

You can stop the container using docker stop <container-ID>

I want containers to be run on background (detached mode) and can do any other work

ubuntu@ip-172-31-33-200:~$ docker run -d -e MYSQL_ROOT_PASSWORD=______ mysql:5.7

How I can go into running container and access MySQL database by entering password?

exec - execute

it - Interactive terminal

ubuntu@ip-172-31-33-200:~$ docker exec -it 1268a3854379 bash

bash-4.2# → It is a terminal which is present inside container

bash-4.2# mysql -u root -p

Enter password:

mysql>

mysql> show databases;

How to write docker file for small Java application?

ubuntu@ip-172-31-33-200:~/docker-projetcs/java-app$ vim Hello.java

import java.utils.*;

public class Hello

{

public static void main(String[] args)

{

System.out.println("Hello Dosto");

Date currentDate = new Date();

System.out.println("today date is: "+currentDate);

}

}

Docker plz create an OS / environment / box in such a way that it will help to run java file.

a)OS - ubuntu b) jdk.

Note:- No require to mention this all the things

a)Docker tells I have a base image. In that base image, linux, openjdk will be already installed.

b)Code → Hello.java

c)javac Hello.java

d)java Hello

All the things will be mention inside box known as image. Run the box, which is known as container.

ubuntu@ip-172-31-33-200:~/docker-projetcs/java-app$ vim Dockerfile

Type “Get a base image with JDK installed” in google and go to Docker Hub link

UseCase: Get a base image with JDK installed

\Container build steps**

FROM :

FROM openjdk:11

Create a working directory to compile, run java app

WORKDIR /app

Copy code from local machine to docker container

COPY Hello.java .

Note:- . defines current working directory is /app

Compile the code

RUN javac Hello.java

#Container build steps

#Run the box

Run the java app

CMD ["java","Hello"]

Syntax: docker build -t [tag] <app-name>:version-name <path-to-docker-file>

Tagging a java app with latest version

Eg: docker build -t java-app:latest .

To make an image from file, use the command “docker build”

To make an container from image, use “docker run”

ubuntu@ip-172-31-33-200:~/docker-projetcs/java-app$ docker run java-app:latest Hello Output: Dosto

today date is: Mon Nov 11 06:55:33 UTC 2024

Now I am creating another app called as ‘Flask App’.

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app$ vim app.py

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app$ cat app.py

from flask import Flask

app = Flask(name)

@app.route('/')

def hello_world():

return 'Hey, welcome to DevOps Zero To Hero'

@app.route('/health')

def health():

return 'Server is up and running'

But in this code, there is no main function. Here you won’t take the code from bit and pieces. When developer push the code into Github, as a DevOps engineer you need to pull the code from repository as it is.

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app$ rm app.py

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ ls

README.md app.py requirements.txt run.py

Developer said that my code will run from ‘run.py’ file. Flask comes under Python framework. Create a file called Dockerfile

#Get a base image with Python 3.9

FROM python:3.9

WORKDIR /app

COPY . .

Developer said that you need to install flask in Python. Developer has written a file called requirements.txt where he had mentioned the version of flask. You need to install this file.

Install all the required dependencies. Pip is a python package installer

RUN pip install -r requirements.txt

python.py is used to run python file. Run the python app

CMD ["python","run.py"]

Note:- We have created the Dockerfile. app.py contains the code. run.py runs on port no 80 which means it runs on port no 80 inside the container. I need to access this port outside the container then you need to publish your port.

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ docker images

-p : publish, container_port:host_port

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ docker run -p 80:80 flask-app:latest

Traceback (most recent call last): File "/app/run.py", line 1, in from app import app File "/app/app.py", line 1, in from flask import Flask File "/usr/local/lib/python3.9/site-packages/flask/init.py", line 5, in from .app import Flask as Flask File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 30, in from werkzeug.urls import url_quote ImportError: cannot import name 'url_quote' from 'werkzeug.urls' (/usr/local/lib/python3.9/site-packages/werkzeug/urls.py)

If you are using latest Python version, please use latest flask

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ cat requirements.txt

flask==2.2.2u

Edit this code and remove the flask version and build the app.

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ cat requirements.txt

flask

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ docker build -t flask-app:latest .

Check whether python:3.9 is compatible with flask-3.0 version or not.

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ docker run -p 8080:80 flask-app:latest

Open the port no 8080 by going to your instance dashboard > Security > Security Group > Inbound > Click on Edit Inbound Rules > Add Rule, enter port no 8080 and select “Anywhere-IPV4, click on Save Rules

ubuntu@ip-172-31-33-200:~/docker-projetcs/flask-app/flask-app-ecs$ curl http://localhost:8080

The command ‘curl http://localhost:8080 send an HTTP request to the server which is running on local machine.

Output:- Hey, welcome to DevOps Zero To Heroubuntu

On an alternative way, you can enter <public-ip>:8080

We need all OS files, libraries, code into one folder inside out container for isolation, hence we require to create a work directory.

ubuntu@ip-172-31-33-200:~$ docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e8042d0d13ad flask-app:latest "python run.py" 9 minutes ago Up 9 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp boring_cray

ubuntu@ip-172-31-33-200:~$ docker exec -it e8042d0d13ad bash root@e8042d0d13ad:/app# ls

Dockerfile README.md pycache app.py requirements.txt run.py

These are the OS files

root@e8042d0d13ad:/# ls

app bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

Now we are crating a node app

ubuntu@ip-172-31-33-200:~/docker-projetcs/node-app/node-todo-cicd$ ls

DevSecOps Jenkinsfile README.md app.js docker-compose.yaml k8s kustomize package-lock.json package.json sonar-project.properties terraform test.js views

While seeing this file content, we can assume that we need a base image for Node js.

ubuntu@ip-172-31-33-200:~/docker-projetcs/node-app/node-todo-cicd$ cat README.md

node-todo-cicd

Run these commands:

sudo apt install nodejs

sudo apt install npm

npm install

node app.js

or Run by docker compose

test

Don’t put the latest version of node js while mentioning the base image. The libraries which were used in app.js file will might not compatible with latest node js version.

ubuntu@ip-172-31-33-200:~/docker-projetcs/node-app/node-todo-cicd$ cat package-lock.json

Using above json file or requirement file you can knew which version of node js would be compatible.

As a DevOps engineer you need to mention that your test needs to be passed. When you are doing same changes, check if your application won’t break. → test.js

Now write a docker file for node js

FROM node:14

WORKDIR /app

COPY . .

#Install the dependencies

RUN npm install

#All my test cases are passing

RUN npm run test

Note:- npm satnds for Node Package Manager. It is the default package manager for Node.js runtime environment.

Check the port no in app.js → 8000

EXPOSE 8000 → The container should listen the port no 8000 at runtime.

CMD ["node","app.js"]

ubuntu@ip-172-31-33-200:~/docker-projetcs/node-app/node-todo-cicd$ docker run -d node-app:latest

83abef55391ae51f91909d2f34049500a73e4a16e5bea36dc2a94f8638de87a8

ubuntu@ip-172-31-33-200:~/docker-projetcs/node-app/node-todo-cicd$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

83abef55391a node-app:latest "docker-entrypoint.s…" 24 seconds ago Up 23 seconds 8000/tcp gallant_liskov

Exposing the port of the container does not means it get bind to the host port. It is possible if we can connect 2 container but if we want to access at system level, it should be bound.

It maps system 8000 port with container 8000 port. Also open your port 8000 at Security Group under your server.

Enter url as <public-ip>:8000

18 views

More from this blog

Untitled Publication

36 posts