In a Dockerfile, the use of ENTRYPOINT
and CMD
is crucial in defining the way a container behaves. However, it does confuse a lot of us regarding the usage, best practices, and key considerations when using these instructions.
ENTRYPOINT vs CMD:
ENTRYPOINT:
The ENTRYPOINT
instruction sets the primary command that will executed by the container when it starts. It can be specified with or without an executable and also allows for arguments.
ENTRYPOINT ["nginx", "-g", "daemon off;"]
ENTRYPOINT
command cannot be overridden by appending a command while executing 'docker run' at runtime. However, the arguments can be appended.
Example Dockerfile:
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
Run the container with a command:
docker run my-image Goodbye
Output:
# output
Hello Goodbye
If we really want to overwrite the command in ENTRYPOINT
, we need to use the '--entrypoint' with docker run:
# Example
docker run -it --entrypoint /bin/sh my_custom_image
CMD:
The CMD
instruction sets the default command for the container. If used without an ENTRYPOINT
, it becomes the default command and arguments that will be used when the container starts. Whereas, when used with an ENTRYPOINT
, it provides default arguments for the entry point.
This can be overridden though at runtime by passing a command when running the container using 'docker run'.
Example:
CMD ["nginx", "-g", "daemon off;"]
CMD
command can be overridden by appending a command while executing 'docker run' at runtime.
Example Dockerfile:
FROM ubuntu
CMD ["echo", "Hello"]
Run the container with a command:
docker run my-image Goodbye
Output:
# output
Goodbye
Best Practices:
We should prefer the exec form of the ENTRYPOINT
and CMD
to avoid shell processing.
Example:
ENTRYPOINT ["echo", "Hello, $USER"]
If we use the insecure way of using shell form instead, it might introduce a security vulnerability. The shell form can be abused to perform shell injection. Additionally, the shell form becomes dependent on the particular shell in use and if a different shell is being used in a distribution, it might not be consistent.
# An example where $USER can be used for shell injection vulnerability.
# Malicious code can be introduced if the $USER variable is not sanitized.
FROM ubuntu
CMD echo "Hello, $USER"
Choosing Between CMD and ENTRYPOINT
Use
CMD
when you want to provide default values for the command and allow them to be easily overridden at runtime.Use
ENTRYPOINT
when you want to set a fixed primary command and allow users to append additional arguments.
In many cases, combining both instructions offers a balance of flexibility and definition. Understanding these use cases will empower you to create more versatile and user-friendly Docker images.
ENTRYPOINT as a Script:
If we have a scenario where we want to run a script instead of any particular command, and maybe pass a default argument, we can do it seamlessly with ENTRYPOINT and using CMD along with it.
FROM node
# Set the working directory
WORKDIR /app
# Copy the application files
COPY . .
# Set the script as the ENTRYPOINT
ENTRYPOINT ["./entrypoint.sh"]
# Default argument 'start' to pass to the script if nothing mentioned in run.
CMD ["start"]
Conclusion:
Mastering Dockerfile entry points empowers you to create efficient, modular, and customizable Docker images. Whether you're building a simple web server or a complex microservices architecture, understanding how to leverage ENTRYPOINT
and CMD
is essential for Dockerfile success.
Happy Dockerizing!