Table of Contents
Introduction
When working with Docker, understanding the difference between RUN
, CMD
, and ENTRYPOINT
is key to effectively managing how containers are executed. These commands serve different purposes in controlling the behavior of a container when it's started.
The RUN Command: Your Image Builder
Think of RUN
as your container's construction worker. It executes during the image build process, setting up your environment.
Here's what RUN
does:
- Installs packages
- Creates directories
- Copies files
- Sets up your environment
Example:
FROM python:3.9
RUN apt-get update
RUN pip install flask
RUN mkdir /app
Each RUN
command creates a new layer in your image. It's like adding a new floor to a building - permanent and part of the structure.
The CMD Command: Your Default Instructions
CMD
is like leaving a note saying "here's what to do if no one says otherwise." It provides default commands or parameters that can be easily overridden.
Key points about CMD
:
- You can only have one
CMD
instruction in a Dockerfile
- It can be overridden from the command line
- It specifies the default program that should run in your container
There are three forms of CMD:
CMD python app.py
CMD ["python", "app.py"]
CMD ["--port", "8080"]
The ENTRYPOINT: Your Container's Primary Purpose
ENTRYPOINT
defines your container's main executable. Think of it as your container's mission in life - it's what the container is designed to do.
Two forms of ENTRYPOINT:
ENTRYPOINT python app.py
ENTRYPOINT ["python", "app.py"]
How They Work Together
The real magic happens when you combine these commands. Here's how they interact:
RUN
sets up your environment
ENTRYPOINT
sets the main executable
CMD
provides default arguments
Example:
FROM python:3.9
RUN pip install flask
RUN mkdir /app
WORKDIR /app
COPY . .
ENTRYPOINT ["python"]
CMD ["app.py", "--port", "8080"]
In this case:
- If you run the container normally: It executes
python app.py --port 8080
- If you run with arguments:
docker run myimage script.py
, it runs python script.py
Common Use Cases
Web Server Example
FROM nginx:alpine
RUN mkdir -p /usr/share/nginx/html
COPY ./website /usr/share/nginx/html
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
Application Server Example
FROM node:14
RUN mkdir /app
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
ENTRYPOINT ["node"]
CMD ["server.js"]
Best Practices
-
For RUN:
- Use for installation and setup
- Combine related commands with
&&
to reduce layers
- Clean up after installations
-
For CMD:
- Always use the exec form
["executable", "param1", "param2"]
- Use for default parameters that might need to change
- Remember it can be overridden at runtime
-
For ENTRYPOINT:
- Use for commands that shouldn't change
- Combine with CMD for flexible defaults
- Always use exec form for predictable behavior
Quick Reference Table
Command | Purpose | Can Override? | Multiple Allowed? |
---|
RUN | Build-time setup | No | Yes |
CMD | Default runtime command/args | Yes | No (last one wins) |
ENTRYPOINT | Container's main executable | Yes (--entrypoint) | No (last one wins) |
Example: Putting It All Together
Here's a complete example showing all three commands working together:
FROM python:3.9
RUN apt-get update && \
apt-get install -y --no-install-recommends \
postgresql-client && \
rm -rf /var/lib/apt/lists/*
RUN pip install flask psycopg2-binary
WORKDIR /app
COPY . .
ENTRYPOINT ["python"]
CMD ["app.py", "--host", "0.0.0.0", "--port", "8080"]
In this example:
RUN
installs dependencies and sets up the environment
ENTRYPOINT
specifies that Python is our main executable
CMD
provides default arguments that can be overridden
Conclusion
Understanding the differences between RUN
, CMD
, and ENTRYPOINT
is crucial for Docker mastery:
- Use
RUN
for building your image and setting up the environment
- Use
CMD
for default commands and arguments that might change
- Use
ENTRYPOINT
for the main executable that defines your container's purpose
Remember: RUN
executes during build, while CMD
and ENTRYPOINT
determine what happens when your container starts. Happy Dockerizing!