What is the difference between ENTRYPOINT and CMD in a Dockerfile?
Fast recall
Quick revision
Core answer
ENTRYPOINT defines the executable and CMD supplies default arguments when both are present. With only CMD, it defines the default command. Arguments after the image name replace CMD; --entrypoint replaces ENTRYPOINT. Shell-form instructions have different argument and signal behavior, so exec form is usually clearer for services.Interview-ready guide
Interview answer
CMD supplies a container's default command when used alone. When an exec-form ENTRYPOINT is also present, CMD supplies its default arguments. Arguments after the image name replace CMD, while docker run --entrypoint ... replaces the entrypoint.
For example, ENTRYPOINT ["java","-jar","/app/app.jar"] with CMD ["--spring.profiles.active=prod"] runs the JAR with that default profile. docker run image --spring.profiles.active=dev replaces only the CMD argument.
Exec and shell forms matter. Exec form avoids an extra shell and generally gives the application clearer signal behavior. Shell form changes argument combination and PID/signal handling. I use ENTRYPOINT for a stable executable and CMD for replaceable defaults, but either instruction can be overridden; ENTRYPOINT is not an unbreakable command.
What is the difference between ENTRYPOINT and CMD in a Dockerfile
Direct Answer
In exec-form usage, ENTRYPOINT defines the executable and CMD supplies default arguments when both are present. With only CMD, it defines the default command. Arguments after the image name replace CMD; --entrypoint replaces ENTRYPOINT. Shell-form instructions have different argument and signal behavior, so exec form is usually clearer for services.
Code Example
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/order-service.jar app.jar
# ENTRYPOINT = fixed executable; CMD = default args you can override at run time
ENTRYPOINT ["java", "-jar", "app.jar"]
CMD ["--spring.profiles.active=prod"]
# docker run order-service
# -> java -jar app.jar --spring.profiles.active=prod
# docker run order-service --spring.profiles.active=dev
# -> CMD replaced; java -jar app.jar --spring.profiles.active=dev
# Use exec form (brackets) so Java is PID 1 and receives SIGTERM cleanly.
Common Mistakes & Pitfalls
- Using CMD when ENTRYPOINT is better: Freshers often write CMD ["java", "-jar", "app.jar"] thinking it locks down the startup command, but any argument passed to docker run replaces the entire CMD. If someone runs docker run myapp /bin/bash, your Java app never starts. Use ENTRYPOINT for fixed commands.
- Mixing exec form and shell form: Writing ENTRYPOINT ["java", "-jar"] with CMD app.jar (without brackets) creates a type mismatch. Both must use exec form ["..."] or both shell form.
- Not understanding argument replacement: Freshers think docker run myapp --spring.profiles.active=prod appends to CMD, but it replaces CMD entirely. If your ENTRYPOINT is java -jar app.jar, you'd need to pass the JAR name again. Solution: put the JAR in ENTRYPOINT and only profiles in CMD.
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.