So today I noticed a interesting "crond" process taking up 100% of the cpu.
The strange thing is, I don't have cron installed.
find / -name "crond"
/var/lib/docker/devicemapper/mnt/d359c68dd07e2defb573e3d6f5c20f9984a3796d1fbdd92dd2d48923bf49ea8f/rootfs/usr/sbin/crond
Not really sure what else I can do besides kill the process. Is there any way I could diagnose the cause of this issue?
The crond is running within the container.
You can attach to the container, i.e. with docker exec -it <container> bash then navigate to /var/logs and inspect logs for further analysis.
In case you have multiple running containers you need to find which one is generating the issue: i.e. you can enumerate them with docker ps then run
docker inspect <container> | grep d359c68dd07e2defb573e3d6f5c20f9984a3796d1fbdd92dd2d48923bf49ea8f on each.
When you have a hit you have found the container to analyze further.
Related
We are running a docker swarm and using Monit to see resources utilisation. The
Process memory for dockerd keeps on growing over time. This happens on all nodes that at least perform a docker action e.g docker inspect or docker exec. I'm suspecting it might be something related to this these actions but I'm not sure how to replicate it. I have a script like
#!/bin/sh
set -eu
containers=$(docker container ls | awk '{if(NR>1) print $NF}')
# Loop forever
while true;
do
for container in $containers; do
echo "Running Inspect on $container"
CONTAINER_STATUS="$(docker inspect $container -f "{{.State}}")"
done
done
but I'm open to other suggestions
Assuming you can run ansible to run a command via ssh on all servers:
ansible swarm -a "docker stats --no-stream"
A more SRE solution is containerd + Prometheus + AlerManager / Grafana to gather metrics from the swarm nodes and then implement alerting when container thresholds are exceeded.
Don't forget you can simply set a resource constraint on Swarm services to limit the amount of memory and cpu service tasks can consume or be restarted. Then just look for services that keep getting OOM killed.
I can view the list of running containers with docker ps or equivalently docker container ls (added in Docker 1.13). However, it doesn't display the user who launched each Docker container. How can I see which user launched a Docker container? Ideally I would prefer to have the list of running containers along with the user for launched each of them.
You can try this;
docker inspect $(docker ps -q) --format '{{.Config.User}} {{.Name}}'
Edit: Container name added to output
There's no built in way to do this.
You can check the user that the application inside the container is configured to run as by inspecting the container for the .Config.User field, and if it's blank the default is uid 0 (root). But this doesn't tell you who ran the docker command that started the container. User bob with access to docker can run a container as any uid (this is the docker run -u 1234 some-image option to run as uid 1234). Most images that haven't been hardened will default to running as root no matter the user that starts the container.
To understand why, realize that docker is a client/server app, and the server can receive connections in different ways. By default, this server is running as root, and users can submit requests with any configuration. These requests may be over a unix socket, you could sudo to root to connect to that socket, you could expose the API to the network (not recommended), or you may have another layer of tooling on top of docker (e.g. Kubernetes with the docker-shim). The big issue in that list is the difference between the network requests vs a unix socket, because network requests don't tell you who's running on the remote host, and if it did, you'd be trusting that remote client to provide accurate information. And since the API is documented, anyone with a curl command could submit a request claiming to be a different user.
In short, every user with access to the docker API is an anonymized root user on your host.
The closest you can get is to either place something in front of docker that authenticates users and populates something like a label. Or trust users to populate that label and be honest (because there's nothing in docker validating these settings).
$ docker run -l "user=$(id -u)" -d --rm --name test-label busybox tail -f /dev/null
...
$ docker container inspect test-label --format '{{ .Config.Labels.user }}'
1000
Beyond that, if you have a deployed container, sometimes you can infer the user by looking through the configuration and finding volume mappings back to that user's home directory. That gives you a strong likelihood, but again, not a guarantee since any user can set any volume.
I found a solution. It is not perfect, but it works for me.
I start all my containers with an environment variable ($CONTAINER_OWNER in my case) which includes the user. Then, I can list the containers with the environment variable.
Start container with environment variable
docker run -e CONTAINER_OWNER=$(whoami) MY_CONTAINER
Start docker compose with environment variable
echo "CONTAINER_OWNER=$(whoami)" > deployment.env # Create env file
docker-compose --env-file deployment.env up
List containers with the environment variable
for container_id in $(docker container ls -q); do
echo $container_id $(docker exec $container_id bash -c 'echo "$CONTAINER_OWNER"')
done
As far as I know, docker inspect will show only the configuration that
the container started with.
Because of the fact that commands like entrypoint (or any init script) might change the user, those changes will not be reflected on the docker inspect output.
In order to work around this, you can to overwrite the default entrypoint set by the image with --entrypoint="" and specify a command like whoami or id after it.
You asked specifically to see all the containers running and the launched user, so this solution is only partial and gives you the user in case it doesn't appear with the docker inspect command:
docker run --entrypoint "" <image-name> whoami
Maybe somebody will proceed from this point to a full solution (:
Read more about entrypoint "" in here.
If you are used to ps command, running ps on the Docker host and grep with parts of the process your process is running. For example, if you have a Tomcat container running, you may run the following command to get details on which user would have started the container.
ps -u | grep tomcat
This is possible because containers are nothing but processes managed by docker. However, this will only work on single host. Docker provides alternatives to get container details as mentioned in other answer.
this command will print the uid and gid
docker exec <CONTAINER_ID> id
ps -aux | less
Find the process's name (the one running inside the container) in the list (last column) and you will see the user ran it in the first column
I have multiple docker instance running and I want to push the log outputs to a GUI.
I wrote python script which basically does
docker logs $containerId --tail 50 -f
for each container.
The result is nice and it works fine, but I have a very high cpu load from dockerd.
What can I do to prevent the high load? Are there better ways to get the log output?
Thanks in advance.
I fixed it. Docker also saves the output to a file:
docker inspect --format='{{.LogPath}}' $containerId
Then I just tail this file:
tail -f $path
I currently use docker for my backend, and when I first start them up with
docker-compose up
I get log outputs of all 4 dockers at once, so I can see how they are interacting with each other when a request comes in. Looking like this, one request going from nginx to couchdb
The issue is now that I am running on GCE with load balancing, when a new VM spins up, it auto starts the dockers and runs normally, I would like to be able to access a load balanced VM and view the live logs, but I can not get docker to allow me this style, when I use logs, it gives me normal all white font with no label of where it came from.
Using
docker events
does nothing, it won't return any info.
tldr; what is the best way to obtain a view, same as the log output you get when running "docker-compose up"
If using docker-compose, you use
docker-compose logs --tail=0 --follow
instead of
docker logs --tail=0 --follow
This will get the output I was originally looking for.
You can see the logs for all running containers with
docker ps -q | xargs -L 1 docker logs
In theory this might work for the --follow too if xargs is ran with -P <count>, where the count is higher than the number of running containers.
I use a variation of this to live tail (--follow) all logs and indicate which log is tailing at the time. This bash includes both stdout and stderr. Note you may need to purge the /tmp dir of *.{log,err} afterwards.
for c in $(docker ps -a --format="{{.Names}}")
do
docker logs -f $c > /tmp/$c.log 2> /tmp/$c.err &
done
tail -f /tmp/*.{log,err}
Hope this helps. Logging has become so problematic these days, and other get-off-my-lawn old man rants...
Try "watch"
Here's a quick and dirty multitail/xtail for docker containers.
watch 'docker ps --format "{{.Names}}" | sort | xargs --verbose --max-args=1 -- docker logs --tail=8 --timestamps'
How this works:
watch to run every few seconds
docker ps --format "{{.Names}}" to get the names of all running containers
sort to sort them
xargs to give these names to docker logs:
docker logs to print the actual logs
Adjust parameter "--tail=8" as needed so that everything still fits on one screen.
The "xargs" methods listed above (in another user's answer) will stop working as containers are stopped and restarted. This "watch" method here does not have that problem. (But it's not great either.)
If you are using Docker Swarm, you can find your services by
docker service ls
Grap the id, and then run
docker service logs $ID -f
if the service is defined with tty: true, then you must run with the --raw flag. Notice, this wont tell you which container is giving the outputted log entry.
Docker's documentation says that --rm and -d cannot be used together: https://docs.docker.com/engine/reference/run/#detached-d
Why? I seem to be misunderstanding what "detached" means; it seems entirely orthogonal to what --rm does. Why are they mutually exclusive?
By way of analogy, if I start a process in the background (e.g. start my-service), and the process exits, the process's resources are freed automatically (by init). It doesn't stick around, waiting for me to manually remove it. Why doesn't docker allow me to combine -d with --rm so that my container works in an analogous way?
I think that would address a very common use case. Seems that it would very nicely obviate the following work around: https://thraxil.org/users/anders/posts/2015/11/03/Docker-and-Upstart/
What am I missing???
Because --rm is implemented as a client-side option: when you specify --rm, the docker client waits around for the container to exit, and then removes it.
When you specify -d, the docker client exits. The container is running and is managed by the Docker server. There is no longer any client running to implement the --rm functionality.
As a way of answering, lets imagine i launch a container using -d and --rm and this is allowed. docker run -d --rm --name=my_app my_container
If my app works as expected it will run and when it come time to die, it dies and quietly removes itself, meaning I can rerun this command with little hassle. This seems ideal, and your question was one I faced myself while setting up some docker automation for my project.
What if, however, something goes wrong, the process running in the container encounters a fatal error and crashes, causing the container to die. The problem is that, to any outside observer, be they human or monitoring software, will not be able to tell the difference between these two scenarios, except maybe by how long the container was alive.
In cases where -d is not used, running a command in CLI or using upstart/initd/systemd/other, the container writes output, which will remain even if the container was given --rm, allowing an error or crash to be noticed and resolved.
In cases where -d is used, not binding container output to any output stream or file, --rm is not allowed to ensure that there is evidence left behind, in the form of a dead container, of an error/crash.
To wrap up/TL;DR: I believe this conscious choice was made by docker developers to prevent cases in which containers were completely unaccounted for with the trade-off being the need to add two more commands to your automation script.
As of version 1.13, you now can use --rm with background jobs. The remove operation has been moved from the client to the server to enable this.
See the following pull request for more details: https://github.com/docker/docker/pull/20848
Here's an example of this new behavior:
$ docker run -d --rm --name sleep busybox sleep 10
be943302d668f6416b083b8b6fa74e254b8e4200d14f6d7743d48691db1a4b18
$ docker ps | grep sleep
be943302d668 busybox "sleep 10" 4 seconds ago Up 3 seconds sleep
$ sleep 10; docker ps | grep sleep