সহজ কথায়, ডকার হলো OS-level virtualization। এটি হাইপারভাইজরের মতো পুরো হার্ডওয়্যার সিমুলেট করে না, বরং হোস্ট অপারেটিং সিস্টেমের Kernel শেয়ার করে।
ডকারের আসল জাদুকর: ডকার মূলত লিনাক্স কার্নেলের দুটি প্রধান ফিচারের ওপর দাঁড়িয়ে:
ডকার ইমেজ বনাম কন্টেইনার:
ইমেজ হলো আপনার অ্যাপ্লিকেশনের “ব্লু-প্রিন্ট”।
docker build -t <image-name> . : আপনার Dockerfile থেকে একটি ইমেজ তৈরি (Build) করে। -t দিয়ে ইমেজের একটা নাম দেওয়া হয়।
docker images : আপনার কম্পিউটারে বর্তমানে কতগুলো ইমেজ ডাউনলোড করা বা তৈরি করা আছে তার লিস্ট দেখায়।
docker rmi <image-id> : অপ্রয়োজনীয় কোনো ইমেজ ডিলিট করার জন্য। (rmi = Remove Image)
docker pull <image-name> : Docker Hub থেকে কোনো ইমেজ ডাউনলোড করার জন্য (যেমন: docker pull postgres)।
docker run <image-name> : ইমেজ থেকে একটি নতুন কন্টেইনার তৈরি করে এবং সেটি চালু করে।
docker run -d -p 5000:5000 <image-name> :
-d (Detached mode): কন্টেইনার ব্যাকগ্রাউন্ডে চলবে।-p (Port mapping): হোস্টের ৫০০০ পোর্টের সাথে কন্টেইনারের ৫০০০ পোর্ট কানেক্ট করবে।-d (Detached mode): কন্টেইনার ব্যাকগ্রাউন্ডে চলবে।
-p (Port mapping): হোস্টের ৫০০০ পোর্টের সাথে কন্টেইনারের ৫০০০ পোর্ট কানেক্ট করবে।
docker ps : বর্তমানে কোন কোন কন্টেইনার চলছে তার লিস্ট দেখায়।
docker ps -a : সব কন্টেইনারের লিস্ট দেখায় (সেটা চলুক বা বন্ধ থাকুক)।
docker stop <container-id> : রানিং কোনো কন্টেইনারকে থামিয়ে দেয়।
docker start <container-id> : বন্ধ হয়ে থাকা (Exited) কোনো কন্টেইনারকে আবার চালু করে।
docker rm <container-id> : কোনো কন্টেইনার পার্মানেন্টলি ডিলিট করে দেয়।ডেভেলপমেন্টের সময় কন্টেইনারের ভেতর কী হচ্ছে তা দেখার জন্য এগুলো লাগে।
docker logs <container-id> : কন্টেইনারের কনসোলে কী কী আউটপুট বা এরর আসছে তা দেখার জন্য।
docker logs -f <container-id> : লাইভ লগ দেখার জন্য (যেমনটা আপনি টার্মিনালে দেখেন)।
docker exec -it <container-id> sh (বা bash) : কন্টেইনারের ভেতরে ঢোকার জন্য। অনেকটা SSH করার মতো। এর ভেতরে ঢুকে আপনি ফাইল চেক করতে পারেন।
docker inspect <container-id> : কন্টেইনারের IP address, মাউন্ট করা ভলিউমসহ সব টেকনিক্যাল ডিটেইলস দেখার জন্য।
ডকার অনেক সময় প্রচুর ডিস্ক স্পেস দখল করে ফেলে।
docker system prune : এক কমান্ডে সব বন্ধ থাকা কন্টেইনার, অব্যবহৃত নেটওয়ার্ক এবং ক্যাশ ডিলিট করে দেয়। (সাবধানে ব্যবহার করবেন!)
docker volume ls : আপনার সিস্টেমে কতগুলো ডকার ভলিউম (যেখানে ডাটা সেভ থাকে) আছে তা দেখার জন্য।
docker run -d -p 8080:80 --name my-nginx nginx
The -d flag runs in detached mode (background). -p 8080:80 maps port 8080 on your host to port 80 in the container. --name gives it a friendly name instead of a random one.
You should see a long container ID printed, and your terminal prompt returns immediately. The container runs in the background.
-d flag is crucial for long-running serviceshost:containerdocker ps
docker logs my-nginx
docker ps (without -a) shows only running containers. docker logs displays what the container has output to stdout/stderr.my-nginx listed as running (UP status) and nginx access logs when you view the logs.docker logs my-nginx again to see new log entriesdocker logs -f my-nginx to follow logs in real-time (like tail -f)docker stop my-nginx
docker ps -a
docker rm my-nginx
docker ps -a
docker stop gracefully stops a running container. docker rm removes a stopped container completely. Notice how the container disappears from the list after removal.stop, the container status changes to “Exited”. After rm, it’s completely gone from docker ps -a.docker rm -f my-nginx to force-remove a running containerdocker container prune to remove all stopped containers at oncedocker run -d -p 8081:80 --name my-apache httpd
docker ps
docker logs my-apache
docker stop my-apache
docker rm my-apache
This follows the full container lifecycle: run in background, check it’s running, view logs, stop it, and clean up. The httpd image is Apache web server.
You should be able to visit http://localhost:8081 and see Apache’s default page. Then successfully stop and remove the container.
--name for easier managementdocker images to see all the images you’ve downloadeddocker search nginx
docker search --filter stars=1000 nginx
The docker search command queries Docker Hub for images. The filter option helps you find popular, well-maintained images with many stars.
You’ll see a list of nginx-related images with columns for NAME, DESCRIPTION, STARS, OFFICIAL, and AUTOMATED.
docker pull nginx
This downloads the nginx image from Docker Hub. Without a tag, it defaults to ‘latest’. The image is stored locally and can be used to create containers.
You’ll see download progress bars for each layer. Output ends with something like ‘Status: Downloaded newer image for nginx:latest’.
docker pull nginx:1.25
docker pull nginx:alpine
docker images nginx
Tags specify versions or variants. Format is image:tag. Alpine variants are minimal Linux distributions, resulting in smaller images.
You’ll see three nginx images listed with different tags: latest, 1.25, and alpine. Notice the size differences.
Alpine images are typically 5-10x smaller than standard images
Use specific version tags (like 1.25) in production to ensure consistency
Check Docker Hub for available tags and their documentation
docker inspect nginx:latest
docker history nginx:latest
docker inspect shows JSON metadata including config, layers, and environment. docker history displays the build commands that created each layer.
You’ll see detailed JSON output from inspect, and a table of layers with their sizes from history.
docker inspect nginx:latest | grep -A 10 Env to see just environment variablesdocker images
docker images --format "table \t\t"
docker pull python:3.11
docker pull python:3.11-alpine
docker images python
Create your own tag (alias) for an image.
docker tag nginx:latest my-nginx:v1
docker images | grep nginx
repository:tag or registry/repository:tag for remote registriesdocker system df
docker system df -v
docker rmi python:3.11
docker images
docker image prune -a
docker rmi removes a specific image. docker image prune -a removes all unused images (not referenced by any container).docker container pruneApply what you’ve learned to work with a different image.
docker search redis
docker pull redis:7-alpine
docker inspect redis:7-alpine | grep -A 5 ExposedPorts
docker rmi redis:7-alpine
Learn about the different states a container can be in: created, running, paused, exited.
docker run -d --name demo-nginx nginx
docker ps
docker stop demo-nginx
docker ps -a
Containers transition through states: created → running → stopped (exited). The ps command shows running containers, while ps -a shows all containers regardless of state.
You’ll see the container appear in ‘docker ps’ with UP status, then after stopping it will show ‘Exited’ status in ‘docker ps -a’.
docker start demo-nginx
docker ps
docker restart demo-nginx
docker ps
docker start resumes a stopped container. docker restart stops and then starts a container in one command. Both preserve the container’s data.
The container returns to running state. Notice the container ID and name remain the same - it’s the same container, not a new one.
Temporarily freeze a container’s processes without stopping it.
docker pause demo-nginx
docker ps
docker unpause demo-nginx
docker ps
Pausing freezes all processes in the container using cgroups. The container remains in memory but consumes no CPU. Useful for temporarily halting resource-intensive containers.
When paused, the container status shows ‘Paused’. After unpause, it returns to ‘Up’ status and resumes immediately where it left off.
Run commands inside a live container without stopping it.
docker exec demo-nginx ls /usr/share/nginx/html
docker exec demo-nginx cat /etc/nginx/nginx.conf
docker exec -it demo-nginx bash
docker exec runs a new process inside a running container. The -it flags give you an interactive terminal. Type ‘exit’ to leave without stopping the container.
You’ll see directory contents, config file content, and then get an interactive shell inside the running container.
docker logs demo-nginx
docker logs --tail 20 demo-nginx
docker logs --since 5m demo-nginx
docker logs -f demo-nginx
Logs show everything written to stdout/stderr. Use –tail to limit lines, –since for time range, and -f to follow in real-time. Press Ctrl+C to stop following.
You’ll see nginx access and error logs. The -f option streams new log entries as they appear.
| Use grep to filter: docker logs demo-nginx | grep error |
docker run -d -p 3000:3000 ts-docker:v1
docker start --attach ts-docker-container
ইন্টারঅ্যাক্টিভ কাজ (Input/Output): যদি আপনার অ্যাপটি ইউজারের কাছ থেকে কোনো ইনপুট চায়, তবে –attach ছাড়া আপনি সেই ইনপুট দিতে পারবেন না। এটি আপনার টার্মিনালকে কন্টেইনারের সাথে সরাসরি পাইপের মতো জুড়ে দেয়।
কন্টেইনারের বর্তমান অবস্থা বোঝা: কখনও কখনও docker start দিলে মনে হয় কন্টেইনারটি চালু হয়েছে, কিন্তু আসলে সেটি ২ সেকেন্ড পরেই বন্ধ হয়ে যায়। –attach করলে আপনি দেখতে পাবেন কেন সেটি দ্রুত বন্ধ হয়ে যাচ্ছে (যেমন: কোনো ফাইল মিসিং বা কনফিগারেশন ভুল)।
docker inspect demo-nginx
docker inspect --format '' demo-nginx
docker inspect --format '' demo-nginx
docker inspect --format '' demo-nginx
Inspect returns detailed JSON about the container. Use –format with Go templates to extract specific fields like IP address, status, or volumes.
First command shows full JSON. Subsequent commands show just the requested field: status, IP address, and image name.
| Use jq for better JSON formatting: docker inspect demo-nginx | jq |
docker stats demo-nginx
docker stats --no-stream demo-nginx
Stats displays live resource consumption. Without –no-stream, it updates continuously. With it, shows a single snapshot. Press Ctrl+C to exit continuous mode.
You’ll see a table with CPU %, memory usage, network I/O, and block I/O updating in real-time.
echo '<h1>Hello from Docker!</h1>' > custom.html
docker cp custom.html demo-nginx:/usr/share/nginx/html/
docker exec demo-nginx cat /usr/share/nginx/html/custom.html
docker cp demo-nginx:/etc/nginx/nginx.conf ./nginx-backup.conf
The docker cp command copies files between host and container. Works with both running and stopped containers. Format: source → destination.
The HTML file is copied into the container and can be accessed. The config file is copied from container to your current directory.
docker rename demo-nginx my-webserver
docker ps
docker update --memory 512m my-webserver
docker inspect --format '' my-webserver
Rename changes a container’s name. Update modifies resource constraints like memory and CPU limits on running containers without restarting.
The container now appears with the new name. Memory limit is set to 512MB (shown in bytes in inspect output).
docker diff my-webserver
Shows filesystem changes: A (added), D (deleted), C (changed). Useful for understanding what a container has modified.
You’ll see files added or changed, including the custom.html you copied earlier.
docker run -d --name test-ubuntu ubuntu bash -c 'while true; do date; sleep 2; done'
docker attach test-ubuntu
Attach connects your terminal to the container’s main process. Press Ctrl+C to detach (this will stop the container unless you use Ctrl+P, Ctrl+Q).
You’ll see date output every 2 seconds. Use Ctrl+P then Ctrl+Q to detach without stopping, or Ctrl+C to stop the container.
docker stop my-webserver test-ubuntu
docker rm my-webserver test-ubuntu
docker ps -a
docker container prune
docker ps -a
Stop containers before removing them, or use ‘docker rm -f’ to force remove. Prune removes all stopped containers at once - useful for bulk cleanup.
Containers are removed from the system. Prune asks for confirmation and shows how much space was reclaimed.
মনে করুন, আপনার একটা স্মার্টফোন আছে (Container)। ফোনের ভেতরে আপনি কিছু ছবি তুললেন। এখন ফোনটা যদি পানিতে পড়ে নষ্ট হয়ে যায় বা হারিয়ে যায়, তবে আপনার সব ছবিও শেষ।
কিন্তু আপনি যদি ফোনের ভেতরে একটা মেমোরি কার্ড বা এসডি কার্ড (Volume) লাগান এবং সব ছবি সেখানে সেভ করেন, তাহলে ফোন হারিয়ে গেলেও আপনার ছবি হারাবে না। আপনি ওই এসডি কার্ডটা খুলে অন্য যেকোনো ফোনে লাগালেই সব ছবি ফেরত পাবেন।
ডকার ভলিউম ঠিক ওই এসডি কার্ডের মতো কাজ করে।
ভলিউম ছাড়া: কন্টেইনার ডিলিট = সব ডাটা ডিলিট। ❌
ভলিউম সহ: কন্টেইনার ডিলিট = ডাটা হার্ডড্রাইভে (ভলিউমে) সুরক্ষিত। ✅
চলুন আমরা একটা এসডি কার্ড (Volume) কিনি এবং সেটা কন্টেইনারে লাগাই।
docker volume create my_sd_card
(এই কমান্ড দিয়ে আপনি ডকারকে বললেন, "আমার জন্য একটা আলাদা স্টোরেজ বক্স বানাও যার নাম my_sd_card")
docker run -it --name phone1 -v my_sd_card:/app_data alpine sh
এই কমান্ডের মানে বুঝুন:
-v my_sd_card:/app_data: এর মানে হলো, আমার তৈরি করা my_sd_card ভলিউমটিকে কন্টেইনারের ভেতরের /app_data ফোল্ডারের সাথে কানেক্ট করো।
cd /app_data
echo "I have a plan" > file.txt
ls
ফাইলটি তৈরি হয়েছে। এবার exit লিখে কন্টেইনার থেকে বের হয়ে যান।
docker rm phone1
(আপনার কন্টেইনার এখন ভ্যানিশ!)
docker run -it --name phone2 -v my_sd_card:/some_other_folder alpine sh
এখন কন্টেইনারের ভেতরে গিয়ে দেখুন:
cat /some_other_folder/file.txt
আউটপুট আসবে: I have a plan
alpine :/app_data sh এর মানে কী?
কমান্ডটি ছিল: docker run -it -v my_sd_card:/app_data alpine shএখানে প্রত্যেকটি অংশের কাজ আলাদা:
alpine: এটি একটি অপারেটিং সিস্টেমের নাম (যেমন Windows বা Ubuntu)। এটি খুব ছোট এবং হালকা, তাই ডকার শেখার জন্য এটি সবাই ব্যবহার করে। ডকারকে আপনি বলছেন, “ভাই, আলপাইন (Alpine) ইমেজটা ব্যবহার করে একটা কন্টেইনার বানাও।”
-v my_sd_card:/app_data মানে হলো: “আমার তৈরি করা my_sd_card (এসডি কার্ড) বক্সটাকে কন্টেইনারের ভেতরের /app_data ফোল্ডারের সাথে আঠা দিয়ে লাগিয়ে দাও।”আপনি যখন docker volume create my_sd_card লিখেন, ডকার আপনার পিসির হার্ড ড্রাইভের একটি বিশেষ জায়গায় একটা ফোল্ডার তৈরি করে।
/var/lib/docker/volumes/my_sd_card/_datadocker volume inspect my_sd_card
"Mountpoint": "/var/lib/docker/volumes/my_sd_card/_data"
sudo ls /var/lib/docker/volumes/my_sd_card/_data
ডকার কন্টেইনারের ভেতর আপনি যা করবেন, কন্টেইনার ডিলিট করলে সব মুছে যাবে। এটা বাঁচানোর ২টা উপায় আছে:
উপায় ১ (Named Volume): ডকারকে বললেন, “তুমি তোমার নিজের মতো একটা স্টোরেজ বক্স বানাও আর সেখানে আমার ফাইল রাখো।” (এটা কোথায় থাকে সেটা ডকার ভালো জানে, আপনি সহজে খুঁজে পাবেন না)।
উপায় ২ (Bind Mount): আপনি ডকারকে বললেন, “বেশি পণ্ডিতি করো না, আমার পিসির এই learning ফোল্ডারটা ব্যবহার করো।” (এটা আপনার চোখের সামনে থাকে, আপনি VS Code দিয়ে ফাইল দেখতে ও এডিট করতে পারেন)।
docker run -d --name practice-redis redis:alpine
docker ps
docker exec practice-redis redis-cli PING
docker logs practice-redis
docker stats --no-stream practice-redis
docker pause practice-redis
docker unpause practice-redis
docker restart practice-redis
docker stop practice-redis
docker rm practice-redis
This workflow demonstrates the complete container lifecycle: create, verify, execute commands, check logs, monitor resources, pause/unpause, restart, and finally cleanup.
Each command succeeds. The redis-cli PING returns ‘PONG’. Stats show resource usage. The container is cleanly removed at the end.
docker exec practice-redis redis-cli SET mykey "Hello"docker exec practice-redis redis-cli GET mykeydocker run my-ubuntu:v1
docker run my-ubuntu:v1 curl --version
The first command runs the default CMD from the Dockerfile. The second overrides the CMD to verify curl is installed.
First command outputs ‘Hello from my custom image!’. Second shows curl version information, confirming the package was installed during build.
cat > Dockerfile << 'EOF'
# Base image
FROM node:18-alpine
# Set working directory
WORKDIR /app
# Copy files
COPY package.json .
# Run commands
RUN npm install
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Set environment variable
ENV NODE_ENV=production
# Default command
CMD ["node", "app.js"]
EOF
কেন alpine? এটি খুব গুরুত্বপূর্ণ। আলপাইন হলো লিনাক্সের সবথেকে হালকা ভার্সন। সাধারণ উবুন্টু ইমেজ ২০০এমবি হলে, আলপাইন মাত্র ৫এমবি। ইন্টারভিউতে বলবেন— “ইমেজ সাইজ ছোট রাখার জন্য আমি আলপাইন ব্যবহার করেছি।”
সুবিধা: এরপর আপনি যা কপি করবেন বা রান করবেন, সব এই /app ফোল্ডারের ভেতরেই হবে। পিসিতে cd /app করার মতো।
মাস্টার টিপস (Layer Caching): খেয়াল করুন, আপনি কিন্তু সব ফাইল একসাথে কপি করেননি, শুধু package.json করেছেন। কেন? কারণ ডকার প্রতিটি লাইনকে একটি Layer হিসেবে সেভ করে। যদি আপনার কোড চেঞ্জ হয় কিন্তু প্যাকেজ চেঞ্জ না হয়, তবে ডকার আগের লেয়ার থেকে npm install এর রেজাল্ট নিয়ে নেয়। এতে বিল্ড অনেক ফাস্ট হয়।
৪. RUN npm install কাজ: এটি ইমেজ বানানোর সময় চলে। এটি ইন্টারনেটে গিয়ে আপনার প্রজেক্টের সব ডিপেন্ডেন্সি (Libraries) ডাউনলোড করে node_modules ফোল্ডার বানায়।
৫. COPY . . কাজ: এবার আপনার পিসির বাকি সব কোড (app.js, ইমেজেস, সিএসএস) কন্টেইনারের ভেতরে কপি করে দেয়। এটি npm install এর নিচে রাখা হয় যেন কোড চেঞ্জ করলে বারবার সব ডাউনলোড করতে না হয়।
৬. EXPOSE 3000 কাজ: এটি শুধু একটি ডকুমেন্টেশন বা সিগন্যাল। এটি ডকারকে জানায় যে এই অ্যাপটি ৩০০০ পোর্টে কথা বলবে। (তবে এটি একা পোর্ট ওপেন করতে পারে না, রান করার সময় -p লাগে)।
৭. ENV NODE_ENV=production কাজ: কন্টেইনারের ভেতরে একটি পরিবেশ চলক (Environment Variable) সেট করে। অনেক ফ্রেমওয়ার্ক এই ভ্যারিয়েবল দেখে বুঝে নেয় যে এখন অ্যাপটি প্রোডাকশনে চলছে, তখন তারা বাড়তি লগ বন্ধ করে স্পিড বাড়িয়ে দেয়।
৮. CMD [“node”, “app.js”] কাজ: এটি কন্টেইনার চালু হওয়ার সময় শেষ কমান্ড হিসেবে চলে। এটি আপনার সার্ভারকে স্টার্ট করে।
মনে রাখবেন: RUN চলে ইমেজ বানানোর সময়, আর CMD চলে কন্টেইনার রান করার সময়।
FROM node:20-alpine
ARG NODE_ENV=development
ARG PORT=3000
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE ${PORT}
ENV NODE_ENV=${NODE_ENV}}
ENV PORT=${PORT}
CMD [ "node", "app.js" ]
ENV (Runtime): এটি কন্টেইনার চলার সময় কাজে লাগে। অ্যাপের ভেতরে কোড যখন রান করবে, তখন সে এই ভ্যালুগুলো দেখতে পাবে।
ARG NODE_ENV=development: এটি একটি ডিফল্ট মান। যদি আপনি বিল্ড করার সময় কিছু না বলেন, তবে সে development ধরে নেবে।
ENV NODE_ENV=${NODE_ENV}: এটি জাদুকরী লাইন! এখানে আপনি ARG এর মানটিকে ENV-এ ট্রান্সফার করছেন। কারণ আপনার নোড অ্যাপ (app.js) শুধু ENV পড়তে পারে, ARG নয়।
প্রথম বিল্ড (Dev Version):
docker build -t my-node-app:dev .
এখানে আপনি কোনো –build-arg দেননি।
ফলাফল: এই ইমেজের ভেতর পোর্ট হবে 3000 আর এনভায়রনমেন্ট হবে development।
docker build -t my-node-app:prod --build-arg NODE_ENV=production --build-arg PORT=8080 .
আমি ARG ব্যবহার করে একই Dockerfile দিয়ে ডাইনামিক ইমেজ বানাতে পারি। এতে কোড ডুপ্লিকেট হয় না (DRY - Don’t Repeat Yourself)