avoid-run-cd
cd in a Dockerfile RUN doesn't persist to the next instruction. Use WORKDIR to change directories in Docker builds.
On this page
Every RUN starts a fresh shell, so RUN cd /app changes directory for that one instruction and is forgotten by the next line — the most common "why is my file not where I put it" surprise in Dockerfile debugging. This rule flags cd used inside RUN to establish directory context.
What the rule catches
FROM node:22-slim
RUN cd /app && npm ci
RUN npm run build # runs in /, not /app — build failsScanning this file reports:
ℹ INFO [docker-doctor/avoid-run-cd]
Avoid using 'cd' in RUN instructions. Use WORKDIR instead to change the working directory stably across layers.Why it matters
cd inside RUN either does nothing beyond its own line (a standalone RUN cd /app is a pure no-op) or buries the directory context mid-command where readers and tools can't see it. WORKDIR is the Dockerfile-native way to say "operations happen here": it persists across all subsequent RUN, COPY, CMD, and ENTRYPOINT instructions, creates the directory if needed, and appears at the top level of the file where directory context belongs.
How to fix it
Use the WORKDIR instruction instead of cd inside RUN to establish directory context.
FROM node:22-slim
WORKDIR /app
RUN npm ci
RUN npm run buildA cd can be legitimate within one compound command when you need a temporary directory change mid-pipeline (RUN tar xzf src.tar.gz && cd src && make install && cd .. && rm -rf src). The rule's target is cd standing in for WORKDIR — directory context that the next instruction depends on.
Rule details
- Rule key —
docker-doctor/avoid-run-cd - Category — Best Practices
- Default severity —
info - Applies to — Dockerfiles
Explain this rule from the CLI:
npx @docker-doctor/cli@latest rules explain docker-doctor/avoid-run-cdChange its severity — or turn it off — in your config file:
// docker-doctor.config.ts
export default {
rules: {
"docker-doctor/avoid-run-cd": "off",
},
};Severity affects the health score: error findings cost more points than warning, and info costs the least.