Home › CKS › Topics › Practice tasks › Docker Security
CKS · System Hardening

Harden the Docker Daemon on a Kubernetes Node

Perform the following tasks to secure the cluster node: Remove user developer from the docker group. Do not remove the user from any other group.

Check live lab access → All CKS tasks

Live lab access

This task description is public. Live practice requires full access unless this is the selected free weekly task. AI Lab Coach is available in single-task labs, including the free weekly task. See this week's free task.

Create an account to continue →

Read this week's free task →

On a phone? Read the task and create your account here, then sign in on a desktop or laptop for the terminal lab. Nothing starts until you choose Start.

The task

Task

Perform the following tasks to secure the cluster node:

After completing your work, ensure the Kubernetes cluster is healthy.

*Lab note: this lab node holds the Docker configuration but does not run a live systemd/dockerd, so systemctl commands will not work here (System has not been booted with systemd...). Edit the configuration directly; the grader inspects the on-disk config.*

Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. Everything here changes a host's Docker daemon: practise on a throwaway VM with systemd, never on a node that runs real workloads.

Who can reach the Docker daemon, and where that is configured

The Docker daemon runs as root, and anyone who can talk to its API can start a container that mounts the host's /. Docker's own docs say membership of the docker group grants root-level privileges. Hardening a node therefore means controlling three things: who is in the group that owns the Unix socket, which group that is, and whether the API is also exposed on a TCP port.

user ──(group membership)──→ /run/docker.sock ──→ dockerd (root)
                                     ▲ owner/group/mode set by docker.socket (fd://) or dockerd --group
remote host ──→ tcp://...:2375 ──→ dockerd   (only if -H tcp:// or "hosts" says so)

1. Inspect, change nothing yet

getent group docker
id trainee
ls -l /run/docker.sock
systemctl cat docker.service docker.socket
sudo cat /etc/docker/daemon.json
sudo ss -ltnp | grep dockerd

On a standard systemd install the service starts dockerd -H fd://: systemd creates the socket from docker.socket, whose upstream unit sets SocketUser=root, SocketGroup=docker and SocketMode=0660, and hands it to the daemon. When dockerd creates a unix:// socket itself, the group comes from --group (or the "group" key in daemon.json), default docker. Find out which case you are in before changing anything.

2. Remove one user from one group

sudo gpasswd -d trainee docker
getent group docker

gpasswd -d deletes the user from the named group only. Avoid usermod -G for this: it replaces the whole supplementary list and silently drops every group you forget to list. Existing login sessions keep the old membership until the user logs in again, so test from a fresh session.

3. Change the socket's group (socket-activated case)

Suppose policy says only members of a dedicated dockerops group may use Docker. Create a drop-in rather than editing the vendor unit:

sudo groupadd dockerops
sudo systemctl edit docker.socket
#   [Socket]
#   SocketGroup=dockerops
sudo systemctl daemon-reload
sudo systemctl restart docker.socket docker.service
ls -l /run/docker.sock

The listing should now show dockerops as the group. If dockerd creates the socket itself, the equivalent knob is the daemon's group setting instead.

4. Find and remove TCP exposure

A TCP listener can come from -H tcp://... in the unit (often a drop-in from systemctl edit) or from a "hosts" array in /etc/docker/daemon.json. Never set the same option in both places: Docker refuses to start when an option appears as a flag and in the file, even with identical values. Because the stock unit already passes -H fd://, adding "hosts" to daemon.json on a systemd host produces exactly that conflict. Check a file before restarting:

sudo dockerd --validate --config-file /etc/docker/daemon.json

After removing the TCP entry from wherever it lives, run systemctl daemon-reload if a unit changed, restart Docker, and repeat the ss check: no line for dockerd means no TCP listener.

Common mistakes

Example checkEvidence
User no longer in groupgetent group docker omits the user; other groups intact in id
Socket ownershipGroup column of ls -l /run/docker.sock
No TCP APIss -ltnp shows no dockerd listener
Daemon healthysystemctl is-active docker and docker info as root succeed

Cleanup: revert with sudo systemctl revert docker.socket, re-add the user if you need it, or discard the VM. References: Docker daemon attack surface, Configure remote access for Docker daemon, dockerd reference, Linux post-installation steps. Next, try kubelet hardening or Dockerfile best practices.

Exam
CKS
Domain
System Hardening
Grading
Programmatic · partial credit

What this tests

Reduce the host attack surface with AppArmor, seccomp, and kernel hardening. On the CKS exam, System Hardening tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.

Practice it for real

The public description lets you study the task before signing up. Full access includes this live lab; the selected Task of the Week is free with an account. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.