difference between docker attach and docker exec - docker
Both will be able to execute commands in container.
Both could detach the container.
So what is the real difference between docker exec and docker attach?
2015: There was a commit PR which added to the doc:
Note: This command (attach) is not for running a new process in a container.
See: docker exec.
The answer to "Docker. How to get bash\ssh inside runned container (run -d)?" illustrates the difference:
(docker >= 1.3) If we use docker attach, we can use only one instance of shell.
So if we want to open new terminal with new instance of container's shell, we just need to run docker exec
if the docker container was started using /bin/bash command, you can access it using attach, if not then you need to execute the command to create a bash instance inside the container using exec.
As mentioned in this issue:
Attach isn't for running an extra thing in a container, it's for attaching to the running process.
"docker exec" is specifically for running new things in a already started container, be it a shell or some other process.
The same issue adds:
While attach is not well named, particularly because of the LXC command lxc-attach (which is more akin docker exec <container> /bin/sh, but LXC specific), it does have a specific purpose of literally attaching you to the process Docker started.
Depending on what the process is the behavior may be different, for instance attaching to /bin/bash will give you a shell, but attaching to redis-server will be like you'd just started redis directly without daemonizing.
Update 2022: See more with "Containers 101: attach vs. exec - what's the difference?" (Dec. 2021) from Ivan Velichko:
Extract:
Difference between attach and logs
On the diagram above, docker attach streams the container's logs back to the terminal.
However, the docker logs command does a similar thing.
So, what's the difference?
The logs command provides various options to filter the logs while attach in that regard acts as a simple tail.
But what's even more important is that the stream established by the logs command is always unidirectional and connected to the container's logs, not the container's stdio streams directly.
The logs command simply streams the content of the container's logs back to your terminal, and that's it.
So, regardless of how you created your container (interactive or non-interactive, controlled by a pseudo-terminal or not), you cannot accidentally impact the container while using the logs command.
However, when attach is used:
If a container was created in the interactive mode (-i), everything you type in the terminal after attach-ing to the container will be sent to its stdin.
You can (intentionally or accidentally) send a signal to the container - for instance, hitting ctrl+c on your end while attached sends SIGINT to the container.
What does exec command do
The exec command is actually a totally different story.
In the case of attach, we were connecting our terminal to an existing container (read, process).
However, the exec command starts a totally new container!
In other words, exec is a form of the run command (which itself is just a shortcut for create + start).
Bart reminds us in the comments that docker exec runs a new command in a running container. Not a "totally new one".
When a container is started using /bin/bash then it becomes the containers PID 1 and docker attach is used to get inside PID 1 of a container. So docker attach < container-id > will take you inside the bash terminal as it's PID 1 as we mentioned while starting the container. Exiting out from the container will stop the container.
Whereas in docker exec command you can specify which shell you want to enter into. It will not take you to PID 1 of the container. It will create a new process for bash.
docker exec -it < container-id > bash.
Exiting out from the container will not stop the container.
You can also use nsenter to enter inside containers.
nsenter -m -u -n -p -i -t < pid of container >
You can find PID of container using: docker inspect < container-id > | grep PID
Note: If you have started your container with -d flag then exiting out of container will not stop the container,whether you use attach or exec to get inside.
As Michael Sun stated in his answer
docker exec executes a new command / create a new process in the container’s environment, while docker attach just connects the standard input/output/error of the main process(with PID 1) inside the container to corresponding standard input/output/error of current terminal(the terminal you are using to run the command).
My answer will focus more on letting you validate the above statement and understand it more clearly.
Open up a terminal window and run the command docker run -itd --name busybox busybox /bin/sh. The command will pull the image busybox if not already present. It will then create a container with the name busybox using this image.
You can check the status of your container by running the command docker ps -a | grep busybox.
If you run docker top busybox, you should see an output something like this.
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
Of course, the PID, PPID and other values will be different in your case. You can use other tools and utilities as well like pstree, top, htop to see the list of PID and PPID.
The PID and PPID means the process id and parent process id. The process started when we created and started our container with the command /bin/sh. Now, run the command docker attach busybox. This will attach the standard input/output/error stream of the container to your terminal.
After attaching the container, create a shell session by running the command sh. Press CTRL-p CTRL-q sequence. This will detach the terminal from the container and will keep the container running. If you'll now run docker top busybox, you should see two processes in the list.
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
But the PPID of the two processes will be different. In fact, the PPID of the second process will be the same as PID of the first one. The first process acts as the parent process for the shell session that we just created.
Now, run docker exec -it busybox sh. Once inside the container, check the list of running processes for the container busybox in another terminal window by running the command docker top busybox. You should see something like this
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
root 7880 7451 0 11:45 pts/1 00:00:00 sh
The PPID of the first and third process will be the same, which confirms that docker exec creates a new process in the container's environment while docker attach just connects the standard input/output/error of the main process inside the container to corresponding standard input/output/error of current terminal.
Docker exec executes a new command / create a new process in the container’s environment, while docker attach just connects the standard input/output/error of the main process(with PID 1) inside the container to corresponding standard input/output/error of current terminal(the terminal you are using to run the command).
A container is an isolated environment, with some processes running in the environment. Specifically, a container has its own file system space and PID space that are isolated from host and other containers.
When the container is started using “docker run –it …”, the main process will have a pseudo-tty and STDIN kept open.
When attached in the tty mode, you can detach from the container (and leave it running) using a configurable key sequence. The default sequence is CTRL-p CTRL-q. You configure the key sequence using the --detach-keys option or a configuration file.
You can reattach to a detached container with docker attach.
Docker exec just starts a new process, inside the container’s environment, that is, belongs to the PID space of the container.
For example, if you start your container using “docker run –dit XXX /bin/bash”,you can attach to the container(‘s main process) using two different terminals. While you are inputting in one terminal, you can see it appears in the other terminal, for both terminal are connected to same tty.
Be careful that you are now in the main process of the container, if you type “exit”, you will exit the container(so be careful, using detach-keys to detach), and you will see both terminals exited.
But if you run “docker exec –it XXX /bin/bash” in two terminals, you have started two new processes inside the container, and they are not related to each other and to the main process, and you can safely exit from them.
Related
How to see the docker state instead of interacting with the shell?
I use following command to build web server docker run --name webapp -p 8080:4000 mypyweb When it stopped and I want to restart, I always use: sudo docker start webapp && sudo docker exec -it webapp bash But I can't see the server state as the first time: Digest: sha256:e61b45be29f72fb119ec9f10ca660c3c54c6748cb0e02a412119fae3c8364ecd Status: Downloaded newer image for ericgoebelbecker/stackify-tutorial:1.00 * Running on http://0.0.0.0:4000/ (Press CTRL+C to quit) How can I see the state instead of interacting with the shell?
When you use docker run, the default behavior is to run the container detached. This runs in the background and is detached from your shell's stdin/out. To run the container in the foreground and connected to stdin/out: docker run --interactive --tty --publish=8080:4000 mypyweb To docker start a container, similarly: docker start --interactive --attach [CONTAINER] NB --attach rather than -tty You may list (all add --all) running containers: docker container ls E.g. I ran Nginx: CONTAINER ID IMAGE PORTS NAMES 7cc4b4e1cfd6 nginx 0.0.0.0:8888->80/tcp nostalgic_thompson NB You may use the NAME or any uniquely identifiable subset of the ID to reference the container Then: docker stop nostalgic_thompson docker start --interative --attach 7cc4 You may check the container's logs (when running detached or from another shell) by grabbing the container's ID or NAMES docker logs nostalgic_thompson docker logs 7cc4 HTH!
Using docker exec is causing the shell to attach to the container. If you are comparing the behavior of docker run versus docker start, they behave differently, and it is confusing. Try this: $ sudo docker start -a webapp the -a flag tells docker to attach stdout/stderr and forward signals. There are some other switches you can use with the start command (and a huge number for the run command). You can run docker [command] --help to get a summary of the options. One other command that you might want to use is logs which will show the console output logs for a running container: $ docker ps [find the container ID] $ docker logs [container ID]
If you think your container's misbehaving, it's often not wrong to just delete it and create a new one. docker rm webapp docker run --name webapp -p 8080:4000 mypyweb Containers occasionally have more involved startup sequences and these can assume they're generally starting from a clean slate. It should also be extremely routine to delete and recreate a container; it's required for some basic tasks like upgrading the image underneath a container to a newer version or changing published ports or environment variables. docker exec probably shouldn't be part of your core workflow, any more than you'd open a shell to interact with your Web browser. I generally don't tend to docker stop containers, except to immediately docker rm them.
How to automatically stop and remove Docker container on Ctrl+C in terminal/gitbash/powershell/etc.?
For example I run docker run --rm --name mycontainer -p 8080:8080 myrepo/myimage then I see an output of my application, everything is OK. Then I press the Ctrl+C but the container is still running and I'm forced to explicitly stop and remove it: docker rm -f <container_id> Or even worse: docker stop <container_id> docker rm <container_id> Is there any way to do it automatically? If not it's OK. PS: What is the purpose of all that stopped containers still kept on the harddrive?!
What is the purpose of all that stopped containers still kept on the harddrive?! Running containers include the process you are running along with the namespaced environment to run that process inside of (networking, pid, filesystem, etc). A stopped container has the container specific read/write filesystem layer, any configuration you included to run the container (e.g. environment variables), and logs if you are using the json logging driver (default). Removing a container deletes that RW filesystem layer, json logs, and the configuration, which also removes the container from the list of stopped containers. This is a permanent operation, so do not remove containers you may want to later inspect or restart. I press the Ctrl+C but the container is still running and I'm forced to explicitly stop and remove it First, make sure you are running a current version of docker. I believe somewhere around 1.13 they migrated the processing of the --rm option from the client to the server. Next, make sure your application handles the Ctrl+C command. In a shell script, this would be a handler for a SIGTERM. You also need run the container interactively so that the keyboard input is sent to the container, that is the -it flag. With all three of those done, you should see containers automatically cleaned up with: docker run --rm -it --name mycontainer -p 8080:8080 myrepo/myimage followed by a Ctrl+C. The -it will pass the SIGTERM to the container which should then stop the process, which stops the running container. And the --rm will result in the container being automatically removed. If for some reason you cannot get your container to handle the SIGTERM, then you can send a SIGKILL with a docker kill command, which cannot be trapped and ignored by the application. Note that if you run a docker stop on your container and see a 10 second delay before it is stopped, then your application is ignoring the SIGTERM. One common cause for this is a /bin/sh running as pid 1. A shell will ignore this signal when it's running as pid 1 by default, on the assumption that you are in signal user mode.
Per default, docker runs the image command as pid 1. pid 1 is handled special by the kernel as it normally is used for the system init process. For this reason, CTRL+C / SIGTERM does not work on pid 1. Actual docker versions provide option --init to run a minimal init system (tini) as pid 1. Your image command runs as a child of tini. As no longer being pid 1, your image command will accept CTRL+C again. Add --init to your sample command, and you can stop with CTRL+C docker run --rm --init --name mycontainer -p 8080:8080 myrepo/myimage Not needed in your case, just additional info: You can change the signal from docker stop with --stop-signal SIGNAL with SIGNAL being one of the many signals shown by kill -L, for example SIGHUP or SIGINT.
docker run vs create+start: why are created containers different?
Related to docker container started in Detached mode stopped after process execution https://serverfault.com/questions/661909/the-right-way-to-keep-docker-container-started-when-it-used-for-periodic-tasks I do understand the difference between docker run and create + start, but don't understand how the actual containers created in these two ways differ. Say I create and run a container with docker run -dit debian:testing-slim and then stop it. The created container can later be started with docker start silly_docker_name and it'll run in the background, because the entry command for the image is bash. But when a container is first created docker create --name silly_name debian:testing-slim and then started with docker start silly_name then it'll exit immediately. Why isn't bash started, or how come it exits in this case?
The difference for a container process that is a shell (like bash in your debian example) is that a shell started without a terminal+interactive "mode" exits without doing anything. You can test this by changing the command of a create'd container to something that doesn't require a terminal: $ docker create --name thedate debian date Now if I run thedate container, each time I run it it outputs the date (in the logs) and exits. docker logs thedate will show this; one entry for each run. To be explicit, your docker run command has flags -dit: detached, interactive (connect STDIN), and tty are all enabled. If you want a similar approach with create & start, then you need to allocate a tty for the created container: $ docker create -it --name ashell debian Now if I start it, I ask to attach/interactively to it and I get the same behavior as run: $ docker start -ai ashell root#6e44e2ae8817:/# NOTE: [25 Jan 2018] Edited to add the -i flag on create as a commenter noted that as originally written this did not work, as the container metadata did not have stdin connected at the create stage
reconnect to container as the original "docker run"
I have some containers running and once in a while the connection is lost in the terminal. The container is still running perfectly. How do I reconnect to the samme user process? The problem is: When I do docker exec -it name bash, I get a new root user. But then I need to stop the applications the original user started to get them into this bash. How do you reconnect to the original running user process/bash. info: using mac terminal.
You would need to use the docker attach <container ID> refer: man docker-attach " The docker attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively. You can attach to the same contained process multiple times simultaneously, screen sharing style, or quickly view the progress of your daemonized process. You can detach from the container (and leave it running) with CTRL-p CTRL-q (for a quiet exit) or CTRL-c which will send a SIGKILL to the container. When you are attached to a con‐ tainer, and exit its main process, the process's exit code will be returned to the client. "
docker ps -a # list all the containers and find your container docker start <container ID> # start the exited container docker attach <container ID> # attach to your container
Correct way to detach from a container without stopping it
In Docker 1.1.2 (latest), what's the correct way to detach from a container without stopping it? So for example, if I try: docker run -i -t foo /bin/bash or docker attach foo (for already running container) both of which get me to a terminal in the container, how do I exit the container's terminal without stopping it? exit and CTR+C both stop the container.
Type Ctrl+p then Ctrl+q. It will help you to turn interactive mode to daemon mode. See https://docs.docker.com/engine/reference/commandline/cli/#default-key-sequence-to-detach-from-containers: Once attached to a container, users detach from it and leave it running using the using CTRL-p CTRL-q key sequence. This detach key sequence is customizable using the detachKeys property. [...]
Update: As mentioned in below answers Ctrl+p, Ctrl+q will now turn interactive mode into daemon mode. Well Ctrl+C (or Ctrl+\) should detach you from the container but it will kill the container because your main process is a bash. A little lesson about docker. The container is not a real full functional OS. When you run a container the process you launch take the PID 1 and assume init power. So when that process is terminated the daemon stop the container until a new process is launched (via docker start) (More explanation on the matter http://phusion.github.io/baseimage-docker/#intro) If you want a container that run in detached mode all the time, i suggest you use docker run -d foo With an ssh server on the container. (easiest way is to follow the dockerizing openssh tutorial https://docs.docker.com/engine/examples/running_ssh_service/) Or you can just relaunch your container via docker start foo (it will be detached by default)
I dug into this and all the answers above are partially right. It all depends on how the container is launched. It comes down to the following when the container was launched: was a TTY allocated (-t) was stdin left open (-i) ^P^Q does work, BUT only when -t and -i is used to launch the container: [berto#g6]$ docker run -ti -d --name test python:3.6 /bin/bash -c 'while [ 1 ]; do sleep 30; done;' b26e39632351192a9a1a00ea0c2f3e10729b6d3e22f8e0676d6519e15c08b518 [berto#g6]$ docker attach test # here I typed ^P^Q read escape sequence # i'm back to my prompt [berto#g6]$ docker kill test; docker rm -v test test test ctrl+c does work, BUT only when -t (without -i) is used to launch the container: [berto#g6]$ docker run -t -d --name test python:3.6 /bin/bash -c 'while [ 1 ]; do sleep 30; done;' 018a228c96d6bf2e73cccaefcf656b02753905b9a859f32e60bdf343bcbe834d [berto#g6]$ docker attach test ^C [berto#g6]$ The third way to detach There is a way to detach without killing the container though; you need another shell. In summary, running this in another shell detached and left the container running pkill -9 -f 'docker.*attach': [berto#g6]$ docker run -d --name test python:3.6 /bin/bash -c 'while [ 1 ]; do sleep 30; done;' b26e39632351192a9a1a00ea0c2f3e10729b6d3e22f8e0676d6519e15c08b518 [berto#g6]$ docker attach test # here I typed ^P^Q and doesn't work ^P # ctrl+c doesn't work either ^C # can't background either ^Z # go to another shell and run the `pkill` command above # i'm back to my prompt [berto#g6]$ Why? Because you're killing the process that connected you to the container, not the container itself.
If you do "docker attach "container id" you get into the container. To exit from the container without stopping the container you need to enter Ctrl+P+Q
I consider Ashwin's answer to be the most correct, my old answer is below. I'd like to add another option here which is to run the container as follows docker run -dti foo bash You can then enter the container and run bash with docker exec -ti ID_of_foo bash No need to install sshd :)
Try CTRL+P,CTRL+Q to turn interactive mode to daemon. If this does not work and you attached through docker attach, you can detach by killing the docker attach process. Better way is to use sig-proxy parameter to avoid passing the CTRL+C to your container : docker attach --sig-proxy=false [container-name] Same option is available for docker run command.
The default way to detach from an interactive container is Ctrl+P Ctrl+Q, but you can override it when running a new container or attaching to existing container using the --detach-keys flag.
You can use the --detach-keys option when you run docker attach to override the default CTRL+P, CTRL + Q sequence (that doesn't always work). For example, when you run docker attach --detach-keys="ctrl-a" test and you press CTRL+A you will exit the container, without killing it. Other examples: docker attach --detach-keys="ctrl-a,x" test - press CTRL+A and then X to exit docker attach --detach-keys="a,b,c" test - press A, then B, then C to exit Extract from the official documentation: If you want, you can configure an override the Docker key sequence for detach. This is useful if the Docker default sequence conflicts with key sequence you use for other applications. There are two ways to define your own detach key sequence, as a per-container override or as a configuration property on your entire configuration. To override the sequence for an individual container, use the --detach-keys="<sequence>" flag with the docker attach command. The format of the <sequence> is either a letter [a-Z], or the ctrl- combined with any of the following: a-z (a single lowercase alpha character ) # (at sign) [ (left bracket) \ (two backward slashes) _ (underscore) ^ (caret) These a, ctrl-a, X, or ctrl-\\ values are all examples of valid key sequences. To configure a different configuration default key sequence for all containers, see Configuration file section. Note: This works since docker version 1.10+ (at the time of this answer, the current version is 18.03)
If you just want see the output of the process running from within the container, you can do a simple docker container logs -f <container id>. The -f flag makes it so that the output of the container is followed and updated in real-time. Very useful for debugging or monitoring.
In Docker container atleast one process must be run, then only the container will be running the docker image(ubuntu,httd..etc, whatever it is) at background without exiting For example in ubuntu docker image , To create a new container with detach mode (running background atleast on process), docker run -d -i -t f63181f19b2f /bin/bash it will create a new contain for this image(ubuntu) id f63181f19b2f . The container will run in the detached mode (running in background) at that time a small process tty bash shell will be running at background. so, container will keep on running untill the bash shell process will killed. To attach to the running background container,use docker attach b1a0873a8647 if you want to detach from container without exiting(without killing the bash shell), By default , you can use ctrl-p,q. it will come out of container without exiting from the container(running background. that means without killing the bash shell). You can pass the custom command during attach time to container, docker attach --detach-keys="ctrl-s" b1a0873a8647 this time ctrl-p,q escape sequence won't work. instead, ctrl-s will work for exiting from container. you can pass any key eg, (ctrl-*)
You can simply kill docker cli process by sending SEGKILL. If you started the container with docker run -it some/container You can get it's pid ps -aux | grep docker user 1234 0.3 0.6 1357948 54684 pts/2 Sl+ 15:09 0:00 docker run -it some/container let's say it's 1234, you can "detach" it with kill -9 1234 It's somewhat of a hack but it works!
To prevent having logs you should run in detach mode using the -d flag docker run -d <your_command> If you are already stuck, you could open a new window/tab in your terminal and close the first one. It won't stop the process of the running job
in case if you using docker on windows, you may use combination 'CTRL + D'
Old post but just exit then start it again... the issue is if you are on a windows machine Ctrl p or Ctrl P are tied to print... exiting the starting the container should not hurt anything