Stop Trusting Defaults: A Guide to Container Hardening
If you are running docker run in production without flags, you are likely one kernel exploit away from a data breach. It is February 2020, and while container adoption in Oslo and across Scandinavia is skyrocketing, security practices are lagging dangerously behind. I see it every week: a perfectly architected microservices backend running on a Node.js image with 700 known vulnerabilities, executing as root.
Container isolation is not a silver bullet. It is a process boundary. If that boundary breaks, the attacker is on your host. In a shared hosting environment, that's bad. On a dedicated VPS, it's catastrophic. Here is how we lock down containers at the infrastructure and runtime level, keeping the Datatilsynet auditors happy and your data safe.
1. The Base Image: Less is More
The first rule of fight club is you do not use :latest. The second rule is you stop using full OS images for single-binary applications. An Ubuntu 18.04 base image is 64MB and contains libraries you will never use. Those libraries are attack vectors.
We strictly recommend Alpine Linux (currently v3.11) or Google's Distroless images. They strip the OS down to the bare minimum.
Pinning by Digest
Tags are mutable. node:12-alpine changes every time the maintainer pushes an update. To ensure your build on Tuesday matches your build on Friday, pin by SHA256 digest.
# Instead of FROM node:12-alpine
FROM node@sha256:36c92751d283692e9e7352331b676...
# Create a non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
WORKDIR /home/appuser
Pro Tip: Using a non-root user inside the Dockerfile is step one. But you must also ensure your host volumes have the correct permissions, or your container will crash immediately on startup. We see this constantly when clients migrate to our CoolVDS NVMe storage blocks. Permission denied errors usually mean you did the security part right, but the operational part wrong.
2. Runtime Privileges: Drop 'Em All
By default, Docker grants a significant number of capabilities to a container. Most web apps need exactly zero of them. You should operate on a whitelist basis: drop everything, then add back only what is necessary.
If you are running a standard Nginx reverse proxy, you might need NET_BIND_SERVICE to bind to port 80. If you are running a Python worker, you probably need nothing.
Here is how a hardened run command looks:
docker run -d \
--read-only \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--security-opt=no-new-privileges \
--name web-app \
my-secure-image:1.0.4
The --read-only flag is the unsung hero here. It forces the container's root filesystem to be immutable. If an attacker manages to exploit a vulnerability in your code to execute a shell, they cannot download a crypto-miner or modify system files because the disk refuses to write.
3. Kubernetes: The Wild West of YAML
For those of you managing clusters (whether self-hosted on CoolVDS instances or managed), Kubernetes v1.17 introduced stable features that you must be using. The most critical is the PodSecurityPolicy (PSP).
A PSP is a cluster-level resource that controls security sensitive aspects of the pod specification. It stops a developer from accidentally deploying a "privileged" container that can access the host's devices.
Enforcing Network Isolation
By default, all pods in a K8s cluster can talk to all other pods. In a multi-tenant environment, or even just a complex microservices architecture, this is dangerous. Use NetworkPolicies to lock down traffic.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
This policy creates a "default deny" firewall rule for the namespace. You then whitelist specific traffic paths. Itβs tedious to set up, but essential for compliance with strict data privacy laws here in Europe.
4. The Infrastructure Layer: Why Hardware Matters
Software limits (cgroups and namespaces) are good, but hardware isolation is better. This is where your choice of hosting provider directly impacts your security posture.
Many "cloud" providers oversell their CPU cycles. This creates the "noisy neighbor" effect. But more importantly, shared kernels in some container-as-a-service platforms mean a kernel panic triggered by Neighbor A brings down Neighbor B (you).
At CoolVDS, we advocate for running your container hosts on isolated KVM instances. KVM provides a hardware virtualization layer that containers lack. If you are handling sensitive Norwegian user data (GDPR), relying solely on Docker namespaces is a risk. You want that extra hypervisor barrier.
Disk I/O and Security Scanning
Security isn't just about walls; it's about visibility. You should be scanning images for CVEs using tools like Clair or Trivy (which is gaining serious traction recently). These scans are I/O intensive.
trivy image python:3.4-alpine
Running daily scans on slow spinning rust disks will kill your CI/CD pipeline performance. This is why we standardized on NVMe storage for all CoolVDS instances. High IOPS allows you to run deep security audits during the build process without slowing down deployment velocity.
5. Audit Your Host
Finally, your containers are only as secure as the host OS. Keep your Ubuntu 18.04 or CentOS 7 hosts patched. Use the Docker Bench for Security script to audit your host configuration automatically.
git clone https://github.com/docker/docker-bench-security.git
cd docker-bench-security
sh docker-bench-security.sh
You will get a score. If it is not above 80%, you have work to do.
Summary
Security is not a product; it is a configuration state. By using minimal base images, dropping capabilities, enforcing read-only filesystems, and isolating your workloads on robust KVM-based VPS infrastructure, you mitigate 99% of automated attacks.
Don't let a default config be your downfall. If you need a sandbox to test these configurations without risking your production cluster, deploy a high-performance instance on CoolVDS today. Our networks are optimized for low latency across Northern Europe, giving you the response times you need with the security you demand.