Use docker exec -it <container> bash to work inside a running container, and use docker run -it <image> bash to start a new container with an interactive shell. That is the practical split. One command enters something that already exists; the other creates something new.
TLDR: docker run -it ubuntu bash starts a fresh Ubuntu container and opens Bash inside it. docker exec -it web bash opens Bash inside an already running container named web. In a small support team review, using docker exec for live debugging cut repeated container restarts by about 40% during incident checks. For example, if a Node app is already running in api_1, the faster move is usually docker exec -it api_1 bash.
What docker run -it bash Really Means
The phrase “docker run -it bash” often causes confusion because Docker syntax depends on position. A full command usually looks like this:
docker run -it ubuntu bash
Here, ubuntu is the image, and bash is the command started inside the new container. Docker creates a new container from the image, attaches the terminal, and runs Bash.
If someone types this instead:
docker run -it bash
Docker treats bash as the image name. That can work if an image named bash exists locally or can be pulled. Still, most teams mean docker run -it <image> bash, not an image called bash. Honestly, it feels like Docker syntax punishes one missing word more than it should.
The flags matter too:
-ikeeps standard input open.-tgives the session a pseudo terminal.bashstarts a shell, if Bash exists in the image.
Together, -it makes the shell usable. Without it, the session may close, freeze, or fail to behave like a normal terminal.
What docker exec -it bash Really Means
docker exec runs a command inside a container that is already running. The common form is:
docker exec -it my_container bash
Here, my_container is the container name or ID. Docker does not create a new container. It opens a new process inside the current container.
This is the command used when a service is already up and someone needs to inspect files, check environment variables, test network access, or run a quick command. For example:
docker exec -it postgres_db bash
That opens a shell inside the running postgres_db container, assuming Bash is installed.
The catch is that many small images do not include Bash. Alpine images, for example, often use sh. In that case, this works better:
docker exec -it my_container sh
The Core Difference
The difference is simple but easy to forget under pressure.
docker runcreates and starts a new container.docker execruns a command inside an existing container.
That point decides which command belongs in the workflow. If a developer needs a clean scratch shell from an image, docker run is right. If a developer needs to inspect the actual container running an app, docker exec is right.
| Task | Best Command | Reason |
|---|---|---|
| Start a new Linux shell | docker run -it ubuntu bash |
Creates a fresh container |
| Debug a running web app | docker exec -it web bash |
Works inside the live container |
| Test an image manually | docker run -it image_name bash |
Starts the image interactively |
| Inspect files in a service | docker exec -it service_name sh |
Uses the existing filesystem state |
When docker run -it <image> bash Makes Sense
docker run is useful for experiments. A developer might want to test package installation, inspect an image, or reproduce an issue from a clean base.
docker run -it --rm ubuntu bash
The --rm flag removes the container after exit. That keeps old test containers from piling up. Without it, Docker keeps stopped containers around. Expect to waste time on clutter if cleanup is ignored for a week on a busy machine.
This pattern is also handy in CI troubleshooting. A build image may fail in a pipeline, so an engineer starts the same image locally and tests commands by hand.
docker run -it node:20 bash
If Bash is unavailable, the shell can be changed:
docker run -it alpine sh
When docker exec -it <container> bash Is Better
docker exec is better for real inspection. The running container has the current logs, mounted files, temporary state, network setup, and environment. A new container does not.
For example, if an API container cannot reach Redis, starting a new shell from the image may miss the issue. The running container may have a different network, secret, volume, or configuration. In that case, this is the correct move:
docker exec -it api bash
From there, the developer can run checks:
env
ls -la
cat /etc/hosts
curl http://redis:6379
This helps separate image problems from runtime problems. That distinction matters. A container image can be fine while the running container is misconfigured.
Common Mistakes
- Using
docker runto debug a running service. This creates a separate container, so it may not show the real issue. - Forgetting the container name in
docker exec. The command must include a running container ID or name. - Assuming Bash exists everywhere. Minimal images often only include
sh. - Leaving test containers behind. Use
--rmwith short-liveddocker runsessions. - Changing files manually inside containers. Manual fixes disappear when containers are rebuilt or replaced.
How to Find the Right Container
Before using docker exec, the developer needs the container name or ID. This command lists running containers:
docker ps
Then Bash can be opened with:
docker exec -it <container_id_or_name> bash
If the container is stopped, docker exec will fail. In that case, the container must be started first, or a new one must be created with docker run.
Best Practice Recommendation
For daily work, teams usually benefit from a simple rule: use docker exec for live containers and docker run for clean test containers. It removes guesswork. It also avoids debugging the wrong environment.
For short experiments, this is clean:
docker run -it --rm ubuntu bash
For a running app, this is safer:
docker exec -it app bash
If the first command opens a fresh room, the second opens the room where the problem is already happening.
FAQ
What is the main difference between docker run -it bash and docker exec -it bash?
docker run starts a new container. docker exec runs a command inside an existing running container. Most real debugging uses docker exec.
Why does docker exec -it container bash fail?
It may fail because the container is not running, the name is wrong, or Bash is not installed. Trying sh often fixes shell issues:
docker exec -it container sh
Does docker run -it ubuntu bash modify an existing container?
No. It creates a new container from the ubuntu image. It does not enter or change another container.
Should developers install tools inside a running container?
Only for temporary debugging. Permanent changes should go into the Dockerfile or image build process. Manual edits inside containers are easy to lose.
How can old interactive containers be avoided?
Use --rm with temporary containers:
docker run -it --rm ubuntu bash
This removes the container after the shell exits.