Running containers safely
Containers isolate processes. They do not isolate them from a misconfiguration, and two Docker defaults surprise people badly.
The docker socket is root
Anyone who can talk to /var/run/docker.sock can start a container that
mounts the host filesystem and become root on the machine. That means:
- Membership of the
dockergroup is equivalent to root. Grant it as deliberately as you grant sudo. - Never mount the socket into a container unless you fully accept that the container is now root on the host. Many monitoring and CI images ask for it.
- Never expose the Docker API on a TCP port. If you must, mutual TLS and a firewall, and think again first.
Docker rewrites your firewall
Publishing a port with -p 3306:3306 inserts rules that bypass your
ufw or firewalld configuration. Your firewall says the port is closed; the world
disagrees. This is how databases in containers end up exposed.
Bind to localhost explicitly:
-p 127.0.0.1:3306:3306
Then check from outside, every time — see firewalling your
server. ss -ltnp on the host tells you what is really listening.
Do not run as root inside
Most images default to root. Add a user in the Dockerfile and
USER app, or at runtime:
--user 1000:1000
Then take away what is left:
--cap-drop=ALL --cap-add=NET_BIND_SERVICE
--security-opt no-new-privileges
--read-only --tmpfs /tmp
A read-only root filesystem stops an intruder writing a payload at all, and most
applications work fine with a writable /tmp and one data volume.
Limit resources
--memory=2g --cpus=2 --pids-limit=200
Without limits, one container can take the whole machine — a fork bomb, a leak, a runaway build. See swap and the OOM killer.
Images
- Pin versions.
:latestmeans your rebuild next month is a different application. - Small base images: fewer packages, fewer vulnerabilities.
- Scan them —
trivy image yourimage— and act on the output. - No secrets in the image. Layers are permanent and anyone who can pull it can read them; see managing secrets.
- Rebuild regularly. An image built six months ago contains six months of unpatched libraries.
Rootless, where you can
Rootless Docker and Podman run the whole runtime as an unprivileged user, which removes the socket problem entirely. Some things are harder — low ports, some networking — but for most application workloads it is a straightforward win. See Docker on your server for the basics.
Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base