How to Set Working Directory in Docker Run Command When Executing Shell Commands


3 views

The fundamental problem occurs because Docker's run command doesn't execute commands through a shell by default. When you try to chain commands with semicolons like cd /path; ./script, Docker interprets the entire string as a single executable name rather than a shell command sequence.

Your successful interactive approach works because /bin/bash creates a proper shell environment that understands command chaining:

docker run -it ubuntu/decomposer /bin/bash -c "cd /local/deploy/decomposer && ./decomposer-4-15-2014"

Here are three robust approaches to solve this problem:

1. Using Explicit Shell Invocation

docker run -P ubuntu/decomposer /bin/sh -c "cd /local/deploy/decomposer && ./decomposer-4-15-2014"

2. Leveraging Docker's WORKDIR Instruction

In your Dockerfile, you can set the working directory permanently:

FROM ubuntu/decomposer
WORKDIR /local/deploy/decomposer
CMD ["./decomposer-4-15-2014"]

3. Using the -w Flag for Runtime Directory

docker run -P -w /local/deploy/decomposer ubuntu/decomposer ./decomposer-4-15-2014

For complex scenarios, consider these patterns:

Environment Variables with Directory Paths

docker run -e APP_DIR=/local/deploy/decomposer \
  ubuntu/decomposer \
  /bin/sh -c "cd \$APP_DIR && ./decomposer-4-15-2014"

Multi-command Entrypoint Scripts

Create an entrypoint.sh:

#!/bin/sh
cd /local/deploy/decomposer
exec "$@"

Then in Dockerfile:

COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
CMD ["./decomposer-4-15-2014"]

When troubleshooting directory issues in Docker:

  • Use docker exec -it container_id ls /path to verify directory contents
  • Check default working directory with docker inspect --format='{{.Config.WorkingDir}}' image_name
  • For permission issues, add --user flag to run commands

When you execute docker run with a command string, Docker doesn't interpret it through a shell by default. This explains why your attempt with cd /local/deploy/decomposer; ./decomposer-4-15-2014 fails - Docker tries to execute the entire string as a single executable.

# This doesn't work because Docker looks for a single executable
docker run ubuntu/decomposer "cd /path && ./script"

Solution 1: Use Shell Form with -c Flag

The most straightforward approach is to explicitly invoke a shell:

docker run ubuntu/decomposer /bin/sh -c "cd /local/deploy/decomposer && ./decomposer-4-15-2014"

Solution 2: Set Working Directory in Dockerfile

For production deployments, define the working directory in your Dockerfile:

FROM ubuntu/decomposer
WORKDIR /local/deploy/decomposer
CMD ["./decomposer-4-15-2014"]

Solution 3: Use --workdir Flag (Docker 17.05+)

Modern Docker versions support runtime working directory specification:

docker run --workdir /local/deploy/decomposer ubuntu/decomposer ./decomposer-4-15-2014

If your application depends on relative paths, consider these approaches:

# Option 1: Rewrite paths in the application
docker run -v /host/path:/container/path --workdir /container/path app-image

# Option 2: Use entrypoint script
#!/bin/bash
cd /required/path && exec "$@"
  • Verify paths exist in container: docker run --rm ubuntu/decomposer ls -la /local/deploy/decomposer
  • Check default working directory: docker run --rm ubuntu/decomposer pwd
  • Test shell interpretation: docker run --rm ubuntu/decomposer /bin/sh -c "echo $PWD"