660

I have a container that is running the Apache service in the foreground. I would like to be able to access the container from another shell in order to "poke around" inside it and examine the files. At the moment, if I attach to the container, I am left looking at the Apache daemon and cannot run any commands.

Is it possible to attach another tty to a running container? Possibly, I can take advantage of the fact that Docker is actually just wrapping around LXC containers? I have tried sudo lxc-console -n [container-id] -t [1-4] but it appears that only one tty is made available and that is the one running the apache daemon. Perhaps there is a way to enable multiple lxc consoles during the build?

I would rather not configure and build the container with an openssh service if possible.

Diogo Gomes
  • 152
  • 6
Programster
  • 12,242
  • 9
  • 49
  • 55
  • 8
    Did you try ```docker attach [conainer-id]``` ? – shabbychef Apr 01 '14 at 17:21
  • 15
    @shabbychef unless docker attach has changed, the attach command attaches to the running tty, not a new one, hence the question title is "...with new TTY". This is why the answer below does not use the attach command. – Programster Apr 01 '14 at 17:28
  • 1
    Since 1.3 there is an easier way as described on [this answer](http://stackoverflow.com/a/26496854/107049) – Thomasleveil Oct 22 '14 at 20:28

11 Answers11

1286

With docker 1.3, there is a new command docker exec. This allows you to enter a running container:

docker exec -it [container-id] bash

Note: this assumes bash is installed on your container. You may run sh or whatever interactive shell is installed on the container.

Michael_Scharf
  • 33,154
  • 22
  • 74
  • 95
  • 34
    I have changed this to be the correct answer (from my own) because this new method, which wasn't around at the time of the question, is the best current method IMO. – Programster Oct 29 '14 at 11:43
  • 3
    Notice however that `exec` doesn't act as a normal terminal. For example you can't change user once inside the container. – Pithikos Oct 29 '14 at 17:04
  • For docker 1.2 use [nsenter](https://github.com/jpetazzo/nsenter). On OS X and Windows you can follow the [nsenter instructions](https://github.com/jpetazzo/nsenter#docker-enter-with-boot2docker) – Michael_Scharf Feb 06 '15 at 14:01
  • 4
    @Pithikos: I'm able to use exec to run a shell and then `su someuser` to change user. Running Docker 1.4.1 – lsh Mar 02 '15 at 13:56
  • 2
    Note to anyone reading this discussion. I'm sure `docker exec -it` will eventually provide a fully-functional pseudo tty, but for now (Docker version 1.9.1), there are some shortcomings : https://github.com/docker/docker/issues/8755 – blong Jan 05 '16 at 03:11
  • 22
    if you get the error 'exec: "bash": executable file not found in $PATH' you can try this : docker exec -it [container-id] /bin/sh – Dai Kaixian Sep 12 '16 at 12:05
  • Provided in some cases bash is not sufficient we need to set PID1 as /bin/bash docker exec -it [container-id] /bin/bash – Alok Adhao Apr 05 '17 at 10:52
  • 2
    Here in Alpine, if container has a name defined: `docker exec -it NAME /bin/sh` – Junior Mayhé May 17 '17 at 20:08
  • The container name will also do the same. – Arefe Mar 15 '19 at 16:44
  • This doesn't work if the container is running in a swarm. I haven't found the way to do this yet... but would appreciate it if someone knows. Any suggestions, @Michael_Scharf ? It always says `Error: No such container: `, even if in the same/only node where the service exists and is running. – code_dredd Jan 16 '20 at 00:25
  • -it = --interactive + --tty? – Andrey Kurnikovs Jun 19 '21 at 11:51
42

You should use Jérôme Petazzoni's tool called 'nsenter' to enter a container without using SSH. See: https://github.com/jpetazzo/nsenter

Install with simply running: docker run -v /usr/local/bin:/target jpetazzo/nsenter

Then use the command docker-enter <container-id> to enter the container.

Hyperfocus
  • 773
  • 1
  • 7
  • 14
  • This is the right way. See [blog](http://jpetazzo.github.io/2014/06/23/docker-ssh-considered-evil/). – Jesse Glick Jul 18 '14 at 15:00
  • 6
    With docker 1.3, there is a new command [`docker exec`](https://docs.docker.com/reference/commandline/cli/#exec). This allows you to enter a running docker: `docker exec -it bash` (see my answer below) – Michael_Scharf Oct 24 '14 at 14:53
  • 6
    Does `docker-enter` still exist? It gives me `command not found`. – Snowcrash Oct 10 '16 at 20:14
22

Update

As of docker 0.9, for the steps below to now work, one now has to update the /etc/default/docker file with the '-e lxc' to the docker daemon startup option before restarting the daemon (I did this by rebooting the host).

update to the /etc/default/docker file

This is all because...

...it [docker 0.9] contains a new "engine driver" abstraction to make possible the use of other API than LXC to start containers. It also provide a new engine driver based on a new API library (libcontainer) which is able to handle Control Groups without using LXC tools. The main issue is that if you are relying on lxc-attach to perform actions on your container, like starting a shell inside the container, which is insanely useful for developpment environment...

source

Please note that this will prevent the new host only networking optional feature of docker 0.11 from "working" and you will only see the loopback interface. bug report


It turns out that the solution to a different question was also the solution to this one:

...you can use docker ps -notrunc to get the full lxc container ID and then use lxc-attach -n <container_id> run bash in that container as root.

Update: You will soon need to use ps --no-trunc instead of ps -notrunc which is being deprecated.

enter image description here Find the full container ID

enter image description here Enter the lxc attach command.

enter image description here Top shows my apache process running that docker started.

Community
  • 1
  • 1
Programster
  • 12,242
  • 9
  • 49
  • 55
  • So, there is no way to do this with just Docker, right? I personally prefer not to mix in LXC myself. – qkrijger Jan 06 '14 at 13:06
  • Is there any way to run a command with lxc-attach instead to launch the bash? thx!! – joselo Jan 21 '14 at 05:41
  • @qkrijger as far as I am aware that is correct. Why worried about "mixing" LXC? You realize that docker is built on top of LXC right? – Programster Jan 21 '14 at 08:26
  • @joselo I dont understand your question, but I suggest that you create a new post with more detail? There are many ways to start a docker process, such as with bash or as a daemon with -d etc. – Programster Jan 21 '14 at 08:27
  • @programster yes, I realize that :) Still, using LXC directly in combination with Docker feels like hacking. Fun, but not really maintainable. In general, one should code in the abstraction layer that one chose to work in. If you really need LXC itself, it might be time for a pull request on Docker :) – qkrijger Jan 21 '14 at 22:46
  • @Programster If I use lxc-attach it launch a new bash console but what I want is just run a command directly something like lxc-attach -n xxxx -- echo "test" – joselo Jan 21 '14 at 23:47
  • @joselo I think your thinking of lxc-execute http://lxc.sourceforge.net/man/lxc-execute.html – Programster Jan 22 '14 at 10:05
  • Or you can keep libcontainer and use nsinit :). `go install github.com/dotcloud/docker/pkg/libcontainer/nsinit/nsinit; cd /var/lib/docker/containers/; nsinit exec ` – creack May 08 '14 at 21:16
9

First step get container id:

docker ps

This will show you something like

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

1170fe9e9460 localhost:5000/python:env-7e847468c4d73a0f35e9c5164046ad88 "./run_notebook.sh" 26 seconds ago Up 25 seconds 0.0.0.0:8989->9999/tcp SLURM_TASK-303337_0

1170fe9e9460 is the container id in this case.

Second, enter the docker :

docker exec -it [container_id] bash

so in the above case: docker exec -it 1170fe9e9460 bash

patapouf_ai
  • 17,605
  • 13
  • 92
  • 132
9
docker exec -ti 'CONTAINER_NAME' sh

or

docker exec -ti 'CONTAINER_ID' sh
Paul Wintz
  • 2,542
  • 1
  • 19
  • 33
Flavio
  • 506
  • 4
  • 9
7

What about running tmux/GNU Screen within the container? Seems the smoother way to access as many vty as you want with a simple:

$ docker attach {container id}
hexacyanide
  • 88,222
  • 31
  • 159
  • 162
solr
  • 1,092
  • 1
  • 10
  • 14
  • This is an ok solution if you know that you will want to get access to a container (for example to debug it), but this would not help OP who states that they want to look around an existing container. – Luca Spiller Aug 01 '14 at 10:53
  • 1
    My issue with this answer is that people have already asked about using `docker attach` and I pointed out that: `...the attach command attaches to the running tty, not a new one, hence the question title is "...with new TTY"` – Programster Aug 06 '14 at 14:11
  • Well, if the container is already running this solution won't help you but if you previously take care of leaving a multiplexer running you won't have any need for additional ttys... In fact since I started using tmux I use one tty and only one to do everything I need since once into tmux I can spawn as much vtys as I want. – solr Aug 06 '14 at 20:23
4

nsenter does that. However I also needed to enter a container in a simple way and nsenter didn't suffice for my needs. It was buggy in some occasions (black screen plus -wd flag not working). Furthermore I wanted to login as a specific user and in a specific directory.

I ended up making my own tool to enter containers. You can find it at: https://github.com/Pithikos/docker-enter

Its usage is as easy as

./docker-enter [-u <user>] [-d <directory>] <container ID>
Pithikos
  • 18,827
  • 15
  • 113
  • 136
  • Just tried, very cool! On ubuntu had to run sudo apt-get build-essential -y gcc docker-enter.c -o docker-enter sudo ./docker-enter Nice that I dont have to get the full ID like with lxc-attach -n Codebase is short enough that one can scan the entirety quickly to look for anything malicious. – Programster Sep 02 '14 at 09:07
  • I made an ebuild available on gentoo at https://github.com/steveeJ/personal-portage-overlay as app-emulation/docker-enter. – stefanjunker Sep 03 '14 at 17:10
  • I have added a tutorial/script for automatic this for ubuntu users at http://programster.blogspot.co.uk/2014/01/docker-enter-running-container.html – Programster Oct 01 '14 at 09:36
3
docker exec -t -i container_name /bin/bash

Will take you to the containers console.

Danstan
  • 1,501
  • 1
  • 13
  • 20
  • I landed on this question because I had the same problem. The answer that seems similar didn't work for me until I modified. I can delete this though. – Danstan Jun 26 '18 at 13:17
2

The "nsinit" way is:

install nsinit

git clone git@github.com:dotcloud/docker.git
cd docker
make shell

from inside the container:

go install github.com/dotcloud/docker/pkg/libcontainer/nsinit/nsinit

from outside:

docker cp id_docker_container:/go/bin/nsinit /root/

use it

cd /var/lib/docker/execdriver/native/<container_id>/
nsinit exec bash
kynan
  • 13,235
  • 6
  • 79
  • 81
Ivailo Bardarov
  • 3,775
  • 1
  • 28
  • 25
1

I started powershell on a running microsoft/iis run as daemon using

docker exec -it <nameOfContainer> powershell
Ahmed Samir
  • 117
  • 4
  • Looks as if the question was about a linux-based container. This answer will probably work only if you have a windows-based container -or- if you have the .NET Core version of PowerShell installed, e.g. PowerShell 6 or later. – Manfred Nov 03 '19 at 20:14
0

On Windows 10, I have docker installed. I am running Jnekins on a container and I encountered the same error message. Here is a step by step guide to resolve this issue:

Step 1: Open gitbash and run docker run -p 8080:8080 -p 50000:50000 jenkins.

Step 2: Open a new terminal.

Step 3: Do "docker ps" to get list of the running container. Copy the container id.

Step 4: Now if you do "docker exec -it {container id} sh" or "docker exec -it {container id} bash" you will get an error message similar to " the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'"

Step 5: Run command " $winpty docker exec -it {container id} sh"

vola !! You are now inside the terminal.

Pang
  • 9,564
  • 146
  • 81
  • 122
Dev 00721
  • 1
  • 1