ENV, WORKDIR, and EXPOSE in Dockerfile
Fast recall
Quick revision
Core answer
WORKDIR sets the working directory for later Dockerfile instructions and the default container process, creating it if needed. ENV adds environment defaults to image configuration and affects later build instructions and containers unless overridden. EXPOSE documents intended listening ports; it does not publish them to the host.Interview-ready guide
Interview answer
WORKDIR sets the working directory for later instructions such as RUN, COPY, CMD, and ENTRYPOINT, and creates the directory if needed. A later FROM begins a new stage and resets stage-specific context unless it is set again.
ENV NAME=value stores an environment default in image configuration. It affects later build steps and containers created from the image, but runtime -e or platform configuration can override it. Because image metadata is inspectable, I never use Dockerfile ENV for a secret.
EXPOSE 8080 documents that the image expects a service on a container port and supports behaviors such as docker run -P; it does not create a host listener. I still publish explicitly with -p 127.0.0.1:8080:8080 or Compose ports when host access is required.
ENV, WORKDIR, and EXPOSE in Dockerfile
Direct Answer
WORKDIR sets the working directory for later Dockerfile instructions and the default container process, creating it if needed. ENV adds environment defaults to image configuration and affects later build instructions and containers unless overridden. EXPOSE documents intended listening ports; it does not publish them to the host.
Code Example
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/payment-service-1.0.0.jar app.jar
ENV SPRING_PROFILES_ACTIVE=prod
ENV JAVA_OPTS="-Xmx512m -Xms256m"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
Common Mistakes & Pitfalls
- Not using WORKDIR: Freshers skip WORKDIR and use absolute paths like COPY target/app.jar /app/app.jar, then RUN commands fail because the working directory is still /. Always set WORKDIR early so subsequent commands use relative paths.
- Thinking EXPOSE publishes the port: The biggest mistake is believing EXPOSE 8080 makes the container accessible on localhost:8080. It doesn't. EXPOSE is documentation only. You must use docker run -p 8080:8080 to actually map the port. Without -p, the container runs but the port isn't reachable from the host.
- Hardcoding secrets in ENV: Freshers write ENV DB_PASSWORD=secret123 in the Dockerfile, baking the secret into the image. Anyone who pulls the image can see it with docker history. Use ENV for non-sensitive config only, and pass secrets at runtime with docker run -e.
- Overusing ENV for build-time variables: ENV persists into the running container. If you only need a variable during the build, use ARG instead of ENV to avoid cluttering the runtime environment.
Check your understanding
Answer these without looking back at the article.
- What is the ARG instruction in Dockerfile and how does it differ from ENV?
- How do you pass secrets to a Docker container securely?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.