Sometimes you need interactive access to a running Docker container from your local machine to troubleshoot an issue, inspect files, or run a one-off command. Docker does not enable SSH access by default, and most of the time you do not need it. The Docker-native approach is the docker exec command, and there are a few other options depending on what you are trying to do.
Quick answer, fastest ways to get inside
If you want the command and nothing else, start here.
# List running containers (docker ps command)
docker ps
# Start a shell inside a running container (try sh first for lightweight images)
docker exec -it <container_name_or_id> sh
# If bash exists
docker exec -it <container_name_or_id> bash
# Run a command in a specific working directory
docker exec -it -w /app <container_name_or_id> sh -lc "pwd && ls"
# Run a command with environment variables set for that exec process only
docker exec -it -e APP_ENV=dev -e LOG_LEVEL=debug <container_name_or_id> sh -lc "env | grep -E 'APP_ENV|LOG_LEVEL'"
# If you are using Docker Compose, exec into a single service
docker compose exec <service_name> sh
# If your container has no shell or tools, use Docker Debug
docker debug <container_name_or_id>Why access a Docker container?
- Debugging and troubleshooting running applications.
- Inspecting logs, files, and configuration inside the containerized environment.
- Running administrative or diagnostic tasks inside the container.
- Validating environment variables, working directory, and filesystem state.
Docker basics that matter for this guide
- Dockerfile: a build recipe that defines how an image is created.
- Docker images: the packaged filesystem and metadata you run as containers.
- docker run command: starts a new container from an image.
- docker exec command: runs a new process inside an existing running container.
Before you start, a quick OS and daemon note
On Linux, the docker command is a client that talks to the Docker daemon (dockerd). The daemon is the long-running service (a daemon) that actually starts containers and manages images. On macOS and Windows, Docker Desktop runs the daemon in a lightweight VM, but your CLI workflow stays similar on your local machine.
If you run into docker: command not found, confirm the command exists and the daemon is reachable:
command -v docker
docker version
docker infoMethods to access a Docker container
1. Using docker exec (recommended)
The docker exec command starts a new process inside an already running container. This is the cleanest way to open a shell or run a one-off command without enabling SSH protocol access into the container.
Interactive shell examples:
docker exec -it <container> sh
docker exec -it <container> bashRun a single command, then exit:
docker exec <container> ls -la
docker exec -it -w /app <container> sh -lc "pwd && ls"Environment variables and echo, useful for debugging:
# Print an environment variable that already exists in the container
docker exec -it <container> sh -lc "echo $PATH"
# Set environment variables for this exec process only, then echo them
docker exec -it -e STAGE=dev -e FEATURE_FLAG=1 <container> sh -lc "echo $STAGE && echo $FEATURE_FLAG"Tip: Many production containers are intentionally lightweight and may not include bash. Try sh first.
2. Using docker compose exec for a single service
If your app runs as multiple containers, you often want to exec into a single service managed by Compose. This keeps you from guessing container IDs and aligns with how the stack is defined.
docker compose ps
docker compose exec <service_name> sh
docker compose exec -w /app <service_name> sh -lc "pwd && ls"3. Using docker run for a one-off shell (image-level access)
The docker run command creates a brand-new container from a Docker image. This is helpful when the container you want to inspect keeps crashing, or you want a clean environment with the same image on your local machine.
# Start a temporary container and drop into a shell, remove it on exit
docker run --rm -it <image> sh
# Set the working directory at start
docker run --rm -it -w /app <image> sh
# Pass environment variables at runtime
docker run --rm -it -e APP_ENV=dev -e LOG_LEVEL=debug <image> sh
# Load environment variables from a file
docker run --rm -it --env-file .env <image> shTip: If an image sets an entrypoint that blocks your shell, override it:
docker run --rm -it --entrypoint sh <image>4. Using docker attach (attach to the main process)
docker attach connects your terminal to the container’s main process (often PID 1). This can help for certain interactive processes, but it is easy to misuse for troubleshooting because you are not starting a new shell.
docker attach <container>- It attaches to the primary process, not a new shell.
- To detach without stopping the container, use Ctrl+P then Ctrl+Q.
- You can override detach keys with
--detach-keysif needed.
5. Using docker debug (best for minimal images)
Many production images are slim and intentionally omit shells and tools. docker debug is designed for this scenario and can give you a practical debugging environment even when docker exec does not.
docker debug <container>6. SSH into a container running an SSH daemon (use cautiously)
SSH uses the SSH protocol and provides encryption by default. To allow SSH access into a container, you must run an SSH daemon (typically sshd) inside the container and expose port 22. This increases your attack surface and operational overhead, so a safer default is SSH into the Linux host, then use docker exec locally.
Example approach
This example uses a non-root user and key-based auth. In real environments, avoid baking keys into images. Prefer mounting authorized keys at runtime or using secrets management.
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y openssh-server \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m -s /bin/bash appuser \
&& mkdir -p /var/run/sshd /home/appuser/.ssh \
&& chmod 700 /home/appuser/.ssh \
&& chown -R appuser:appuser /home/appuser/.ssh
RUN printf "PasswordAuthentication no\nPermitRootLogin no\n" >> /etc/ssh/sshd_config
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D", "-e"]Build and run, mapping container port 22 to host port 2222:
docker build -t ssh-container .
docker run -d \
-p 2222:22 \
--name ssh-container \
ssh-containerMount keys at runtime:
docker run -d \
-p 2222:22 \
--name ssh-container \
-v ./authorized_keys:/home/appuser/.ssh/authorized_keys:ro \
ssh-containerConnect from the host:
ssh -p 2222 appuser@localhostSecurity and capabilities: what to avoid, what to prefer
- Prefer
docker execover SSH access unless you have a true network requirement. - Avoid
--privilegedunless you fully understand the impact. - Drop unnecessary Linux capabilities and only add what you need.
# Example: drop all capabilities, then add back only what is required
docker run --rm -it --cap-drop=ALL --cap-add=NET_BIND_SERVICE <image> shBest practices for secure container access
- Prefer the docker exec command for interactive access, it avoids adding an SSH daemon.
- If you do enable SSH protocol access, use keys, disable password auth, avoid root login, and restrict exposed ports.
- Keep images lightweight, and use
docker debugwhen typical Linux tools are missing. - Use runtime environment variables for configuration, avoid baking secrets into Docker images.
- Be explicit about working directory and environment variables when debugging, then validate with
pwd,env, andecho.
Frequently Asked Questions
What is the fastest way to get a shell in a running container?
Use the docker exec command. First find the container with the docker ps command, then exec into it with sh or bash.
docker ps
docker exec -it <container> sh
How to SSH in a Docker container?
Say you've finished your Docker course, but you still need to know how to SSH into a Docker container. The container must be running an SSH daemon (sshd) and exposing port 22 internally, then you publish that port to the host (for example, -p 2222:22) and connect using the SSH protocol.
ssh -p 2222 appuser@localhost
In many cases, a better option is direct shell access without SSH:
docker exec -it container_name sh
What is the difference between docker exec and docker run?
The docker exec command runs a new command inside an existing running container. The docker run command creates a new container from a Docker image and starts it. Use exec to troubleshoot a live container, use run for one-off inspection or when the target container cannot stay running.
How do I exec into a single service in Docker Compose?
Use docker compose exec with the service name. This is the easiest way to access a single service in a multi-container app.
docker compose exec <service_name> sh
How do I set the working directory when I exec into a container?
Use -w (or --workdir) to run the command from a specific directory.
docker exec -it -w /app container_name sh
To confirm where you are:
docker exec -it -w /app container_name sh -lc "pwd && ls"
How do I pass or inspect environment variables in a container?
At runtime, use docker run -e or --env-file. For a one-off exec process, you can pass variables with docker exec -e. To check values, use env, printenv, or echo.
docker run --rm -it -e APP_ENV=dev --env-file .env image sh
docker exec -it -e FEATURE_FLAG=1 container_name sh -lc "echo $FEATURE_FLAG"
Why does docker exec fail on some containers?
Often the image is minimal or lightweight and does not include bash or even sh. Try sh first, and if there is no shell or tooling, use docker debug to troubleshoot without rebuilding the image.
docker exec -it container_name sh
docker debug container_name
What are Linux capabilities in Docker, and why do they matter?
Capabilities are a Linux OS feature that breaks root privileges into smaller units. Containers can run with fewer capabilities to reduce risk. Prefer dropping capabilities you do not need, and avoid --privileged unless you have a specific reason.
docker run --rm -it --cap-drop=ALL --cap-add=NET_BIND_SERVICE <image> sh
Do I need the container IP address to connect with SSH?
If you publish the port with -p 2222:22, you usually connect to the host on that port from your local machine. Container IP addresses can change and differ across Docker networks and OS setups.
Key takeaways
- Use the docker exec command for direct access to a running container.
- Use the docker run command when you need a clean temporary container from Docker images.
- Use
docker compose execto access a single service cleanly. - If you enable SSH access, you are running an SSH daemon in the container and exposing ports, treat it as an exception.
- Reduce risk by limiting privileges and managing Linux capabilities deliberately.
- Be explicit about working directory and environment variables, then validate with
pwd,env, andecho.
Wrapping up
Accessing a running Docker container is usually best done with the docker exec command. When you need a fresh environment, the docker run command is often the right tool. SSH protocol access can work and provides encryption, but it should be used carefully and only when a network requirement makes it necessary. The more you lean on Docker-native workflows, the less you have to maintain inside the container.