DEV Community

Ragib Hasan
Ragib Hasan Subscriber

Posted on

Dockerfile CMD Explained: Build-Time vs Runtime and How CMD Override Works

Dockerfile শেখার সময় FROM, RUN, WORKDIR, এবং COPY নিয়ে কাজ করার পর খুব স্বাভাবিকভাবেই একটি প্রশ্ন আসে:

Container start হলে application automatically কীভাবে run করবে?

আমরা যদি শুধু এই ধরনের Dockerfile লিখি—

FROM ubuntu:24.04

RUN apt update
RUN apt install -y golang

WORKDIR /app

COPY ./server.go ./server.go
Enter fullscreen mode Exit fullscreen mode

তাহলে image তৈরি হবে ঠিকই।

Go-ও install হবে।

server.go-ও image-এর মধ্যে চলে যাবে।

কিন্তু container start করলে কি আমাদের Go server automatically চালু হবে?

না।

আমাদের আবার container-এর ভিতরে ঢুকে manually লিখতে হবে:

go run server.go
Enter fullscreen mode Exit fullscreen mode

এটাই সেই জায়গা যেখানে Dockerfile-এর একটি অত্যন্ত গুরুত্বপূর্ণ instruction সামনে আসে:

CMD

CMD আমাদের image-এর default runtime command নির্ধারণ করে।

এই article-এ আমরা দেখব:

  • কেন container immediately exit করতে পারে
  • CMD কী
  • RUN এবং CMD-এর পার্থক্য
  • build time বনাম runtime
  • CMD কীভাবে Docker image-এর সঙ্গে থাকে
  • কীভাবে CMD override করা যায়
  • এবং একটি real Go server দিয়ে পুরো বিষয়টি hands-onভাবে বোঝা

এই distinction বোঝা Docker-এর fundamental concepts-এর একটি।


1. The Problem: Why Does the Container Exit?

ধরুন আমাদের image তৈরি হয়ে গেছে:

new_go_server:1.0.0
Enter fullscreen mode Exit fullscreen mode

এখন আমরা চালালাম:

docker run new_go_server:1.0.0
Enter fullscreen mode Exit fullscreen mode

কিন্তু কিছুক্ষণ পরেই container বন্ধ হয়ে গেল।

docker ps-এ কিছু নেই।

তখন:

docker ps -a
Enter fullscreen mode Exit fullscreen mode

দিলে দেখা যাবে container-এর status:

Exited
Enter fullscreen mode Exit fullscreen mode

কেন?

কারণ container কোনো GUI application নয় যে শুধু "open" হয়ে থাকবে।

একটি Docker container-এর lifecycle মূলত তার primary process-এর সঙ্গে সম্পর্কিত।

যে process container-এর প্রধান process হিসেবে চলছে সেটি শেষ হয়ে গেলে container-ও শেষ হয়ে যায়। Reference material-এও এই কারণেই default command/process না থাকলে container start হয়ে immediately exit করার বিষয়টি দেখানো হয়েছে।

আমাদের Go application-এর ক্ষেত্রে আমরা চাই:

docker run
     ↓
Container starts
     ↓
Go server starts
     ↓
Server keeps running
     ↓
Container stays alive
Enter fullscreen mode Exit fullscreen mode

কিন্তু Docker-কে তো আমরা বলিইনি যে server কীভাবে start করবে।

এখানেই CMD প্রয়োজন।


2. What Does CMD Actually Do?

সহজ ভাষায়:

CMD বলে দেয়—কোনো image থেকে container start হলে default হিসেবে কোন command চালানো হবে।

আমাদের ক্ষেত্রে:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

এর অর্থ:

Container starts
       ↓
Run:
go run server.go
Enter fullscreen mode Exit fullscreen mode

ফলে:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

দিলেই Go server automatically start হবে।

আর manually:

go run server.go
Enter fullscreen mode Exit fullscreen mode

লিখতে হবে না।

এটাই CMD-এর মূল purpose।


3. Our Complete Dockerfile

এখন আগের Dockerfile-এ CMD যোগ করি:

FROM ubuntu:24.04

RUN apt update

RUN apt install -y golang

WORKDIR /app

COPY ./server.go ./server.go

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

এখন আমাদের Dockerfile-এর responsibilities পরিষ্কার:

FROM
 ↓
Base Image

RUN
 ↓
Install Dependencies

WORKDIR
 ↓
Set Working Directory

COPY
 ↓
Bring Application Code

CMD
 ↓
Define Default Runtime Command
Enter fullscreen mode Exit fullscreen mode

এটি Dockerfile-এর একটি very useful mental model।


4. The Most Important Concept: RUN vs CMD

Dockerfile শেখার সময় সবচেয়ে common confusion:

"RUN আর CMD—দুটোই তো command চালায়। তাহলে difference কী?"

Difference হলো কখন এবং কেন command চালানো হচ্ছে।

RUN

RUN execute হয়:

docker build
Enter fullscreen mode Exit fullscreen mode

এর সময়।

CMD

CMD execute হয়:

docker run
Enter fullscreen mode Exit fullscreen mode

এর সময়।

অর্থাৎ:

                 docker build
                      │
                      ▼
               ┌─────────────┐
               │     RUN     │
               └─────────────┘
                      │
                      ▼
                   IMAGE
                      │
                      │ docker run
                      ▼
               ┌─────────────┐
               │     CMD     │
               └─────────────┘
                      │
                      ▼
                 CONTAINER
Enter fullscreen mode Exit fullscreen mode

Reference material-এও RUN-কে build phase এবং CMD-কে run phase-এর instruction হিসেবে আলাদা করা হয়েছে।


5. What Happens During docker build?

ধরুন আমরা চালালাম:

docker build -t new_go_server:1.0.1 .
Enter fullscreen mode Exit fullscreen mode

Dockerfile:

FROM ubuntu:24.04

RUN apt update
RUN apt install -y golang

WORKDIR /app

COPY ./server.go ./server.go

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

Build-এর সময় Docker:

FROM ubuntu:24.04
        ↓
RUN apt update
        ↓
RUN apt install -y golang
        ↓
WORKDIR /app
        ↓
COPY server.go
        ↓
Create Image
Enter fullscreen mode Exit fullscreen mode

কিন্তু এখানে একটি গুরুত্বপূর্ণ বিষয়:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

এই command build-এর সময় execute হয় না।

এটি image-এর configuration/metadata-এর অংশ হিসেবে রাখা হয়।

Reference build flow-এও CMD build step হিসেবে execute না হয়ে image-এর সঙ্গে default runtime instruction হিসেবে সংরক্ষিত হওয়ার বিষয়টি দেখানো হয়েছে।


6. Then What Happens During docker run?

Build শেষ।

আমাদের image:

new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

এখন:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

চালালাম।

Docker image থেকে একটি container তৈরি করবে।

তারপর image-এর মধ্যে থাকা default CMD দেখবে:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

এবং container-এর ভিতরে সেটি execute করবে।

ফলে:

docker run
     ↓
Create Container
     ↓
Start Container
     ↓
Execute CMD
     ↓
go run server.go
     ↓
Go Server :8080
Enter fullscreen mode Exit fullscreen mode

Output:

Server is running on :8080
Enter fullscreen mode Exit fullscreen mode

এখন container আর সঙ্গে সঙ্গে exit করবে না, কারণ Go server foreground-এ চলমান process হিসেবে container-কে active রাখছে। Reference hands-on test-এও docker run new_go_server:1.0.1-এর পর CMD থেকে Go server automatically start হওয়ার বিষয়টি দেখানো হয়েছে।


7. Understanding the Exec Form

আমরা লিখেছি:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

এটাকে বলা হয় Exec Form

এখানে প্রতিটি argument আলাদা string:

"go"
"run"
"server.go"
Enter fullscreen mode Exit fullscreen mode

এবং comma দিয়ে আলাদা করা হয়েছে।

Conceptually এটি:

go run server.go
Enter fullscreen mode Exit fullscreen mode

command-টির equivalent।

Reference material-এ Dockerfile-এর জন্য এই JSON-array/Exec Form syntax-টিকেই ব্যবহার করা হয়েছে।


8. A Critical Mental Model

এখন এই দুইটি statement মনে রাখুন:

RUN

Build the image.

CMD

Run the application when the container starts.

আরও সহজভাবে:

RUN
→ Image তৈরির সময়

CMD
→ Container চালুর সময়
Enter fullscreen mode Exit fullscreen mode

এই একটি distinction Dockerfile-এর অনেক confusion দূর করে।


9. CMD Does NOT Run During Build

এটি beginner-দের একটি common misunderstanding।

ধরুন:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

লিখেছি।

তারপর:

docker build -t go-server:1.0.1 .
Enter fullscreen mode Exit fullscreen mode

চালালাম।

এখানে Go server start হবে না।

আপনি build output-এ:

Server is running on :8080
Enter fullscreen mode Exit fullscreen mode

দেখবেন না।

কারণ CMD তখন execute হয়নি।

Image তৈরি হয়েছে এবং default command হিসেবে CMD image-এর সঙ্গে সংরক্ষিত হয়েছে।

তারপর:

docker run go-server:1.0.1
Enter fullscreen mode Exit fullscreen mode

দিলে CMD execute হবে।


10. The Magic of Default Commands

এখন সবচেয়ে useful part।

আমাদের image:

new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

এর default command:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

তাই:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

মানে effectively:

Run container
+
Use the image's default command
Enter fullscreen mode Exit fullscreen mode

ফলে server automatically start হয়।

এটাই containerized application-এর expected behaviour:

docker run image
        ↓
Application starts
        ↓
Application keeps running
Enter fullscreen mode Exit fullscreen mode

User-কে container-এর ভিতরে ঢুকে application manually start করতে হয় না।


11. But What If I Want Another Command?

এখানে Docker-এর আরেকটি powerful feature আছে।

ধরুন image-এর default:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

কিন্তু debugging-এর জন্য আমরা container-এর ভিতরে bash shell চাই।

তাহলে:

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

এখানে কী হলো?

আমরা bash command দিয়েছি।

Docker default CMD ব্যবহার না করে এই command execute করবে।

অর্থাৎ:

Dockerfile CMD
      │
      │ override
      ▼
docker run ... bash
      │
      ▼
bash
Enter fullscreen mode Exit fullscreen mode

Reference material-এ এই exact behaviour দেখানো হয়েছে—docker run <image> <custom_command> ব্যবহার করলে Dockerfile-এর CMD override হয়ে custom command execute হয়।


12. CMD Override: A Practical Example

Default behaviour:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

Result:

go run server.go
Enter fullscreen mode Exit fullscreen mode

কিন্তু:

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

Result:

bash
Enter fullscreen mode Exit fullscreen mode

অর্থাৎ CMD override হয়েছে।

এটি বিশেষ করে debugging-এর সময় useful।

ধরুন application start হচ্ছে না।

তখন:

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

দিয়ে container-এর ভিতরে ঢুকে manually inspect করতে পারি:

ls
go version
go run server.go
Enter fullscreen mode Exit fullscreen mode

অর্থাৎ production-এ default command ব্যবহার করা হবে, আর troubleshooting-এর সময় custom command দিয়ে override করা যেতে পারে।


13. CMD Override মানে Image পরিবর্তন নয়

এখানে আরেকটি subtle point আছে।

যখন আমরা:

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

দিই, তখন আমরা Docker image-এর CMD permanently পরিবর্তন করছি না।

শুধু এই particular container-এর জন্য default command-এর পরিবর্তে bash চালাচ্ছি।

পরেরবার:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

দিলে আবার:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

execute হবে।

অর্থাৎ:

Image
│
├── Default CMD → go run server.go
│
├── Container A → default CMD
│
└── Container B → bash override
Enter fullscreen mode Exit fullscreen mode

Image-এর default configuration unchanged থাকে।


14. Hands-On: Build the New Image

এখন complete Dockerfile দিয়ে নতুন image build করি:

docker build -t new_go_server:1.0.1 .
Enter fullscreen mode Exit fullscreen mode

Build-এর সময়:

FROM
RUN
RUN
WORKDIR
COPY
Enter fullscreen mode Exit fullscreen mode

এর instructions process হবে।

কিন্তু:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

run হবে না।

এটি image-এর default runtime command হিসেবে save হবে।


15. Run Without -it

এবার:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

কোনো:

-it
Enter fullscreen mode Exit fullscreen mode

নেই।

কোনো:

bash
Enter fullscreen mode Exit fullscreen mode

নেই।

শুধু:

docker run
+
image
Enter fullscreen mode Exit fullscreen mode

এবং তারপরও Go server start হয়ে যাবে।

কারণ Docker image-এর মধ্যে আমরা already define করেছি:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

Output:

Server is running on :8080
Enter fullscreen mode Exit fullscreen mode

এটাই আমাদের desired behaviour।


16. Verify the Running Container

অন্য terminal খুলে:

docker ps
Enter fullscreen mode Exit fullscreen mode

চালালে running container দেখা যাবে।

তারপর container-এর ভিতরে প্রবেশ করতে:

docker exec -it <CONTAINER_ID> bash
Enter fullscreen mode Exit fullscreen mode

এবং:

curl http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Expected:

Hello World!
Enter fullscreen mode Exit fullscreen mode

Reference hands-on workflow-এ docker exec দিয়ে running container-এ ঢুকে curl http://localhost:8080 ব্যবহার করে Hello World! response verify করা হয়েছে।


17. docker run বনাম docker exec

এই example-এ আরেকটি important distinction পাওয়া যায়।

docker run

নতুন container তৈরি করে এবং তার default command বা supplied command চালায়।

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

docker exec

Already running container-এর ভিতরে নতুন command চালায়।

docker exec -it <CONTAINER_ID> bash
Enter fullscreen mode Exit fullscreen mode

অর্থাৎ:

docker run
→ Start a new container

docker exec
→ Execute inside an existing container
Enter fullscreen mode Exit fullscreen mode

এই distinction debugging-এর সময় খুব গুরুত্বপূর্ণ।


18. Complete Lifecycle

এখন পুরো lifecycle-টা একসঙ্গে দেখি:

                 Dockerfile
                     │
                     │ docker build
                     ▼
              Docker Image
                     │
              ┌──────┴──────┐
              │             │
              │ docker run  │
              │             │
              ▼             ▼
        Default CMD      Custom Command
              │             │
              ▼             ▼
     go run server.go      bash
              │
              ▼
       Go HTTP Server
              │
              ▼
          :8080
Enter fullscreen mode Exit fullscreen mode

এখানে Dockerfile থেকে image, image থেকে container, এবং container start হওয়ার সময় CMD execution—পুরো chain-টি পরিষ্কার হয়ে যায়।


19. RUN vs CMD: Final Comparison

বিষয় RUN CMD
কখন execute হয়? docker build docker run
মূল উদ্দেশ্য Image তৈরি/configure করা Default runtime command
Image layer তৈরি করে? হ্যাঁ Command নিজে build layer তৈরি করে না
Build-এর সময় application চালায়? হতে পারে না
Container start হলে automatically execute? না হ্যাঁ, যদি override না করা হয়
Override করা যায়? Runtime command হিসেবে নয় হ্যাঁ
Example RUN apt install -y golang CMD ["go", "run", "server.go"]

Reference material-এও execution phase, purpose এবং image-এর সঙ্গে persistence-এর ভিত্তিতে RUNCMD-কে এভাবেই আলাদা করা হয়েছে।


20. The Three Most Important Commands

এই lesson-এর core workflow মাত্র কয়েকটি command-এ:

Build

docker build -t new_go_server:1.0.1 .
Enter fullscreen mode Exit fullscreen mode

Normal Run

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

CMD automatically execute হবে।

Debug / Override

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

CMD override হয়ে bash execute হবে।

এই তিনটি command-এর relationship বুঝলেই CMD অনেক সহজ হয়ে যায়।


21. The Most Important Mental Model

Dockerfile-এর ক্ষেত্রে এই flow-টি মনে রাখুন:

                 BUILD TIME
                     │
                     ▼
        ┌────────────────────────┐
        │ FROM                   │
        │ RUN                    │
        │ WORKDIR                │
        │ COPY                   │
        └────────────────────────┘
                     │
                     ▼
                Docker Image
                     │
                     │ docker run
                     ▼
                 RUNTIME
                     │
                     ▼
                   CMD
                     │
                     ▼
             Application Process
Enter fullscreen mode Exit fullscreen mode

অর্থাৎ:

RUN prepares the image. CMD starts the application.

এই এক লাইনের mental model-টি Dockerfile-এর অনেক confusion দূর করতে পারে।


22. Why This Matters Beyond This Example

আমাদের example একটি simple Go server।

কিন্তু একই principle practically সব ধরনের containerized application-এর ক্ষেত্রে দেখা যায়।

একটি application image তৈরি করার সময়:

Dependencies
Configuration
Application Files
Enter fullscreen mode Exit fullscreen mode

image-এর মধ্যে prepare করা হয়।

আর container start হওয়ার সময়:

Application Process
Enter fullscreen mode Exit fullscreen mode

start করা হয়।

তাই একটি well-designed container-এর ক্ষেত্রে user experience ideally এমন:

docker run <image>
Enter fullscreen mode Exit fullscreen mode

এবং application নিজে থেকেই start করবে।

User-কে container-এর ভিতরে গিয়ে manually setup করতে হবে না।

এটাই containerization-এর বড় সুবিধাগুলোর একটি।


23. One Last Look at Our Go Server

আমাদের server.go:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintln(w, "Hello World!")
    })

    fmt.Println("Server is running on :8080")
    http.ListenAndServe(":8080", nil)
}
Enter fullscreen mode Exit fullscreen mode

Dockerfile:

FROM ubuntu:24.04

RUN apt update
RUN apt install -y golang

WORKDIR /app

COPY ./server.go ./server.go

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

Build:

docker build -t new_go_server:1.0.1 .
Enter fullscreen mode Exit fullscreen mode

Run:

docker run new_go_server:1.0.1
Enter fullscreen mode Exit fullscreen mode

Debug:

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

Test:

curl http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Response:

Hello World!
Enter fullscreen mode Exit fullscreen mode

এই ছোট example-এর মধ্যেই Dockerfile-এর একটি complete lifecycle দেখা যাচ্ছে।


Final Takeaway

আজকের lesson-এ মূলত একটি প্রশ্নের উত্তর খুঁজেছি:

How do we make a Docker container automatically start our application?

উত্তর:

CMD ["go", "run", "server.go"]
Enter fullscreen mode Exit fullscreen mode

কিন্তু শুধু syntax মনে রাখলে হবে না।

বোঝা দরকার কখন এটি execute হয়।

docker build

FROM
RUN
WORKDIR
COPY
Enter fullscreen mode Exit fullscreen mode

এগুলো image তৈরি করে।

CMD তখন execute হয় না।

তারপর:

docker run

Container Created
      ↓
CMD Executed
      ↓
Go Server Started
      ↓
Container Keeps Running
Enter fullscreen mode Exit fullscreen mode

আর যদি debugging করতে চাই:

docker run -it new_go_server:1.0.1 bash
Enter fullscreen mode Exit fullscreen mode

তাহলে default CMD override হয়ে bash চালু হবে।

শেষ পর্যন্ত Docker-এর এই simple mental model-টি মনে রাখুন:

Build the environment with RUN.
Define the default application process with CMD.
Start it with docker run.
Override it when you need to debug.

একটি ছোট CMD instruction আসলে Docker image-কে একটি static filesystem থেকে একটি runnable application environment-এ পরিণত করার গুরুত্বপূর্ণ অংশ।

আর Docker শেখার পরবর্তী ধাপে এই concept থেকেই naturally আসে ENTRYPOINT, CMD বনাম ENTRYPOINT, environment variables, ports, volumes এবং production-grade container design।

Understand the lifecycle, not just the command. 🐳

Top comments (0)