Docker for Beginners (Windows)

What is Docker

Docker is a platform that allows us to package and run applications inside lightweight, isolated environments called containers. These containers include all the necessary dependencies and code needed to run our app consistently across different machines. Unlike traditional virtual machines, Docker containers share the same host operating system, making them efficient and portable. Docker simplifies version control, dependency management, and ensures consistent environments for development and production. It’s a powerful tool for streamlining software deployment and scaling. 🚀


Before

Image description

After

  1. Own isolated environment and own operating system which is linux based.

  2. Packed with all configuration

  3. One command to install the app

Image description

Application deployment

  1. So before docker , the configuration of the server needed

  2. There might dependencies conflict

  3. Misunderstandings

  4. Text doc for deployment

so after the containers,

  1. No environmental configuration on the server - except docker runtime

  2. Developers and Operations works together to the package the application in a container

What is a container

  • The container is a layer of images.

  • Mostly linux base image, because small in size[ alpine: 3.10]

  • And the application image is on top.

Lets install Postgres:9.6

  1. 1st go to DockerHub

  2. Search postgres

Image description

3 . Choose your desired version, i choose 9.6

Image description

4 . For windows, open wsl and run docker run postgres:9.6

Image description

Difference between Image and Container

  1. Image is an actual package or software that we want to run. It can be moved around

  2. Actually when we start the application is called container. And when we run the image, then it first bring to a container and then we run it and called container

Difference between Docker and Virtual machine

  1. Docker image is much smaller like couple of megabytes and vm might be couple of gigabytes

  2. Docker container start and runs faster but the vm is much slower

  3. If we want to run some linux based application on windows then it will not run, because the the OS kernel is not same. Thats why we need to use the Docker tool box

Basic Docker commands

  1. docker pull

  2. docker run

  3. docker start

  4. docker stop

  5. docker ps

  6. dokcer exec-it

  7. docker logs

Installing redis image

  1. Just go to docker hub

  2. Search redis

Image description

3 . open wsl , run command docker pull redis

Image description

4 . Now we have to put the redis image to a container to run it. For that just give the command, docker run redis

  1. To check the running images, open a new terminal and give, docker ps

  2. To stop the running image give ctrl + c

  3. docker run, command runs new container when we use it.

  4. Here are some key differences between the two commands: Attached vs Detached Mode: The main difference is that docker run attaches to the container, while docker run -d runs the container in detached mode.

Output: With docker run, you will see the output of the container in your terminal. With docker run -d, you will not see the output. Container Management: With docker run, you can manage the container directly from your terminal. With docker run -d, you will need to use other commands like docker ps and docker stop to manage the container.

In summary, docker run is used to start a container and attach to it, while docker run -d is used to start a container in detached mode, allowing it to run in the background.

Attached mode

Image description

Here the container is attached with the terminal

Detached mode

Image description

9 . Now in detached mode, to stop the container for some reason we can use, docker stop <id>

Image description

10 . To start again use , docker start <id>

Image description

11 . Suppose we stops the container for today and came back tomorrow and want to start from where left, to do that we can use, docker ps -a which will show all the running and not running container logs

12 . Now if want to run 2 redis of different versions, we have to use docker run redis:version , here the version is- which version image we want to run in our container. docker run pulls image and runs the container. So the docker run does two command in one, one is docker pull and the other one is docker run

Image description

Image description

Here we can see, both redis versions are running on port: 6379/tcp, which is also the container port number. But the problem is in tcp we can not use single port for multiple application in our localhost . To solve this issue we have to bind port.

13 . To bind the port at first we have to stop all the running redis images.

Image description

Then run,

docker run -p6000:6379 -d redis for 1st one,

Image description

for the second one we will run it on port 6001 same way but remember 6379 is the container port.

Image description

We can see 2 different redis application runnig on 6001, 6000.

##docker log & docker exec -it

To check why one container is not working properly , using the docker log

  1. docker logs <id>

  2. or docker logs <name>

Image description

but it is difficult to remember the container name. To solve this problem we can name the container as we like.

3 . So we have two container currently running,

Image description

  • at first we have to stop one using, docker stop <id>

  • Now give the command , docker run -d -p6001:6379 --name redis-older redis:7.0

Image description

  • then we can use docker logs by the given name

docker logs redis-older

Docker exec -it

  1. We can easily open the terminal of the current container using, docker exec -it

  2. We have container named redis-old

  3. now give, docker exec -it redis-old /bin/bash

note: we can use the container id also instead of name(redis-old)

  1. Then we went to home directory and run env command

  2. To exit we simply give exit

Image description

Developing with containers

  1. Install express, mongo-express by,
  • docker pull mongo

  • docker pull mong-express

We are going to create a new network

  1. To create a new network, give: docker network create mongo-network

  2. to check the network list: docker network ls

Image description

Run mongo containers

  1. The default container port for mongo is 27017

docker run -d -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ --name mongodb \ --net mongo-network \ mongo

id: 74bd46402e9cebdf13c2265a01b072807dd7d97bb83ae569193e35c191f67f60

Image description

3 . Same way run the mongo-express,

  1. docker run -d -p 8081:8081 \ -e ME_CONFIG_MONGODB_ADMINUSERNAME=admin \ -e ME_CONFIG_MONGODB_ADMINPASSWORD=password \ -e ME_CONFIG_MONGODB_SERVER=mongodb \ --net mongo-network \ --name mongo-express \ mongo-express

id: 6847ec9032c3673c6c61fc0f89e1b2baa5cbb44bea27eeedf0d67a1e384ec109

Image description

4 . Now we can easily check , if mongo-express is connected or not by, docker logs <id>

Image description

5 . Now go to browser and search, localhost:8081

and give username: admin, password: pass

Image description

And you will see the home page,

Image description


Docker Compose

Previously we use run commands to start our containers and created a network to communicate between them. But what if we need to run 10 containers at a time and create a network to communicate them, it will be very difficult to run 10 commands for each containers. To solve this issue we can use Docker Compose File , which will contain all the commands in a structured way.

Image description

1 . Version: 3 // version of docker compose 2 . Services: // here all the container names goes 3 . mongodb: // container name 4 . image: mongo // which image we are using here mongo 5 . port: -27017:27017 // this is the tcp port number host:container 6 . environment: -MONGO_INITDB_ROOT_USERNAME=admin MONGO_INITDB_ROOT_PASSWORD=password // environment variables

7 . mongo-express: // new container name 8 . image: mongo-express // image 9 . ports: -8081:8081 // port number 10. environment: .... // environment variables

But there is one thing is missing that is Docker Network, Actually in docker compose file we don't need that, docker compose itself takes care of creating a common network.

Let's create a docker compose file

In docker compose file(yaml file) the indentation is important. We have a demo project where we have the docker compose file,

Image description

version: '3'
services:
  mongodb:
    image: mongo
    ports:
     - 27017:27017
    environment:
     - MONGO_INITDB_ROOT_USERNAME=admin
     - MONGO_INITDB_ROOT_PASSWORD=password
  mongo-express:
    image: mongo-express
    ports:
     - 8081:8081
    environment:
     - ME_CONFIG_MONGODB_ADMINUSERNAME=admin
     - ME_CONFIG_MONGODB_ADMINPASSWORD=password
     - ME_CONFIG_MONGODB_SERVER=mongodb

save it as, mongo.yaml

  • Now the question is how to run the compose file !!.

  • At first we go to the location where we save the compose file using the terminal.

Image description

  • The docker compose is also installed with docker is installed. Its a package

Image description

now give, docker-compose -f mongo.yaml up Here, the command -f means the mode of the document is file

Image description

Here we can see new network has been created and two new containers also.

Image description

  • Previously to stop the containers we have to use docker stop, but in docker compose we can use

docker-compose -f mongo.yaml down

And it will shutdown all the container in the compose file, and also the network that had been created by docker compose.

Image description

after shutdown,

Image description

Image description

NOTE: The command is used for downing the compose file is actually a container restart and we will lost every data that we worked in previous container.


Dockerfile - Building our own Docker Image

Image description

1 . FROM: node // which gives us the installed node 2 . ENV: // which are the environment variable 3 . RUN : // executes any linux commands , here the directory will be created using mkdir 4 . COPY: // It executes on the HOST machines 5 . CMD: // entry point command

  • To create our own image we need two thigs, 1. name, 2. Tag

  • At first go to the folder that contains Dockerfile, run the command-> docker build -t my-app:1.0 .

Image description

Dockerfile:

FROM node:22.3-alpine3.19

ENV MONGO_DB_USERNAME=admin \
    MONGO_DB_PWD=password

RUN mkdir -p /home/app

COPY ./app /home/app

# set default dir so that next commands executes in /home/app dir
WORKDIR /home/app

# will execute npm install in /home/app because of WORKDIR
RUN npm install

# no need for /home/app/server.js because of WORKDIR
CMD ["node", "server.js"]

To check, give docker images,

Image description

  • We can run the image using, docker run my-app:1.0 and see the logs, docker logs <id>

  • to open it exec mode,

Image description

Privet Docker Registry

  1. Create and account on aws.amazon.com

  2. Serach ECR service

  3. Create a repository

  4. Named the repo my-app

Image description

5 . Now we are going to push the docker image that we created.

Image description

6 . At first we need to create an account on aws.amazon.com.

7 . Install AWS CLI, CLI installer .

Image description

verify installation using, aws --version

8 . Now we need to do aws configure, before that we need to create a IAM account.

Image description

From the user we have to create a user and click on the user and create an access key,

Image description

Image description

Now we can configure the aws cli using , aws configure and put the access key id there.

  1. Now we are going to create an ECR repository which is a private registry,
  • In services search ECR and go to private portion and click on create repository

Image description

Now , give name to your repo, i gave my-app and keep the other things as it is,

Image description

10 . Now Click on the created repo , my-app,

Image description

Then view push command,

Image description

Image description

  1. Copy The first command and paste it to powershell,

if you get this error,

Image description

then, go to IAM user,

Image description

  • Them Add permission

Image description

Create Inline policy

Image description

  • Select JSON,

Image description

  • And remove all code and add this,
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ECRLogin",
      "Effect": "Allow",
      "Action": "ecr:GetAuthorizationToken",
      "Resource": "*"
    }
  ]
}

Now the error must be solved. And give this command,,

Image description

it will show you,

Image description

LOGIN Successful

Now we will come back later and we see the


Image Naming in Docker Registry

Image description

Normally in docker hub, we have the short name of the docker image but in aws ECR we have write the full mode.

Image description

Image description

Now we are going to use the 4th command but we will the latest with 1.0.

[Some images are taken from Tech with nanas YT channel]

1
Subscribe to my newsletter

Read articles from Tahzib Mahmud Rifat directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tahzib Mahmud Rifat
Tahzib Mahmud Rifat

Undergrad Student , interested in Ai, robotics , Internet of Things. Love to contribute in opensource projects