Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 8 min read

Docker Error Guide: 'cannot stop container: permission denied' — Fix Daemon and Cgroup Signal Failures

Fix Docker 'cannot stop container permission denied': diagnose docker socket access, rootless and SELinux/AppArmor policies, stuck cgroups, and kill signals the runtime cannot deliver.

  • #docker
  • #troubleshooting
  • #errors
  • #permissions

Overview

Docker returns this when the daemon accepts a stop request but the underlying runtime cannot deliver the kill signal to the container’s processes:

Error response from daemon: cannot stop container 5c1f9b0a2e83: permission denied

There are two distinct flavors. Either the client cannot talk to the daemon at all (a socket-permission problem on the user’s side), or the daemon can reach the runtime but a security policy or a broken cgroup prevents it from signalling the container’s PID 1. The word permission points at access control — on the socket, in SELinux/AppArmor, or in the cgroup hierarchy.

Symptoms

  • docker stop <id> or docker rm -f <id> returns cannot stop container ... permission denied.
  • The container stays in Up (or Removal In Progress) no matter how many times you stop it.
  • Non-root users get permission denied while trying to connect to the Docker daemon socket on every command.
  • dmesg shows AppArmor/SELinux denials around the container’s runtime.

Common Root Causes

  • Docker socket permissions — the user is not in the docker group, so the client cannot reach /var/run/docker.sock.
  • SELinux or AppArmor policy — a security module denies the runtime the right to send signals to the container.
  • Stuck or corrupted cgroup — the container’s cgroup is in a bad state, so runc cannot deliver SIGTERM/SIGKILL.
  • Rootless Docker limitations — a rootless daemon lacks privileges to signal certain processes.
  • Unkillable process state — PID 1 is stuck in uninterruptible sleep (D state) on a hung mount or I/O.
  • Daemon/runtime mismatch or corruption after an upgrade.

Diagnostic Workflow

First separate a client-side socket problem from a daemon-side signal problem. If ordinary commands fail too, it is the socket:

docker ps                                   # if this also says permission denied -> socket issue
ls -l /var/run/docker.sock
id -nG | tr ' ' '\n' | grep -x docker       # are you in the docker group?

If docker ps works but stop does not, look at the container and the runtime. Check its state and try an explicit kill:

docker inspect --format '{{.State.Status}} pid={{.State.Pid}}' 5c1f9b0a2e83
sudo docker kill -s SIGKILL 5c1f9b0a2e83

Inspect the daemon and kernel for policy denials:

journalctl -u docker --since '10 min ago' | grep -i '5c1f9b0a2e83\|permission\|apparmor'
dmesg | tail -30 | grep -i 'apparmor\|selinux\|denied'

Check whether PID 1 is wedged in uninterruptible sleep on the host:

ps -o pid,stat,cmd -p $(docker inspect --format '{{.State.Pid}}' 5c1f9b0a2e83)

A D in the STAT column means the process is blocked in the kernel and no signal will land until the I/O clears.

Example Root Cause Analysis

An operator could run docker ps but every docker stop web returned cannot stop container ... permission denied. Because listing worked, the socket was fine — this was a daemon-side signal problem.

The daemon log pointed at the security module:

journalctl -u docker --since '5 min ago' | grep -i apparmor
# apparmor="DENIED" operation="signal" profile="docker-default" ...

A custom AppArmor profile applied to the container was denying the signal capability, so runc could not deliver SIGTERM. The immediate remediation was to force-kill through the runtime and then correct the profile:

sudo docker kill -s SIGKILL web

The durable fix was to update the AppArmor profile to permit signalling within docker-default (or run the container with the standard profile), after which normal docker stop worked again. When the cause is instead a stuck cgroup, a daemon restart (sudo systemctl restart docker) clears the wedged state.

Prevention Best Practices

  • Add operators to the docker group (or use rootless Docker deliberately) so socket permission errors never masquerade as stop failures.
  • Test custom SELinux/AppArmor and seccomp profiles against a full container lifecycle — start, exec, and stop — before rolling them out.
  • Keep the daemon and runc/containerd versions in sync, and restart the daemon after upgrades to avoid a stale runtime.
  • Avoid mounts (NFS, network storage) that can hang PID 1 in uninterruptible sleep; add timeouts.
  • Standardize container security settings using the Docker stack guide and validate build-time config with the Dockerfile validator.

Quick Command Reference

docker ps                                    # works? -> daemon-side; fails? -> socket-side
ls -l /var/run/docker.sock; id -nG | grep docker
docker inspect --format '{{.State.Status}} {{.State.Pid}}' <id>
sudo docker kill -s SIGKILL <id>             # force the signal via the runtime
journalctl -u docker --since '10 min ago' | grep -i 'apparmor\|permission'
dmesg | tail -30 | grep -i 'denied'

Conclusion

cannot stop container: permission denied has two very different roots. If every Docker command fails, fix the socket permissions — add the user to the docker group. If only stop fails, the daemon cannot signal the container: check for SELinux/AppArmor denials in the logs, a wedged cgroup, or a PID 1 stuck in D state. Force the kill through the runtime to regain control, then correct the security profile or restart the daemon so ordinary stops work again.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.