Ravindra BagaleCourses & study guides मराठी

Chapter 47: Docker Architecture, Installation on Linux, Windows and Mac, and Docker Desktop Alternatives

47.1 Why Docker: works on my machine, devs vs ops

Chala mitrano! Today we start Docker. Do not worry, there is only one idea today: keep the app and everything it needs in one box. It is very easy. After every new word we do a small example, and you type every example yourself.

What you will learn in this lesson

  1. Why the same app works on one computer and fails on another.
  2. What an environment, an image and a container are.
  3. How to run your first container, list it, open it in a browser and remove it.
  4. How Docker fixes the "works on my machine" problem, with real company examples.

1. Start from something you do every day

Open the Swiggy app. Tap a restaurant. The menu appears in one second.

Behind that menu is a small program on a server. A server is just a computer in a data centre that stays on all day and answers requests from phones.

A developer at Swiggy writes that menu program on her laptop. On her laptop it works. Then she gives it to the operations team. Operations (or "ops") are the people who run programs on servers.

On the server, the program crashes. The developer says: "It works on my machine!" The ops engineer says: "It does not work on my server!" Both are telling the truth. In this lesson we find out why, and we fix it with Docker, one small step at a time.

Developer laptopPython 3.12 - app worksCopy only the codethe setup stays behindServerPython 3.8 - app crashes
Picture 1: the code moved, but the setup did not

2. Why did it break? The environment

Step 1: Environment

Why: The app did not change. Something around the app changed.

What: The environment is everything a program needs around it to run: the language version (for example Python 3.12), the extra libraries it uses, and the settings. Think of it like a recipe: the same recipe fails if one kitchen has a different oven.

Example 1: Ask each computer for its Python version

Type this:

python3 --version

You will see:

Python 3.12.7   (on the laptop)
Python 3.8.10   (on the server)

What it means: Same command, two different answers. The two computers have different environments. That one difference is enough to break the app.

Example 2: Ask for the version of one library

Type this:

python3 -c "import flask; print(flask.__version__)"

You will see:

3.0.3                                      (on the laptop)
ModuleNotFoundError: No module named 'flask'   (on the server)

What it means: A library is extra code that your program borrows, like Flask for building web apps. The laptop has Flask 3.0.3. The server does not have Flask at all. This is the second way an environment can differ.

Example 3: See the operating system name

Type this:

cat /etc/os-release | grep PRETTY_NAME

You will see:

PRETTY_NAME="Ubuntu 24.04.1 LTS"        (on the laptop)
PRETTY_NAME="Amazon Linux 2023"         (on the server)

What it means: The operating system (OS) is the base software of the computer, like Ubuntu or Amazon Linux. Even the OS is different. Real companies like Infosys and TCS see this every week: the code is fine, the environment is not.

So the real problem is this: we send only the code, but the code also needs its environment. If we could send the code and its environment together, in one box, the problem would go away. That box is what Docker gives us.

Ravindra Bagale's Tip

Many students think Docker is a new programming language. It is not. Docker does not change your code. It only packs your code and its environment together. Remember this.

3. The idea: a container

Your appthe menu program+ its environmentPython 3.12, libraries, settings= one containerruns the same on every computer
Picture 2: app plus environment, packed together

Step 2: Docker Engine

Why: Before we make any box, we need the tool that makes and runs boxes.

What: Docker Engine is the program you install on a computer. It makes and runs containers. You talk to it by typing commands that start with the word docker.

Example 4: Check that Docker is installed

Type this:

docker --version

You will see:

Docker version 27.3.1, build ce12230

What it means: Docker is installed and ready. If you see "command not found", install Docker first (lesson 47.5).

Example 5: Check that the engine is running

Type this:

docker version --format '{{.Server.Version}}'

You will see:

27.3.1

What it means: This asks the running engine for its own version. If you get a number, the engine is awake and listening. If you see "Cannot connect to the Docker daemon", start it with sudo systemctl start docker.

Example 6: Ask Docker for a short summary

Type this:

docker info --format 'Containers: {{.Containers}}  Images: {{.Images}}'

You will see:

Containers: 0  Images: 0

What it means: A fresh install has zero containers and zero images. Watch these numbers grow as we go through the lesson.

Step 3: Container

Why: This is the box from Picture 2. Let us run one and see it with our own eyes.

What: A container is a running app that carries its own environment. It is a small, separate space on your computer. What happens inside it does not disturb the rest of your computer.

Example 7: Run your very first container

Type this:

docker run hello-world

You will see:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.

What it means: docker run means "start a container". Docker started a tiny container, it printed a message, and it stopped. Notice the line "Pulling": Docker downloaded something first. That something is the image, which we meet in the next section.

Example 8: Run a container that says one line

Type this:

docker run alpine echo "Namaste from a container"

You will see:

Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
Namaste from a container

What it means: alpine is a very small Linux. After the image name we can give a command, here echo, which prints text. The command ran inside the container, printed the line, and the container stopped.

Example 9: Prove the container has its own space

Type this:

docker run alpine ls /
ls /

You will see:

bin  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
bin  boot  dev  etc  home  lib  ... snap  srv  sys  tmp  usr  var   (your computer)

What it means: The first list is the inside of the container. The second list is your own computer. They are different. The container sees its own files, not yours. That is what "separate space" means.

4. Where does a container come from? The image

Imagepacked box, stored on diskdocker runopen the box and start itContainerthe app is now running
Picture 3: image first, then container

Step 4: Image

Why: In Step 3, Docker "pulled" something before it ran. We need to know what that was.

What: An image is the packed box: the app plus its environment, saved as a file, not running. A container is that box opened and running. Think of a tiffin box: the packed tiffin is the image, and lunch on the table is the container. One tiffin recipe can feed many people, so one image can start many containers.

Example 10: List the images on your computer

Type this:

docker images

You will see:

REPOSITORY    TAG      IMAGE ID       SIZE
alpine        latest   91ef0af61f39   7.8MB
hello-world   latest   d2c94e258dcb   13.3kB

What it means: Two images are now saved. "REPOSITORY" is the image name. "TAG" is the version name; "latest" is the default when you do not give one. "SIZE" shows these are tiny.

Example 11: Start three containers from one image

Type this:

docker run alpine echo one
docker run alpine echo two
docker run alpine echo three

You will see:

one
two
three

What it means: No "Pulling" this time, because the image is already on disk. One image, three containers. Just like one tiffin recipe feeding three friends.

Example 12: Ask for a specific version with a tag

Type this:

docker run alpine:3.20 cat /etc/alpine-release
docker run alpine:3.19 cat /etc/alpine-release

You will see:

3.20.3
3.19.4

What it means: The part after the colon is the tag. Two tags give two different versions, side by side on the same computer, with no clash. Keep this idea in mind; it is the heart of the Swiggy fix.

Step 5: Docker Hub (where images come from)

Why: Where did Docker download the image from?

What: Docker Hub is a big online store of free, ready images. Docker downloads from it by default. Downloading an image is called "pulling". Companies also run their own private stores, called registries, like Amazon ECR at Netflix or Google Artifact Registry at Spotify.

Example 13: Pull Python without installing Python

Type this:

docker pull python:3.12-slim

You will see:

3.12-slim: Pulling from library/python
Status: Downloaded newer image for python:3.12-slim

What it means: Now you have an image with Python 3.12 inside. You did not install Python on your computer. It lives only inside the image. "slim" is a smaller version of the image.

Example 14: Pull a web server image

Type this:

docker pull nginx:1.27

You will see:

1.27: Pulling from library/nginx
Status: Downloaded newer image for nginx:1.27

What it means: nginx is a popular web server program. Companies like Zomato and Flipkart use it in front of their apps. Now it is on your disk, ready to run.

Example 15: Pull the same image again

Type this:

docker pull nginx:1.27

You will see:

1.27: Pulling from library/nginx
Status: Image is up to date for nginx:1.27

What it means: Docker checks first and downloads nothing, because you already have it. Pulling is safe to repeat.

5. Look at your containers

docker runcontainer startsRunningdocker ps shows itExiteddocker ps -a shows itdocker rmcontainer is gone
Picture 4: the life of a container

Step 6: docker ps

Why: After you start containers, you need a way to see them.

What: docker ps lists running containers. Adding -a (short for "all") also lists stopped ones.

Example 16: List running containers

Type this:

docker ps

You will see:

CONTAINER ID   IMAGE   COMMAND   STATUS   NAMES

What it means: Only the header line. Nothing is running now, because hello-world and the alpine containers finished their job and stopped.

Example 17: List all containers, stopped ones too

Type this:

docker ps -a

You will see:

CONTAINER ID   IMAGE         STATUS                     NAMES
7c1d0e2f3a45   alpine        Exited (0) 1 minute ago    happy_hopper
4f1c2a9b7e10   hello-world   Exited (0) 2 minutes ago   eager_lamport

What it means: Stopped containers are still on disk. "Exited (0)" means it finished with no error. Docker gave each a random name because we did not give one.

Example 18: Count all containers

Type this:

docker ps -a -q | wc -l

You will see:

6

What it means: -q (quiet) prints only the IDs, and wc -l counts lines. You ran six small containers in this lesson so far, and all six are still lying around.

Step 7: Removing a container

Why: Stopped containers stay on your computer until you remove them.

What: docker rm removes a container. The image stays, so you can start a new container from it any time.

Example 19: Remove one container by name

Type this:

docker rm eager_lamport

You will see:

eager_lamport

What it means: Use the name from your own output, because your random name will be different. Docker prints the name back to confirm.

Example 20: Remove all stopped containers at once

Type this:

docker container prune -f

You will see:

Deleted Containers:
7c1d0e2f3a45...
Total reclaimed space: 0B

What it means: prune cleans every stopped container. -f (force) skips the yes/no question. Running containers are never touched by this command.

Example 21: Run and remove automatically with --rm

Type this:

docker run --rm alpine echo "I clean up after myself"
docker ps -a

You will see:

I clean up after myself
CONTAINER ID   IMAGE   STATUS   NAMES

What it means: --rm deletes the container as soon as it stops. The list stays empty. Use --rm for quick one-time commands.

6. A container that keeps running: a website

Browseryou open localhost:8080Your computer, door 8080Docker forwards the requestContainer, door 80nginx sends the web page
Picture 5: port mapping, one door outside to one door inside

Step 8: Running in the background (-d) with a name

Why: hello-world stopped at once. A website must keep running.

What: -d means "run in the background" (detached) so your terminal stays free. --name web gives the container an easy name instead of a random one.

Example 22: Start nginx in the background

Type this:

docker run -d --name web nginx:1.27

You will see:

9a8b7c6d5e4f3a2b1c0d...

What it means: Docker prints the long container ID and gives your prompt back. The website is running quietly in the background.

Example 23: See it running

Type this:

docker ps

You will see:

CONTAINER ID   IMAGE        STATUS         PORTS    NAMES
9a8b7c6d5e4f   nginx:1.27   Up 5 seconds   80/tcp   web

What it means: "Up" means it is still running. "80/tcp" is its door, called a port. A port is a numbered door on a computer where a program listens. This door is inside the container, so your browser cannot reach it yet.

Example 24: Stop and start it again

Type this:

docker stop web
docker ps -a --filter name=web
docker start web

You will see:

web
CONTAINER ID   IMAGE        STATUS                     NAMES
9a8b7c6d5e4f   nginx:1.27   Exited (0) 2 seconds ago   web
web

What it means: docker stop stops it but keeps it. docker start starts the same container again. Using the name web is much easier than typing the ID.

Step 9: Port mapping (-p)

Why: We want to open the website from our own browser.

What: -p 8080:80 joins door 8080 on your computer to door 80 inside the container. Read it as "outside:inside".

Example 25: Replace the container with one that has a door

Type this:

docker rm -f web
docker run -d --name web -p 8080:80 nginx:1.27
curl -s localhost:8080 | grep title

You will see:

web
3e4f5a6b7c8d...
<title>Welcome to nginx!</title>

What it means: docker rm -f stops and removes the old container in one go. The new one has the door joined. curl asks for the web page, just like a browser does. You can also open http://localhost:8080 in your browser.

Example 26: Two websites side by side

Type this:

docker run -d --name web2 -p 8081:80 nginx:1.27
docker ps --format 'table {{.Names}}\t{{.Ports}}'

You will see:

NAMES   PORTS
web2    0.0.0.0:8081->80/tcp
web     0.0.0.0:8080->80/tcp

What it means: Both containers use door 80 inside, but different doors outside. This is how one server at Paytm can run many copies of an app.

Example 27: What happens if the outside door is busy

Type this:

docker run -d --name web3 -p 8080:80 nginx:1.27

You will see:

docker: Error response from daemon: ... Bind for 0.0.0.0:8080 failed: port is already allocated.

What it means: Door 8080 already belongs to web. Pick a free number such as 8082. Then clean up with docker rm -f web web2 web3.

7. Now fix the Swiggy problem

One image: python:3.12-slimapp + Python 3.12 packedLaptop runs the imageworksServer runs the same imageworks too
Picture 6: ship the image, not only the code

Step 10: Same image, same result

Why: This is why we learned everything above.

What: We ask containers for their Python version. Each one uses the Python inside its own image, not the Python on your computer.

Example 28: Two Python versions on one computer

Type this:

docker run --rm python:3.12-slim python --version
docker run --rm python:3.8-slim python --version

You will see:

Python 3.12.7
Python 3.8.20

What it means: The two images give two different versions on the same computer. The computer's own Python does not matter.

Example 29: Run the Swiggy-style code that broke

Type this:

printf 'import sys\nmatch sys.argv[1]:\n    case "menu":\n        print("Menu OK on Python", sys.version.split()[0])\n' > app.py
docker run --rm -v "$PWD":/app -w /app python:3.8-slim python app.py menu
docker run --rm -v "$PWD":/app -w /app python:3.12-slim python app.py menu

You will see:

  File "/app/app.py", line 2
    match sys.argv[1]:
          ^
SyntaxError: invalid syntax
Menu OK on Python 3.12.7

What it means: printf writes a tiny app into app.py. match only exists in Python 3.10 and newer. -v "$PWD":/app shares your folder with the container, and -w /app makes it the working folder. On 3.8 it fails, exactly like the server. On 3.12 it works. We just reproduced the bug and the fix on one laptop.

Example 30: The same image on another machine

Type this:

ssh ec2-user@test-server 'docker run --rm python:3.12-slim python --version'

You will see:

Python 3.12.7

What it means: Any server with Docker gives the same answer from the same image. So if Swiggy ships the app inside the 3.12 image, every server runs Python 3.12. In chapter 48 you will pack your own app into your own image.

8. The same idea at real companies

Step 11: Many languages, nothing installed

Why: Real teams use many languages. Installing all of them on every server is slow and risky.

What: Each language has an official image. You run the language straight from the image, so the server stays clean.

Example 31: Node.js, the language behind many web apps

Type this:

docker run --rm node:22-slim node --version

You will see:

v22.11.0

What it means: Zomato and Uber use Node.js for many services. You got Node.js without installing it.

Example 32: Java, used by banks and by Netflix

Type this:

docker run --rm eclipse-temurin:21-jre java -version

You will see:

openjdk version "21.0.5" 2024-10-15 LTS

What it means: Java services at HDFC Bank or Netflix run in images like this, so every server runs the exact same Java.

Example 33: A database for testing

Type this:

docker run -d --name db -e POSTGRES_PASSWORD=example postgres:16
docker exec db psql -U postgres -c 'select version();' | head -3
docker rm -f db

You will see:

...
 PostgreSQL 16.4 on x86_64-pc-linux-gnu ...
db

What it means: -e passes a setting into the container; example is a practice value, never a real password. docker exec runs a command inside a running container. A full database in seconds, removed in one command.

Ravindra Bagale's Tip

A common mistake is to think an image and a container are the same. An image is a packed tiffin; a container is the opened tiffin. docker images shows the tiffins, docker ps shows running containers. Pay attention!

Check yourself

Q1. The app works on the laptop and fails on the server. What is different?

The environment, for example the Python version or a missing library.

Q2. Which is running: the image or the container?

The container. The image is the packed box on disk.

Q3. In -p 8080:80, which number is on your computer?

8080 (outside:inside).

Q4. Which command shows stopped containers too?

docker ps -a

Q5. What does --rm do?

It removes the container automatically when it stops.

Q6. Why did docker pull nginx:1.27 download nothing the second time?

The image was already on disk, so Docker said it is up to date.

Friends, today we learned one thing: send the environment along with the code, in one image. Laptop or server, the result is the same. Did you understand? Let us try it once more. If not, look at Picture 3 again and type the commands from Step 1 to Step 11 yourself. Next: the difference between a virtual machine and a container.

Lab: try at home

  1. Run docker run -d --name myweb -p 9090:80 nginx:1.27.
  2. Open http://localhost:9090 in your browser. You should see "Welcome to nginx!".
  3. Run docker ps and find the PORTS column. Explain it in one sentence.
  4. Run docker run --rm node:22-slim node --version. You get Node.js without installing it.
  5. Run docker run --rm python:3.8-slim python --version and docker run --rm python:3.12-slim python --version. Write both answers down.
  6. Clean up: docker rm -f myweb, then docker container prune -f, then check with docker ps -a.

Recap

  • Same code can fail on two computers because their environments differ.
  • An image is the packed box: app plus environment.
  • A container is that image, running.
  • docker run starts, docker ps lists, docker stop and docker start pause and resume, docker rm removes.
  • -p outside:inside opens a container to your browser.
  • Ship the image, not only the code, and every server gives the same result.

Ravi Sir's Cards for this lesson

मराठी cards