In a Dockerfile, How to update PATH environment variable?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
To update the PATH environment variable in a Dockerfile, use the ENV instruction: ENV PATH="/your/directory:${PATH}". This prepends your directory to the existing PATH and persists across all subsequent layers, RUN commands, and the final container.
How PATH Works in Docker
The PATH environment variable tells the shell which directories to search when you type a command. In Docker images, PATH is inherited from the base image. For example, the official ubuntu image sets PATH to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin. When you install software in a custom directory, you need to add that directory to PATH so the binaries are available without specifying full paths.
The ENV Instruction
The ENV instruction sets environment variables that persist in the image metadata. Unlike RUN export, which only affects the current shell session within a single RUN layer, ENV is permanent.
The ${PATH} reference expands to the current value of PATH, so existing directories are preserved. After this line, any subsequent RUN, CMD, or ENTRYPOINT instruction can find executables in /opt/myapp/bin.
Complete Working Example
Here is a Dockerfile that installs a custom tool and adds it to PATH:
Build and run it:
Prepending vs. Appending
The order of directories in PATH determines which binary runs when multiple directories contain executables with the same name. The shell searches left to right and uses the first match.
Prepending is the standard practice when you want your custom binaries to take priority over system defaults. For example, if you install a newer version of Python in /opt/python3.12/bin, prepending ensures that python3 resolves to your version rather than the system-installed one.
Real-World Patterns
Python Virtual Environment
Go Binary Installation
Node.js Local Binaries
Java with Custom JAVA_HOME
ENV vs. RUN export vs. Shell Profile
| Method | Persists Across Layers? | Available in CMD/ENTRYPOINT? | Available in docker exec? |
ENV PATH=... | Yes | Yes | Yes |
RUN export PATH=... | No | No | No |
RUN echo 'export PATH=...' >> ~/.bashrc | Only in interactive bash | Only if shell reads profile | Only in bash -l |
RUN export PATH=... is a common mistake. Each RUN instruction starts a new shell, so the export is lost as soon as the RUN layer finishes. The ENV instruction is the correct approach because it writes the variable into the image metadata, making it available everywhere.
Writing to .bashrc or .profile is fragile because these files are only read by interactive login shells. CMD ["myapp"] (exec form) does not start a shell at all, so profile scripts are never sourced.
Debugging PATH Issues
When a command is "not found" despite being installed, inspect PATH inside the container:
You can also verify during the build with a RUN instruction:
Multiple ENV Instructions and Layer Efficiency
Each ENV instruction creates a new image layer. If you need to set multiple environment variables, combine them in a single instruction to reduce layer count:
For PATH specifically, you typically only need one ENV PATH instruction. If you have multiple tools in different directories, concatenate them:
Common Pitfalls
Using RUN export instead of ENV. This is the most common mistake. The exported variable disappears after the RUN layer completes. Always use ENV for PATH changes that must persist.
Relative paths in PATH. Adding a relative path like ./bin to PATH can cause unpredictable behavior because it depends on the working directory at runtime. Always use absolute paths.
Forgetting ${PATH} when setting PATH. Writing ENV PATH="/opt/myapp/bin" without ${PATH} replaces the entire PATH, removing standard directories like /usr/bin. This breaks basic commands like ls, cat, and apt-get.
Overriding PATH at runtime. Running docker run -e PATH="/something" replaces the entire PATH set in the Dockerfile. If you need to extend PATH at runtime, reference the existing value: docker run -e PATH="/extra/dir:$PATH" your-image.
Multi-stage build confusion. PATH set in a builder stage does not carry over to the final stage. Each FROM instruction resets the environment to the new base image's defaults. You must set PATH again in the final stage.
Summary
Use ENV PATH="/your/dir:${PATH}" to update PATH in a Dockerfile. Always prepend rather than append when you want your binaries to take priority. Never use RUN export because it does not persist. Use absolute paths, always include ${PATH} to preserve existing directories, and remember that multi-stage builds require setting PATH in each stage. For debugging, use docker run --rm your-image env | grep PATH to verify the final value.
Related reading
- In Docker image names what is the difference between Alpine, Jessie, Stretch, and Buster?
- In Docker, what''s the difference between a container and an image?
- In Kubernetes, what is the difference between ResourceQuota vs LimitRange objects
- In Kubernetes, will Go container use all cores when another is using cores
- InitContainer not idempotent, how to prevent it from running twice?
- Inject code/files directly into a container in Kubernetes on Google Cloud Engine
- Injecting Env variable from initContainer to the main container before its ENTRYPOINT starts
- Install node in Dockerfile?

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.