Container security extends far beyond image scanning and network isolation. At the kernel level, three complementary security mechanisms — Seccomp, AppArmor, and Firejail — restrict what processes inside containers can actually do. These are not alternatives to each other but rather defense-in-depth layers that work together to create a robust container sandbox. Understanding how each mechanism works and how to manage them effectively is critical for running containers securely in production.
This guide explains how to create, manage, and deploy security profiles for containers using the Linux kernel’s built-in security frameworks. We compare Seccomp filters, AppArmor profiles, and Firejail sandboxes — three complementary approaches to restricting container process capabilities at the system call, file access, and user-space levels.
Understanding Container Security Layers
Containers share the host kernel, which means a compromised container process has the same kernel attack surface as any other host process. Linux provides several mechanisms to limit this attack surface:
| Layer | Mechanism | What It Restricts |
|---|---|---|
| System calls | Seccomp | Which syscalls a process can invoke |
| File/Network access | AppArmor | What files, capabilities, and network operations are permitted |
| Resource access | Namespaces + cgroups | Visibility into host resources and resource limits |
| User-space sandboxing | Firejail | Application-level restrictions (X11, devices, network) |
| Kernel isolation | gVisor/Kata | Separate kernel or microVM for complete isolation |
Seccomp and AppArmor are kernel-level mechanisms enforced by Linux itself. Firejail is a user-space sandboxing tool that uses namespaces, seccomp, and other kernel features under the hood but provides a simpler, application-oriented interface.
Seccomp (Secure Computing Mode)
Seccomp is a Linux kernel security feature that filters system calls made by a process. When a process enters seccomp mode, the kernel checks each system call against a Berkeley Packet Filter (BPF) program. If the syscall is not allowed, the kernel kills the process or returns an error.
Key Features
- Syscall filtering — whitelist or blacklist specific system calls
- BPF-based rules — highly efficient, compiled filter programs
- Docker integration — built-in seccomp profiles for containers
- Fine-grained control — filter by syscall, arguments, and return values
- Default deny mode — only explicitly allowed syscalls pass through
Default Docker Seccomp Profile
Docker ships with a default seccomp profile that blocks approximately 44 dangerous system calls while allowing the ~300 syscalls that typical applications need. This profile blocks syscalls like mount, umount, reboot, swapon, swapoff, ptrace, and kernel module loading.
| |
Custom Seccomp Profile
| |
Docker Compose with Seccomp
| |
AppArmor (Application Armor)
AppArmor is a Linux Security Module (LSM) that enforces Mandatory Access Control (MAC) policies on individual programs. Unlike seccomp, which filters system calls, AppArmor controls what files a process can access, what capabilities it can use, and what network operations it can perform — all defined through human-readable profile files.
Key Features
- Path-based access control — restrict file read/write/execute by path
- Network filtering — allow/deny specific network protocols and addresses
- Capability control — restrict Linux capabilities (CAP_NET_RAW, CAP_SYS_ADMIN)
- Include profiles — modular profile composition with abstractions
- Complain mode — log violations without enforcing (for testing)
- Enforce mode — actively block disallowed operations
- Docker integration — load AppArmor profiles at container startup
AppArmor Profile for a Web Container
| |
Docker Compose with AppArmor
| |
| |
Firejail
Firejail is a user-space SUID sandbox program that uses Linux namespaces, seccomp filters, and other kernel features to create restricted execution environments for applications. While Docker provides container-level isolation, Firejail operates at the application level, creating a sandbox around individual programs running on the host or inside containers.
Key Features
- 2,000+ pre-built profiles — profiles for browsers, media players, development tools
- Network isolation — private network namespaces with custom IP/MAC
- X11 sandboxing — prevent keyloggers and screen scrapers
- Filesystem isolation — whitelist/blacklist filesystem access with tmpfs overlays
- Seccomp integration — applies its own seccomp filters on top of the kernel
- No configuration needed —
firejail firefoxjust works - AppArmor integration — can enforce AppArmor profiles within the sandbox
Firejail Profile for a Container Application
| |
| |
Comparison Table
| Feature | Seccomp | AppArmor | Firejail |
|---|---|---|---|
| Level | Kernel syscall filter | Kernel MAC (LSM) | User-space sandbox |
| Primary Scope | System calls | File/network/capability access | Application execution |
| Configuration | JSON BPF profiles | Text profile files | CLI flags + profile files |
| Ease of Use | Complex (requires syscall knowledge) | Moderate (path-based rules) | Easy (pre-built profiles) |
| Docker Integration | Native (–security-opt seccomp) | Native (–security-opt apparmor) | Manual (run inside/outside) |
| Granularity | Syscall-level | Path + capability + network | Namespace + filesystem + network |
| Default Profiles | Docker default (44 blocked syscalls) | Docker default | 2,000+ application profiles |
| Audit Mode | Audit via strace/bpftrace | Complain mode (log only) | –audit flag |
| Performance Overhead | Minimal (BPF filter) | Low (LSM hooks) | Low (namespace isolation) |
| Cross-Distro | Yes (all Linux kernels) | Yes (AppArmor enabled kernels) | Yes (userspace tool) |
| Best For | Blocking dangerous syscalls | Fine-grained access control | Quick application sandboxing |
Defense-in-Depth Strategy
The most secure container deployments combine all three mechanisms:
- Seccomp — block dangerous system calls (mount, ptrace, kernel module loading)
- AppArmor — restrict file access to only what the application needs
- Firejail — add user-space isolation for applications running directly on the host
| |
Why Self-Host Your Container Security Profiles?
Managing seccomp and AppArmor profiles yourself gives you precise control over what each container can do. Cloud container platforms apply generic security profiles that may be either too permissive for your threat model or too restrictive for your application’s needs. By maintaining your own profiles, you can tailor syscall filters and access controls to each specific workload.
Self-hosted security profiles also support compliance requirements. Financial services, healthcare, and government regulations often mandate specific access controls and audit capabilities. Custom AppArmor profiles provide file-level access logging, while seccomp profiles ensure that only approved system calls can execute — both critical for demonstrating compliance during security audits.
The operational benefits extend to incident response. When a container is compromised, well-configured seccomp and AppArmor profiles limit the attacker’s ability to escalate privileges, access sensitive files, or establish reverse shells. An AppArmor profile that denies access to /etc/shadow and blocks raw network sockets significantly constrains what a compromised container process can achieve.
For teams managing dozens of containerized services, a centralized profile management system ensures consistency across environments. Store your seccomp profiles and AppArmor configurations in version control, audit changes through pull requests, and deploy updated profiles alongside application releases. This GitOps approach to container security means your security posture evolves with your application, rather than remaining a static configuration that quickly becomes outdated.
Why Self-Host Your Database Security and Routing Infrastructure?
For deeper container isolation, see our gVisor vs Kata Containers vs Firecracker sandboxing guide for kernel-level separation beyond seccomp. Our Docker Bench vs Trivy vs Checkov hardening guide covers broader container security practices. For runtime threat detection, the NeuVector vs Falco vs Tetragon comparison monitors for security violations after containers are deployed.
FAQ
What happens when a container violates a seccomp rule?
When a process in seccomp mode attempts a blocked system call, the kernel takes the action defined in the profile. The default action is typically SCMP_ACT_ERRNO (return an error code to the process) or SCMP_ACT_KILL (terminate the process immediately). Docker’s default profile uses SCMP_ACT_ERRNO, which causes the syscall to fail with EPERM (Operation not permitted) rather than killing the container. For maximum security, you can use SCMP_ACT_KILL to terminate any process that violates the seccomp policy.
Can I use AppArmor and seccomp together on the same container?
Yes, and you should. AppArmor and seccomp operate at different levels and complement each other. Seccomp filters system calls before they reach the kernel, while AppArmor controls what the process can access once the syscall is allowed. Using both provides defense-in-depth: seccomp blocks entire categories of syscalls, while AppArmor fine-tunes access within the allowed syscalls. Docker supports both simultaneously via --security-opt seccomp=... and --security-opt apparmor=....
How do I test an AppArmor profile before enforcing it?
AppArmor has a “complain mode” that logs policy violations without blocking the operation. Load your profile with sudo aa-complain /etc/apparmor.d/your-profile, run your application normally, then check the audit log with sudo journalctl -k | grep audit or sudo dmesg | grep DENIED. Once you are confident the profile allows all necessary operations, switch to enforce mode with sudo aa-enforce /etc/apparmor.d/your-profile.
Does Firejail work inside Docker containers?
Firejail can run inside containers, but it requires the container to have sufficient privileges (specifically, the ability to create new namespaces). Since most security-hardened containers drop capabilities and use restrictive seccomp profiles, Firejail may not function correctly. The more common pattern is to use Firejail for applications running directly on the host, while using Docker’s built-in seccomp and AppArmor support for containerized applications.
How do I find which syscalls my application needs for a custom seccomp profile?
Use strace to capture all system calls made by your application: strace -f -o syscall-log.txt your-command. Then extract unique syscall names from the log and add them to your seccomp profile’s allowlist. Alternatively, use the seccomp-tools gem (gem install seccomp-tools) to analyze existing profiles or generate new ones from strace output. Start with Docker’s default profile as a baseline and remove syscalls your application does not need.
What is the performance impact of seccomp and AppArmor on containers?
The performance impact is negligible for most workloads. Seccomp uses BPF filters that are compiled to native code and run in the kernel — the overhead is typically less than 1% for normal application workloads. AppArmor’s LSM hooks add minimal overhead, primarily on file access operations where path matching occurs. The only measurable impact is during application startup when profiles are loaded and initial path checks run. For high-throughput network services, neither seccomp nor AppArmor will be a bottleneck.