Docker Detached Mode - docker

What is detached mode in the docker world? I read this article
Link, but it does not explain exactly what detached mode mean.

You can start a docker container in detached mode with a -d option. So the container starts up and run in background. That means, you start up the container and could use the console after startup for other commands.
The opposite of detached mode is foreground mode. That is the default mode, when -d option is not used. In this mode, the console you are using to execute docker run will be attached to standard input, output and error. That means your console is attached to the container's process.
In detached mode, you can follow the standard output of your docker container with docker logs -f <container_ID>.
Just try both options. I always use the detached mode to run my containers. I hope I could explain it a little bit clearer.

The detach option on the docker command line indicates that the docker client (docker) will make a request to the server (dockerd), and then the client will exit while that request continues on the server. Part of the confusion may be that docker looks like a single process, where in reality it is a client/server application where the client is just a thin frontend on a REST API to send every command to the server.
With a docker container run --detach, this means the container will be created, the server will respond with a container id if successful, and the container will continue to run on the server while you are free to run other commands. This is often used for a server (e.g. nginx) you want to start in the background while you continue to run other commands. Note that you can still configure a container with the --interactive and -tty options (often abbreviated -it) and later run a docker container attach to connect to an already running container. (Note, until you attach to the container running with -itd, any attempt by the container to read from stdin would hang, instead of seeing an end of input that often triggers an immediate exit if you just passed -d.)
If you run without the detach option, the client will immediately run an attach API call after the container is created so you can see the output and optionally provide input to the running process on the container. This is useful if your container is running something interactive (e.g. /bin/bash).
Several other commands allow the detach option, including docker-compose up -d which will start an entire project and leave it running on the server in the background. There's also many of the docker service commands which will either detach after submitting the change to the server to create or update a service's target state, or if you do not detach, the client will wait until the service's current state matches the target state and you can see the progress of the deployment. Note with docker service commands, you may have to pass --detach=false to remain attached, the behavior has changed over the past year depending on your version.

What is detached mode in the docker world?
Detached means that the container will run in the background, without being attached to any input or output stream.
docker provide --detach (or -d in short) option and started the program in the background.
This means that the program started but isn’t attached to your terminal.
Example docker run --detach --name web nginx:latest # Note the detach flag.
Why do we need --detach mode?
Server software is generally run in detached containers because it is rare that the software depends on an attached terminal.
Running detached containers is a perfect fit for programs that sit quietly in the background.
Note
Generally, This type of program is called a daemon, or a service. A daemon generally interacts with other programs (or humans over a network) or some other communication channel. When you launch a daemon or other program in a container that you want to run in the background, remember to use either the --detach flag or its short form, -d.

To understand what does mean that -d in docker world, let me explain more clearly with the simulation within it. Docker detached mode means that you can tell the docker that do process(container) until if I am going to write the command docker stop container-id or container-name otherwise I mean without detached mode docker run the process(container) either you press ctrl+c or close a terminal, in other words you have not any choice when docker run the process(container) if you run the process(container) without -d. But you have any choice that docker return id of the container when you type the command with -d because of running process(container) in the background.

docker run -d -t ubuntu:14.04
docker run - Create an instance from docker image as docker container.
(if image not available locally it pulls from docker hub)
ubuntu - Image name
14.04 - Tag
-d, --detach - Detach mode
-t, --tty - Allocate a pseudo-TTY

Related

How to stop Docker from clearing logs for dead containers?

I use Dokku to run my app, and for some reason, the container is dying every few hours and recreates itself.
In order to investigate the issue, I am willing to read the error logs to this container and understand why it's crashing. Since Docker clears logs of dead containers, this is impossible.
I turned on docker events and it shows many events (like container update, container kill, container die, etc.) But no sign of what triggered this kill.
How can I investigate the issue?
Versions:
Docker version 19.03.13, build 4484c46d9d
dokku version 0.25.1
Logs are deleted when the container is deleted. If you want the logs to persist, then you need to avoid deleting the container. Make sure you aren't running the container with an option like --rm that automatically deletes it on exit. And check for the obvious issues like running out of disk space.
There are several things you can do to investigate the issue:
You can run the container in the foreground and allow it to log to your console.
If you were previously starting the container in the background with docker run -d (or docker-compose up -d), just remove the -d from the command line and allow the container to log to your terminal. When it crashes, you'll be able to see the most recent logs and scroll back to the limits of your terminal's history buffer.
You can even capture this output to a file using e.g. the script tool:
script -c 'docker run ...`
This will dump all the output to a file named typescript, although you can of course provide a different output name on the command line.
You can change the log driver.
You can configure your container to use a different logging driver. If you select something like syslog or journald, your container logs will be sent to the corrresponding service, and will continue to be available even after the container has been deleted.
I like use the journald logging driver because this allows searching for output by container id. For example, if I start a container like this:
docker run --log-driver journald --name web -p 8080:8080 -d docker.io/alpinelinux/darkhttpd
I can see logs from that container by running:
$ journalctl CONTAINER_NAME=web
Feb 25 20:50:04 docker 0bff1aec9b65[660]: darkhttpd/1.13, copyright (c) 2003-2021 Emil Mikulic.
These logs will persist even after the container exits.
(You can also search by container id instead of name by using CONTAINER_ID_FULL (the full id) or CONTAINER_ID (the short id), or even by image name with IMAGE_NAME.)

multi execute connection windows display the same session information of one container

In my CentOS server I use docker created a container,
I opened two sessions connected to the container by command:
docker attach container-name
but there is an issue, in each window I execute command the other window is display the same information.
so I cannot control the container when it is installing package.
is it possible to avoid this issue?
The docker attach command attaches to the currently running process as defined by CMD. You can attach as many times as you want, but they all connect to the same process.
If you want to access the container and have different sessions to it, use:
docker exec -it container-name bash
Or whatever shell is available. bash is common, but you may need to use sh or find out what's used, if any is there at all. Some containers are super stripped down.
The -it flag enables "interactive" mode, as otherwise it just runs that command and shows you the output.

Differences between detached mode and background in docker

Running docker run with a -d option is described as running the container in the background. This is what most tutorials do when they don't want to interact with the container. On another tutorial I saw the use of bash style & to send the process to the background instead of adding the -d option.
Running docker run -d hello_world only outputs the container ID. On the other hand docker run hello_world & still gives me the same output as if i had run docker run hello_world.
If I do the both experiments with docker run nginx I get the same behavior on both (at least as far as I can see), and both show up if I run docker ps.
Is the process the same in both cases(apart from the printing of the ID and output not being redirected with &)? If not, what is going on behind the scenes in each?
docker is designed as C-S architecture: docker client, docker daemon(In fact still could fined to container-d, shim, runc etc).
When you execute docker run, it will just use docker client to send things to docker daemon, and let daemon call runc etc to start a container.
So:
docker run -d: It will let runc run container in background, you can use docker logs $container_name to see all logs later, the background happend on server side.
docker run &: It will make the linux command run at background, which means the docker run will be in background, this background run on client side. So you still can see stdout etc in terminal. More, if you leave the terminal(even you bash was set as nohup), you will not see it in terminal, you still need docker logs to see 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.

is it reasonable to run docker processes under runit/daemontools supervision

I have been running docker processes (apps) via
docker run …
But under runit supervision (runit is like daemontools) - so runit ensures that the process stays up, passes signals etc.
Is this reasonable? Docker seems to want to run its own demonization - but it isn't as thorough as runit. Furthermore, when runit restarts the app - a new container is created each time (fine) but it leaves a trace of the old one around - this seems to imply I am doing it in the wrong way.
Should docker not be run this way?
Should I instead set up a container from the image, just once, and then have runit run/supervise that container for all time?
Docker does do some management of daemonized containers: if the system shuts down, then when the Docker daemon starts it will also restart any containers that were running at the time the system shut down. But if the container exits on its own or the kernel (or a user) kills the container while it is running, the Docker daemon won't restart it. In cases where you do want a restart, a process manager makes sense.
I don't know runit so I can't give specific configuration guidance. But you should probably make the process manager communicate with the docker daemon and check to see if a given container id is running (docker ps | grep container_id or equivalent, or use the Docker Remote API directly). If the container has stopped, use Docker to restart it (docker run container_id) instead of running a new container. Or, if you do want a new container each time, then begin with docker run -rm to automatically clean it up when it exits or stops.
If you don't want your process manager to poll docker, you could instead run something that watches docker events.
You can get the container_id when you start the container as the return value of starting a daemon, or you can ask Docker to write this out to a file (docker run -cidfile myfilename, like a PID file)
I hope that helps or helps another runit guru offer more detailed advice.
Yes, I think running docker under runit makes sense. Typically when you start a process there is a way to tell it not to daemonize if it does by default since the normal way to hand-off from the runit run script to a process is via exec on the last line of your run script. For docker this means making sure not to set the -d flag.
For example, with docker you probably want your run script to look something like this:
#!/bin/bash -e
exec 2>&1
exec chpst -u dockeruser docker run -a stdin -a stdout -i ...
Using exec and chpst should resolve most issues with processes not terminating correctly when you bring down a runit service.

Resources