Recording docker exec sessions on Linux hosts
Docker can tell you that someone ran docker exec against a container, but not what they did once they were inside. Its event stream keeps the command line and exit code, container logs leave exec sessions out, and auditd can't name the person behind them. shellz captures every exec as a separate host-side recording that carries the container's name and points back to the SSH login behind it.
Choose shellz if
- People or scripts open shells in containers with
docker exec, and you need to see what was typed and what came back. - Each container session should trace back to a host user, an SSH login and a source IP.
- You want an alert when an exec happens outside a recorded session, or when the Docker API is reachable over the network.
- During an investigation you want to filter sessions by container name or image.
Look elsewhere if
- Your containers run on Kubernetes and people get in with
kubectl exec. shellz doesn't record those sessions. - Exec into some containers must be refused outright. shellz records sessions and blocks nothing.
- You need every process in every container logged, including ones no person started. That's a job for auditd or a runtime security tool.
- Container audit data can't leave your own infrastructure. shellz is cloud-hosted only.
At a glance
| Capability | Docker events | docker logs | auditd | shellz |
|---|---|---|---|---|
| The command that opened the exec | Yes, in the event text | No | Yes, if an execve rule is loaded | Yes |
| What was typed and printed inside | No | No, exec output isn't included | No | Yes: full terminal replay, plus text |
| The host user who ran it | No | No | No, the login ID is unset for processes the daemon starts | Yes, from the SSH login it ran under |
| A history you can go back to | Partial: docker events returns at most the last 256 events | Depends on the logging driver | Yes, on the host's disk | Yes, encrypted and stored off the server |
Docker notes that an exec happened and keeps almost nothing else
docker exec starts a new process inside a container that's already running. Most of the time that process is a shell, opened with something like docker exec -it api bash.
The Docker daemon reports each exec as a pair of events, exec_create and exec_start, followed by exec_die when it ends. In our test on Docker 29.8.2, those events carried the command line, the container name, the image and the exit code. For the shell above, the event text reads bash. Every command typed into that shell is absent, along with the host user who opened it.
The event stream also has a short memory. Docker's docs say docker events returns only the last 256 events, so it's a live feed for tooling rather than an audit trail.
Container logs and auditd miss exec sessions for different reasons
docker logs shows the standard output and error of the container's own command, the process it was started with. An exec is a separate process. When we ran a command through docker exec that printed a marker string, the marker never appeared in docker logs.
auditd, the Linux kernel's audit log, can see the processes an exec starts. It can't connect them to a person. The docker command only asks the daemon to do the work, and the daemon was started at boot by systemd. Red Hat's Dan Walsh explained in 2018 that container processes therefore carry the unset login ID, 4294967295, so the audit record can't point back to the user who typed docker.
Anyone who can reach the Docker socket is effectively root
Docker's install guide warns that the docker group grants root-level privileges. Its guide to protecting the daemon says anyone holding the TLS client keys can give the daemon any instruction, which amounts to root access on the host.
That makes a container shell a privileged action, the same as sudo. If your auditor asks for records of privileged access, exec sessions belong in the evidence.
shellz records each exec as its own session
When someone runs docker exec or docker attach from a login on the host, shellz records the container session separately from the SSH session around it. The recording shows the container name, the image and the user inside the container, and it links back to the parent SSH session with its host user and source IP.
You get a replay of the terminal and a plain-text transcript. Sessions are searchable by container name or image, so you can pull up everything anyone did in postgres containers this week with one filter.
Two situations raise alerts. One is an exec that shellz didn't record, for example a script calling the Docker API directly. The other is a Docker daemon listening on a TCP port, which exposes root-equivalent control to the network.
An illustrative trace from config change to the person who made it
This scenario is made up to show the workflow. An API container on app-02 starts returning errors after a quiet afternoon. Nobody admits to touching it.
Filtering sessions by the container's image turns up one exec from 15:42. The replay shows a shell where someone edited a config file with vi and restarted a worker process. The linked SSH session shows the host user and the office VPN address it came from.
Kubernetes and processes nobody started are out of scope
shellz records sessions on the Linux host. kubectl exec goes through the Kubernetes API to the node, and shellz doesn't record it. Processes a container runs on its own, such as its main service or a cron job inside the image, aren't sessions either. For a log of every process, pair shellz with auditd (shellz vs auditd).
Container shells often print secrets. Running env inside one lists every variable passed to the container, API keys included, and the recording will contain them. Hidden password input stays out. The host encrypts every recording under a key used for that session alone, and with Perfect Secrecy it opens only with a passkey held by someone on your team (security model).
Each Docker host counts as a device, and 10 of them are free. Commercial lifts the device cap for $10 a month per member of your shellz team, plus a dollar a month for each GB you keep (pricing).
Questions
Does docker logs show commands run with docker exec?
No. docker logs shows the output of the container's own command. An exec runs as a separate process, and its input and output don't appear there.
How can I see who ran docker exec on a server?
Docker's events name the container and the command but not the host user. auditd marks processes started by the daemon with an unset login ID. shellz links the exec to its originating SSH session, which carries the user name and source IP.
Does shellz record kubectl exec?
No. shellz records sessions that start on the Linux host, such as docker exec and docker attach. Kubernetes exec sessions go through the cluster API and aren't recorded.
What if someone runs docker exec from a script or over the Docker API?
An exec that shellz didn't record raises an alert. A Docker daemon listening on a TCP port raises one too, since anyone who can reach it can control the host.
Does the recording include what the container printed?
Yes. The replay shows everything the terminal displayed, and the transcript stores it as searchable text. Input typed at hidden password prompts is left out.
Related comparisons
Sources
Competitor details come from public documentation and pricing pages, last checked on November 4, 2026. Products change; if something here is out of date, tell us at hello@shellz.dev and we will correct it.
- Docker docs: docker system events (exec events, last 256 events)
- Docker docs: View container logs (STDOUT and STDERR of the container's command)
- Docker docs: Linux post-installation steps (docker group grants root-level privileges)
- Docker docs: Protect the Docker daemon socket (client keys give root access)
- Docker docs: Docker Engine security (daemon attack surface)
- Opensource.com, Dan Walsh: Podman, a more secure way to run containers (unset loginuid, October 30, 2018)