Mastering Docker Seccomp & AppArmor Profiles (9770)
Introduction
Container security is no longer optional. As workloads move from VMs to Kubernetes, the attack surface shifts to the Linux kernel interface. Seccomp (secure computing mode) and AppArmor (application armor) are the two primary Linux Security Modules (LSMs) that Docker leverages to restrict what a container can do. This article walks you through designing, testing, and deploying custom profiles for production‑grade workloads—specifically targeting database engines (PostgreSQL, MySQL, MongoDB) that demand both performance and strict isolation.
Seccomp Deep Dive
Syscall Filtering Mechanics
Seccomp operates at the kernel level, intercepting each system call before execution. A profile is a JSON document that defines a defaultAction (allow, trap, kill, etc.) and a list of syscalls with per‑call actions. The kernel evaluates rules in order; the first match wins.
Profile Structure
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86"],
"syscalls": [
{"names": ["read", "write", "openat"], "action": "SCMP_ACT_ALLOW"},
{"names": ["ptrace", "process_vm_readv"], "action": "SCMP_ACT_KILL"}
]
}Use docker run --security-opt seccomp=profile.json to attach.
AppArmor Deep Dive
Path‑Based Confinement
AppArmor profiles are textual rulesets that confine an application to a specific set of filesystem paths, capabilities, and network families. Unlike Seccomp, AppArmor understands what the process tries to access, not just how it asks the kernel.
Profile Example for PostgreSQL
#include
profile docker-postgresql {
#include
#include
capability setgid,
capability setuid,
/var/lib/postgresql/** rw,
/run/postgresql/** rw,
/etc/postgresql/** r,
/usr/lib/postgresql/** mr,
network inet stream,
deny /proc/** w,
deny /sys/** w,
} Load with apparmor_parser -r /etc/apparmor.d/docker-postgresql and run docker run --security-opt apparmor=docker-postgresql.
Building Profiles in CI/CD
Automate profile generation with syscall‑exporter (eBPF) to record syscalls during integration tests, then feed the trace into oci‑seccomp‑gen to produce a minimal allow‑list. For AppArmor, use aa‑logprof on staged audit logs. Store profiles as artifacts and inject them at deploy time via Helm values or Kustomize patches.
eBPF/XDP kernel filter evaluates TCP/UDP frames directly on server NIC.
Testing & Debugging
- Seccomp: Use
strace -f -e trace=allinside the container; denied syscalls returnEPERM. - AppArmor: Check
dmesg | grep apparmororaa-statusfor violations. - Integration: Run
docker run --security-opt seccomp=unconfined --security-opt apparmor=unconfinedto baseline, then re‑apply profiles and compare.
Best Practices & Pitfalls
- Start permissive, then tighten. Use
SCMP_ACT_LOGto audit before enforcing. - Version pin profiles. Store them alongside Dockerfiles; treat as code.
- Avoid over‑blocking. Database engines need
futex,epoll,io_uring(if enabled). - Combine with capabilities. Drop
ALLand add only required caps. - Monitor in production. Export Seccomp/AppArmor events to Prometheus via
node_exporter+auditd.
Conclusion
Mastering Seccomp and AppArmor transforms Docker from a convenient packaging format into a hardened runtime. By codifying syscall and filesystem policies, you gain defense‑in‑depth that survives kernel exploits and supply‑chain compromises. The profiles showcased here are battle‑tested on high‑throughput PostgreSQL clusters running on Votion Cloud’s bare‑metal nodes—delivering sub‑millisecond overhead while eliminating entire classes of container breakout attacks.