PWD is not set in ENV instruction in a Dockerfile
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
PWD often behaves the way developers expect inside an interactive shell, so it is confusing when ENV CURRENT_DIR=$PWD in a Dockerfile does not work. The reason is that ENV is not executed by a shell in the way RUN is, and Dockerfile variable expansion only knows about values that already exist in the Docker build context for that instruction. In practice, WORKDIR, ARG, and runtime shell evaluation solve different parts of this problem.
Why PWD Is Not Available the Way You Expect
A Dockerfile has several instruction types, and they do not all evaluate variables the same way.
- '
RUNexecutes a command in a shell-like environment, depending on the form you use.' - '
ENVsets image environment variables.' - '
WORKDIRsets the current working directory for later build steps and at container start.'
This often surprises people:
Here, Docker is not asking a shell to expand the current directory the way your terminal would. Unless PWD is already defined as an environment variable available to that Dockerfile instruction, the expansion will not give you the shell current-directory value you had in mind.
Use WORKDIR for Directory Intent
If what you really want is "this image should work from /app," use WORKDIR.
WORKDIR is the correct tool because it changes where later instructions run and what the container uses as its current directory by default.
If you build and run this image, the shell in CMD prints /app because the container process starts there.
If You Need a Variable, Set It Explicitly
If you want an environment variable representing a known path, declare that path directly:
This is clearer than trying to infer the path indirectly through PWD.
At runtime:
- '
APP_DIRis an image environment variable you defined.' - '
PWDis provided by the shell process that starts in/app.'
Those are related, but they come from different mechanisms.
Passing Host-Side Paths Is a Separate Problem
Sometimes the real goal is not the container working directory, but the host directory from which docker build was invoked. Docker does not automatically expose your host shell PWD into the image build as a magical default.
If you truly need that value, pass it in with a build argument:
Build command:
That works because you explicitly injected the host value. Docker did not infer it for you.
RUN pwd Versus ENV CURRENT_DIR=$PWD
This distinction helps:
RUN pwd prints the current working directory during that build step because it runs as a command.
By contrast, this instruction is just variable assignment using Dockerfile expansion rules:
Those are not equivalent. One executes a program. The other records an environment variable in image metadata.
Prefer Explicit Paths Over Implicit Shell State
Images are more maintainable when their important paths are explicit. WORKDIR /app communicates intent directly. ENV APP_DIR=/app communicates it again for application code that wants a variable. PWD is useful inside running shells, but it is not a strong design anchor for Dockerfile structure.
Common Pitfalls
- Assuming every Dockerfile instruction expands variables the same way a shell does.
- Using
ENVwhen the real need isWORKDIR. - Expecting the host terminal
PWDvalue to appear automatically inside the image build. - Hiding important directory choices behind implicit shell state instead of explicit paths.
- Confusing build-time behavior with runtime shell behavior inside a started container.
Summary
- '
ENVdoes not magically evaluate shellPWDthe way an interactive terminal does.' - Use
WORKDIRto set the image and container working directory. - Set path-like environment variables explicitly if your application needs them.
- Pass host-side directory values with
ARGwhen that information is genuinely required. - Prefer explicit Dockerfile paths over implicit assumptions about shell state.
Related reading
- Python service uses 100 of CPU on while loop with sleep inside docker container
- Rabbitmq connection refused from Docker container to local host
- RabbitMQ in Docker - user creation not persisted
- RabbitMQ with Unity IOC Container in .NET
- Rails server is still running in a new opened docker container
- Rancher with cattle vs Rancher with Kubernetes vs Standalone Kubernetes
- Re-using environment variables in docker-compose.yml
- Re-using existing volume with docker compose

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.