Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

docker exec: How to Get a Shell Inside a Running Container Without Restarting It

Sean

Platform Writer

Jul 18, 2026
7 min read

docker exec runs a command inside a container that is already running - most often an interactive shell for poking around. The command you want almost every time is docker exec -it <container> bash (or sh if the image has no bash). The -i keeps stdin open and the -t gives you a terminal, and together they turn a one-shot command into a usable shell. docker exec does not restart the container and does not create a new one; it steps into the process namespace of the one that is live.

docker exec: How to Get a Shell Inside a Running Container Without Restarting It

The mistake people make first is reaching for docker run when they want docker exec. run starts a new container. exec enters an existing one. If you already have something running and you want to look inside it, exec is the verb.

Table of contents

The command you actually want

docker exec -it my_api bash

That drops you into an interactive bash shell inside the container named my_api. Break it down:

  • exec - run a command in a running container.
  • -i - interactive; keep stdin open so you can type.
  • -t - allocate a pseudo-TTY so the shell behaves like a real terminal.
  • my_api - the container name or ID (docker ps lists them).
  • bash - the command to run; here, a shell.

If the image is a slim one - alpine, distroless-ish, many official images - bash may not exist. Fall back to sh:

docker exec -it my_api sh

sh is almost always present. bash is a luxury the smaller images skip. When bash gives you executable file not found, that is what happened - try sh before assuming the container is broken.

Running one-off commands without a shell

You do not need an interactive shell for a single command. Drop -it and just run it:

docker exec my_api ls -la /app
docker exec my_api cat /etc/hostname
docker exec my_api python manage.py migrate

This is the clean way to run a migration, check a file, or fire a management command against the live container. The output comes straight back to your terminal and you are not left inside a shell you have to exit.

Use -i without -t when you want to pipe input in:

echo "SELECT 1;" | docker exec -i my_db psql -U postgres

The rule: -it for an interactive session, -i alone for piping, neither for a fire-and-forget command. Adding -t to a non-interactive command in a script is a common cause of the input device is not a TTY errors in CI.

Environment, user, and working directory

exec takes the same environment-shaping flags as run:

docker exec -it -u root my_api bash          # enter as root
docker exec -it -w /app my_api bash          # start in /app
docker exec -it -e DEBUG=1 my_api python app.py

-u root is the one you reach for most, because many images run as an unprivileged user and you need root to install a debugging tool or read a protected file. -w sets the working directory so you do not have to cd on entry. -e injects an environment variable for that command only.

These do not persist. Anything you install with -u root lives until the container is recreated, then it is gone - which is the point of containers, and also why you should put real dependencies in the image, not exec them in by hand.

exec versus run versus attach

Three commands sound similar and do different things:

  • docker run creates and starts a new container. Every run is a fresh container.
  • docker exec starts an additional process inside a container that is already running.
  • docker attach connects your terminal to the container’s main process (PID 1) - its existing stdout and stdin. Detaching cleanly is fiddly, and Ctrl+C may stop the container.

For debugging, exec is almost always what you want, because it gives you a separate shell process that you can exit without touching the main application. attach puts you on the main process itself, which is riskier. If you have ever accidentally killed a container by pressing Ctrl+C, you were probably attached, not exec’d.

When exec fails

A few failures come up repeatedly:

  • Container is not running - exec only works on a running container. If it exited, there is nothing to enter; check docker ps -a and the logs with docker logs.
  • executable file not found - the shell or command you asked for is not in the image. Try sh instead of bash.
  • the input device is not a TTY - you passed -t in a context with no terminal, usually a CI pipeline. Drop the -t.
  • Permission denied on a file - you are the container’s non-root user. Re-enter with -u root.

If the container has already crashed, exec cannot help you - there is no process to step into. That is when you go to the logs, or start a throwaway container from the same image with docker run -it <image> sh to inspect the filesystem. Knowing which tool applies to a stopped versus a running container saves a lot of confused minutes.

How this fits the rest of the stack

docker exec is a debugging tool, and needing it a lot is a signal - if you are constantly shelling in to check why something failed, the real gap is logs and health visibility you can see without touching the container. A platform that surfaces build output, run logs, and health in one place is what turns exec from a daily habit into an occasional one. The RunxBuild hosting calculator lays out the service, database, storage, and bandwidth as separate line items, and the RunxBuild dashboard is where the team watches deploys, logs, and restarts as they happen.

Useful related references:

FAQ

What does docker exec do?

It runs a command inside a container that is already running, without restarting or recreating it. The most common use is docker exec -it <container> bash to get an interactive shell for debugging, but it also runs one-off commands like migrations or file checks against the live container.

What is the difference between docker exec and docker run?

docker run creates and starts a brand-new container. docker exec runs a command inside a container that is already running. If something is live and you want to look inside it, use exec; if you want a fresh container, use run.

Why does docker exec bash say executable not found?

The image does not include bash - many slim images ship only sh. Run docker exec -it <container> sh instead. It is not a sign the container is broken, just that bash was left out to keep the image small.

What do the -it flags mean in docker exec?

-i keeps stdin open so you can type, and -t allocates a pseudo-terminal so the shell behaves normally. Together they give you an interactive session. Use -i alone when piping input, and neither for a single fire-and-forget command in a script.

How do I run docker exec as root?

Add -u root: docker exec -it -u root <container> bash. Many images run as an unprivileged user, so you need root to install debugging tools or read protected files. Anything you change this way lasts only until the container is recreated.

#docker exec#docker#containers#debugging#dev-infra