2492

I'm trying to SSH into one of my Docker containers running the WordPress base image to inspect the files/directories that were created during the initial build.

I tried to run docker-compose run containername ls -la, but that didn't do anything.

Even if it did, I'd rather have a console where I can traverse the directory structure, rather than run a single command.

Is something like this possible with Docker, and if so, how?

8
  • So it sounds like the answer is docker attach. But how can I get to that from docker-compose? Commented May 11, 2015 at 16:27
  • 9
    Use docker exec askubuntu.com/a/543057/35816 . Get the container id using docker ps Commented May 11, 2015 at 16:45
  • 69
    sudo docker run -it --entrypoint /bin/bash <container_name> gets you into the container interactively. Then one can inspect the file system in the container using cd <path> Commented May 25, 2017 at 16:44
  • 10
    @Sergei That's incorrect, docker run takes an image name, not a container ID. I was confused about running containers for a long time which is why I ended up writing blog.andrewray.me/towards-a-strong-mental-model-of-docker Commented Dec 29, 2020 at 18:21
  • 1
    @AndyRay blog.andrewray.me/towards-a-strong-mental-model-of-docker is a broken link, do you have a new link for it? Commented Nov 10, 2022 at 23:17

32 Answers 32

3378

docker attach will let you connect to your Docker container, but this isn't really the same thing as ssh. If your container is running a webserver, for example, docker attach will probably connect you to the stdout of the web server process. It won't necessarily give you a shell.

The docker exec command is probably what you are looking for; this will let you run arbitrary commands inside an existing container. For example, to run bash inside a container:

docker exec -it <mycontainer> sh

Of course, whatever command you are running must exist in the container filesystem; if your container doesn't have sh, this will fail with something like:

OCI runtime exec failed: exec failed: unable to start container process:
exec: "sh": executable file not found in $PATH: unknown

[If your container doesn't have sh -- which is a common case for minimal images -- you may need to investigate other ways to explore the container filesystem.]

In the above command <mycontainer> is the name or ID of the target container. It doesn't matter whether or not you're using docker compose; just run docker ps and use either the ID (a hexadecimal string displayed in the first column) or the name (displayed in the final column). E.g., given:

$ docker ps
d2d4a89aaee9        larsks/mini-httpd   "mini_httpd -d /cont   7 days ago          Up 7 days                               web                 

I can run:

$ docker exec -it web ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
18: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:3/64 scope link 
       valid_lft forever preferred_lft forever

I could accomplish the same thing by running:

$ docker exec -it d2d4a89aaee9 ip addr

Similarly, I could start a shell in the container;

$ docker exec -it web sh
/ # echo This is inside the container.
This is inside the container.
/ # exit
$

In commands shown in this answer, the -i and -t options (combined as -it) are necessary to get an interactive shell:

  • -i keeps stdin connected; if you don't specify -i, the shell will simply exit.

  • -t allocates a tty device; if you don't specify -t, you won't have a very pleasant interactive experience (there will be no shell prompt or job control, for example).


If you're specifically using docker compose, there is a convenience docker compose exec command that works very much like the docker exec command, except:

  • It defaults to the behavior of -i and -t
  • It allows you to refer to containers by their service name in your compose.yaml file.

For example, if you have a compose.yaml like this:

services:
  web:
    image: docker.io/alpinelinux/darkhttpd

Then you can run:

docker compose exec web sh

The equivalent docker exec command would be something like:

docker exec -it myproject-web-1 sh
Sign up to request clarification or add additional context in comments.

17 Comments

Also, docker exec only works on running containers (otherwise use docker run -it --entrypoint /bin/bash or similar).
for your convenience, -it is a combination of -i and -t which is --interactive ("Keep STDIN open even if not attached") respectively --tty (" Allocate a pseudo-TTY").
On Alpine Linux based containers you might not have bash, so if so, use sh instead.
@L0j1k it is docker run -it --entrypoint /bin/bash <imageid> --any --more --args, just to clarify for people
@AlexanderMills Yes, and to clarify further, those --any --more --args you have will be fed into whatever the image has defined as its CMD and not Docker (or if your image only defines an ENTRYPOINT and no CMD, then these options will be fed into /bin/bash as you've specified here). So for example any other docker run options (e.g. --net "host") need to go before the <imageid>.
|
547

To bash into a running container, type this:

docker exec -t -i container_name /bin/bash

or

docker exec -ti container_name /bin/bash

or

docker exec -ti container_name sh

11 Comments

Presuming it is a Linux container?
/bin/bash wasnt required just bash did it for me
I would prefer docker exec -it instead of docker exec -t -i
@nakamin According to the docs, adding the -u or --user flag will allow you to specify the user. docs.docker.com/engine/reference/commandline/exec
just bash will work out instead on /bin/bash
|
133

Historical note: At the time I wrote this answer, the title of the question was: "How to ssh into a docker container?"

As other answers have demonstrated, it is common to execute and interact with preinstalled commands (including shells) in a locally-accessible running container using docker exec, rather than SSH:

docker exec -it (container) (command)

Note: The below answer is based on Ubuntu (of 2016). Some translation of the installation process will be required for non-Debian containers.

Let's say, for reasons that are your own, you really do want to use SSH. It takes a few steps, but it can be done. Here are the commands that you would run inside the container to set it up...

apt-get update
apt-get install openssh-server

mkdir /var/run/sshd
chmod 0755 /var/run/sshd
/usr/sbin/sshd

useradd --create-home --shell /bin/bash --groups sudo username ## includes 'sudo'
passwd username ## Enter a password

apt-get install x11-apps ## X11 demo applications (optional)
ifconfig | awk '/inet addr/{print substr($2,6)}' ## Display IP address (optional)

Now you can even run graphical applications (if they are installed in the container) using X11 forwarding to the SSH client:

ssh -X username@IPADDRESS
xeyes ## run an X11 demo app in the client

Here are some related resources:

2 Comments

At the time I wrote this answer, the title of the question was: "How to ssh into a docker container?" Over the years, the question and answers have been edited by interlopers and bots -- in some cases, possibly changing the intent. My previous comment to this effect was anonymously deleted.
94

If the container has already exited (maybe due to some error), you can do:

$ docker run --rm -it --entrypoint /bin/bash image_name

or

$ docker run --rm -it --entrypoint /bin/sh image_name

to create a new container and get a shell into it.

Here is the breakdown of the command:

--rm: This option specifies that the container should be automatically removed when it is finished.

-it: These options allow the container to be run interactively with a pseudo-tty terminal. The -i option stands for interactive mode and the -t option stands for a pseudo-tty terminal.

--entrypoint /bin/bash: This option specifies the entry point for the container as /bin/bash, which is the shell program.

image_name: This is the name of the Docker image on which the container will be based.

Since you specified --rm, the container would be deleted when you exit the shell.

Comments

56

If you're here looking for a Docker Compose-specific answer like I was, it provides an easy way in without having to look up the generated container ID.

docker-compose exec takes the name of the service as per your docker-compose.yml file.

So to get a Bash shell for your 'web' service, you can do:

$ docker-compose exec web bash

1 Comment

docker-compose run works as well, if your container doesn't exist yet.
37

Use exec with sh as a short-form:

docker exec -it <CONTAINER_ID or CONTAINER_NAME> sh

You can find CONTAINER_ID (1st column) or CONTAINER_NAME (last column) by performing docker ps & get output that looks like:

CONTAINER ID   IMAGE                 COMMAND                  CREATED       STATUS                 PORTS                                       NAMES
8e5611ba2567   nextjs:0.0.1   "docker-entrypoint.s…"   3 hours ago   Up 3 hours             0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   web
f3967286c492   redis:7.2.4    "docker-entrypoint.s…"   3 hours ago   Up 3 hours (healthy)   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   web_redis

For nextjs:0.0.1, CONTAINER_ID is 8e5611ba2567 & CONTAINER_NAME is web. To get into web container, type:

docker exec -it 8e5611ba2567 sh
# or docker exec -it web sh (both are same)

For redis:7.2.4, CONTAINER_ID is f3967286c492 & CONTAINER_NAME is web_redis. To get into web_redis container, type:

docker exec -it f3967286c492 sh
# or docker exec -it web_redis sh (both are same)

Comments

33

Start a session into a Docker container using this command:

sudo docker exec -i -t (container ID) bash

2 Comments

or a little shorter: sudo docker exec -it <container ID> bash
or even shorter docker exec -it <container-id> sh :)
30

Notice: this answer promotes a tool I've written.

I've created a containerized SSH server that you can 'stick' to any running container. This way you can create compositions with every container. The only requirement is that the container has Bash.

The following example would start an SSH server attached to a container with name 'my-container'.

docker run -d -p 2222:22 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e CONTAINER=my-container -e AUTH_MECHANISM=noAuth \
  jeroenpeeters/docker-ssh

ssh localhost -p 2222

When you connect to this SSH service (with your SSH client of choice) a Bash session will be started in the container with name 'my-container'.

For more pointers and documentation see: https://github.com/jeroenpeeters/docker-ssh

3 Comments

That's pretty sweet. The big advantage of doing it this way is you're getting a fully functional terminal. When I used the "docker exec" approach then I couldn't clear the terminal content, less was showing a warning each time I run it etc. Using Jeroen's container is giving me a much better experience so far. Just make sure to check out the documentation. The sample command in the response doesn't seem valid any more.
it is a great tool. Do you know how can i use it as a jenkins pipeline docker agent? i Want jenkins to transfer some files by SCP to a remote host and execute them with SSH
Docker On Windows : docker run -d -p 2222:22 -v //var/run/docker.sock:/var/run/docker.sock -e CONTAINER=my-container -e AUTH_MECHANISM=noAuth --name node-manager jeroenpeeters/docker-ssh
27

If you're using Docker on Windows and want to get shell access to a container, use this:

winpty docker exec -it <container_id> sh

Most likely, you already have Git Bash installed. If you don't, make sure to install it.

1 Comment

Presumes a Linux Docker container?
27

In some cases your image can be Alpine-based. In this case it will throw:

OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown

Because /bin/bash doesn't exist. Instead of this you should use:

docker exec -it 9f7d99aa6625 ash

or

docker exec -it 9f7d99aa6625 sh

Comments

20

To connect to cmd in a Windows container, use

docker exec -it d8c25fde2769 cmd

Where d8c25fde2769 is the container id.

Comments

16

GOINSIDE SOLUTION

install goinside command line tool with:

sudo npm install -g goinside

and go inside a docker container with a proper terminal size with:

goinside docker_container_name

old answer

We've put this snippet in ~/.profile:

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside

Not only does this make everyone able to get inside a running container with:

goinside containername

It also solves a long lived problem about fixed Docker container terminal sizes. Which is very annoying if you face it.

Also if you follow the link you'll have command completion for your docker container names too.

1 Comment

Thanks. It works like a charm, at least for those images which have bash already included. Might not work for alpine based images, however, can be fixed with a different function specifically written for sh/ash etc.
16

To inspect files, run docker run -it <image> /bin/sh to get an interactive terminal. The list of images can be obtained by docker images. In contrary to docker exec this solution works also in case when an image doesn't start (or quits immediately after running).

1 Comment

Presuming a Linux Docker image?
16

2022 Solution

Consider another option

Why do you need it?

There is a bunch of modern docker-images that are based on distroless base images (they don't have /bin/bash either /bin/sh) so it becomes impossible to docker exec -it {container-name} bash into them.

How to shell-in any container

Use opener:

  • requires to add alias in your environment opener wordpress
  • works anywhere docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock artemkaxboy/opener wordpress

Instead of wordpress you can use name or id or image-name of any container you want to connect


How it works

Opener is a set of python scripts wrapped-up to a docker image. It finds target container by any unique attribute (name, id, port, image), tries to connect to target using bash. If bash is not found opener tries to connect using sh. Finally if sh is not found either opener installs busybox into target container and connects to the target using busybox shell, opener deletes busybox during disconnection.

2 Comments

That is very cool, I tried this and it works great. I love how simple the scripts are that it runs. I never would have thought to try installing busybox in order to get a shell environment working in a docker container.
Love how simple this is. Shell alias set, so this it the last time I'll have to go looking for help on this. Thank you for the tool!
14

It is simple!

List out all your Docker images:

sudo docker images

On my system it showed the following output:

REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
bash                latest              922b9cc3ea5e        9 hours ago
14.03 MB
ubuntu              latest              7feff7652c69        5 weeks ago         81.15 MB

I have two Docker images on my PC. Let's say I want to run the first one.

sudo docker run -i -t ubuntu:latest /bin/bash

This will give you terminal control of the container. Now you can do all type of shell operations inside the container. Like doing ls will output all folders in the root of the file system.

bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

Comments

12

I've created a terminal function for easier access to the container's terminal. Maybe it's useful to you guys as well:

So the result is, instead of typing:

docker exec -it [container_id] /bin/bash

you'll write:

dbash [container_id]

Put the following in your ~/.bash_profile (or whatever else that works for you), then open a new terminal window and enjoy the shortcut:

#usage: dbash [container_id]
dbash() {
    docker exec -it "$1" /bin/bash
}

Comments

11
$ docker exec -it <Container-Id> /bin/bash

Or depending on the shell, it can be

$ docker exec -it <Container-Id> /bin/sh

You can get the container-Id via docker ps command

-i = interactive

-t = to allocate a psuedo-TTY

Comments

9

There are at least 2 options depending on the target.

Option 1: Create a new bash process and join into it (easier)

  • Sample start: docker exec -it <containername> /bin/bash
  • Quit: type exit
  • Pro: Does work on all containers (not depending on CMD/Entrypoint)
  • Contra: Creates a new process with own session and own environment-vars

Option 2: Attach to the already running bash (better)

  • Sample start: docker attach --detach-keys ctrl-d <containername>
  • Quit: use keys ctrl and d
  • Pro: Joins the exact same running bash which is in the container. You have same the session and same environment-vars.
  • Contra: Only works if CMD/Entrypoint is an interactive bash like CMD ["/bin/bash"] or CMD ["/bin/bash", "--init-file", "myfile.sh"] AND if container has been started with interactive options like docker run -itd <image> (-i=interactive, -t=tty and -d=deamon [opt])

We found option 2 more useful. For example we changed apache2-foreground to a normal background apache2 and started a bash after that.

Comments

8

you can interact with the terminal in docker container by passing the option -ti

docker run --rm -ti <image-name>
eg: docker run --rm -ti ubuntu

-t stands for terminal -i stands for interactive

Comments

8

To exec into a running container named test, below is the following commands

If the container has bash shell

docker exec -it test /bin/bash

If the container has bourne shell and most of the cases it's present

docker run -it test /bin/sh

Comments

7

docker exec will definitely be a solution. An easy way to work with the question you asked is by mounting the directory inside Docker to the local system's directory.

So that you can view the changes in local path instantly.

docker run -v /Users/<path>:/<container path> 

2 Comments

your command is actually mounting the host's directory into the container.
Yeah! Take a backup to another directory and then mount the volume, then move the backup to the mounted folder.
7

Use:

docker attach <container name/id here>

The other way, albeit there is a danger to it, is to use attach, but if you Ctrl + C to exit the session, you will also stop the container. If you just want to see what is happening, use docker logs -f.

:~$ docker attach --help
Usage:  docker attach [OPTIONS] CONTAINER

Attach to a running container

Options:
      --detach-keys string   Override the key sequence for detaching a container
      --help                 Print usage
      --no-stdin             Do not attach STDIN
      --sig-proxy            Proxy all received signals to the process (default true)

Comments

7

Use this command:

docker exec -it containerid /bin/bash

Comments

7

This is best if you don't want to specify an entry point in your docker build file..

sudo docker run -it --entrypoint /bin/bash <image_name>

1 Comment

Shouldn't it be <image_name> instead of <container_name>?
4

If you have Docker installed with Kitematic, you can use the GUI. Open Kitematic from the Docker icon and in the Kitematic window select your container, and then click on the exec icon.

You can see the container log and lots of container information (in settings tab) in this GUI too.

Select Kitematic from menu

Click on exec

Comments

4

There now is an official docker command for this:

docker debug <container or image>

It allows you to get a shell (bash/fish/zsh) into any container. It also works for stopped containers and images. Essentially it's a replacement of docker exec -it <container> sh but with more features and less constraints (eg the debug shell has an install command to add further tools). Using docker debug does not modify your container/image (unless you explicitly do so, and only possible for running containers)

See official docs for more details and examples.

Disclaimer: As of now, this is a paid feature and requires Docker Desktop >= 4.27. Ie., if you want to do this with docker-ce, docker exec -it <container> sh still is the valid answer.

5 Comments

docker: 'debug' is not a docker command.
Are you using docker desktop version 4.27 or higher? As mentioned in the disclaimer and in the referenced docs page, docker debug is a new command available as of docker desktop 4.27.
Understood, thank you! I am using Rancher Desktop 1.12.3 with docker as a backend Client - Version: 24.0.7-rd (output of docker version command )
That feature is paywalled: "Docker Debug requires a Pro, Teams, or Business Subcription."
As of Docker Desktop 4.49, the docker debug command is free to all users: docs.docker.com/desktop/release-notes/#4490
3

There are two options we can connect to the docker terminal directly with these method shell and bash but usually bash is not supported and defualt sh is supported terminal To sh into the running container, type this:

docker exec -it container_name/container_ID sh

To bash into a running container, type this:

docker exec -it container_name/container_ID bash

and you want to use only bash terminal than you can install the bash terminal in your Dockerfile like RUN apt install bash -y

Comments

3

There is one more method I currently utilize, but I've been exploring a more user-friendly alternative.

With the Windows Docker Desktop GUI, there's a feature that not only lets you open a direct shell on a container but also opens that shell in an external terminal. Essentially, it creates an instance of your selected terminal, and every command thereafter automatically utilizes 'docker exec -it ' without the need for manual input each time. Docker Desktop

1 Comment

Just remember that Docker Desktop shouldn't be used for commercial purposes without a license, just for personal use. See docs.docker.com/subscription/desktop-license . There are exceptions though, as for January, 2025 -> "Docker Desktop is free for small businesses (fewer than 250 employees AND less than $10 million in annual revenue), personal use, education, and non-commercial open source projects."
2

If you are using Docker Compose then this will take you inside a Docker container.

docker-compose run container_name /bin/bash

Inside the container it will take you to WORKDIR defined in the Dockerfile. You can change your work directory by

WORKDIR directory_path # E.g  /usr/src -> container's path

Comments

2

In my case, for some reason(s) I need to check all the network involved information in each container. So the following commands must be valid in a container...

ip
route
netstat
ps
...

I checked through all these answers, none were helpful for me. I’ve searched information in other websites. I won’t add a super link here, since it’s not written in English. So I just put up this post with a summary solution for people who have the same requirements as me.

Say you have one running container named light-test. Follow the steps below.

  • docker inspect light-test -f {{.NetworkSettings.SandboxKey}}. This command will get reply like /var/run/docker/netns/xxxx.
  • Then ln -s /var/run/docker/netns/xxxx /var/run/netns/xxxx. The directory may not exist, do mkdir /var/run/netns first.
  • Now you may execute ip netns exec xxxx ip addr show to explore network world in container.

PS. xxxx is always the same value received from the first command. And of course, any other commands are valid, i.e. ip netns exec xxxx netstat -antp|grep 8080.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.