Container and Docker Guide
Overview
Running Ansible Lockdown roles in containerized environments requires special considerations. Containers differ from traditional VMs or bare-metal systems in several important ways that affect security benchmarking and remediation.
Warning
Security benchmarks (CIS and STIG) are primarily designed for traditional operating systems, not containers. Many controls may not apply or could break container functionality. Always test thoroughly in non-production environments.
Container Detection
The Linux remediation roles include automatic container detection to skip controls that are
incompatible with containerized environments. This is controlled through the system_is_container
variable.
Automatic Detection
The roles treat the target as a container when either of these is true:
The Ansible connection is
docker(some roles also acceptcommunity.docker.docker)The
virtualization_typefact isdocker,lxc,openvz,podmanorcontainer
When detection fires, the role sets system_is_container: true and loads the container rule set
from vars/is_container.yml (the file name is set by container_vars_file).
Manual Override
system_is_container is defined in each role’s vars/main.yml, which outranks playbook and
inventory variables. To force it, pass it as an extra var:
ansible-playbook site.yml -e system_is_container=true
This only gates the tasks that test system_is_container. To apply the container rule set as well,
also pass the role’s file (for example -e @vars/is_container.yml), or connect with the docker
connection so detection runs.
Controls Skipped in Containers
When running in container mode, certain controls are automatically skipped because they:
Require kernel-level access (not available in containers)
Depend on systemd services (containers typically use a single process)
Modify boot configurations (containers don’t boot traditionally)
Require hardware access (containers are abstracted from hardware)
Common Skipped Categories:
The exact set differs per role; see the role’s vars/is_container.yml. Typical categories are:
Bootloader configuration and the kernel command line
Separate partitions and mount options
Kernel module management
auditd configuration (requires host kernel support)
Firewall rules (managed at host level)
SELinux or AppArmor
Time synchronization (most roles; handled by the host)
Running Audit in Containers
Audit from Host Against Container
You can also audit a running container from the host using the community.docker.docker_container_exec module.
The audit content sits at {audit_conf_dest}/{benchmark}-Audit, which defaults to /opt/RHEL10-CIS-Audit for RHEL10-CIS:
- hosts: localhost
connection: local
tasks:
- name: Run audit against container
community.docker.docker_container_exec:
container: my_container
command: /opt/RHEL10-CIS-Audit/run_audit.sh
Running Remediation in Containers
Building Hardened Container Images
The recommended approach is to build hardened base images rather than remediating running containers. Run the role against a build container through the docker connection, then commit that container as your image:
# playbook for building hardened images
- hosts: image_build_container
connection: community.docker.docker
roles:
- role: RHEL10-CIS
Remediating Running Containers
While not recommended for production, you can remediate running containers for testing:
- hosts: container_hosts
connection: docker
vars:
# Example: skip an individual control
# (the container rule set already disables bootloader controls such as this one)
rhel10cis_rule_1_4_1: false
roles:
- RHEL10-CIS
Warning
Running privileged containers for auditing requires careful consideration of your security requirements. Limit access and use RBAC appropriately.
Known Limitations
Controls That Cannot Work in Containers:
Category |
Reason |
Alternative |
|---|---|---|
Bootloader (GRUB) |
Containers don’t have bootloaders |
Apply to host OS |
Kernel parameters (sysctl) |
Requires host kernel access (disabled in some roles) |
Apply to host OS |
Partition mounts |
Container filesystems are overlays |
Use read-only containers |
auditd rules |
Requires host auditd |
Use container runtime logging |
Firewall (iptables/nftables) |
Managed at host/orchestrator level |
Use network policies |
Time sync (chrony/ntp) |
Containers use host time (disabled in most roles) |
Apply to host OS |
auditd in Containers:
The auditd subsystem requires kernel-level access. For container environments:
Configure auditd on the container host
Use container runtime audit logging (Docker audit, containerd events)
Best Practices
Harden the Host First Apply full CIS/STIG benchmarks to container hosts before focusing on containers.
Use Minimal Base Images Start with a minimal image of the distribution the role targets (for example UBI-minimal or Rocky minimal for the RHEL roles) to reduce attack surface.
Build Immutable Images Apply hardening at image build time, not runtime. Treat containers as immutable.
Scan Images in CI/CD Integrate audit into your image build pipeline to catch issues before deployment.
Troubleshooting
Playbook fails on service tasks in a container
Containers without systemd cannot start or enable services. Check that container detection ran, or force container mode as described under Manual Override:
ansible-playbook site.yml -e system_is_container=true
Audit shows many failures for kernel controls
Container audits will fail kernel-related checks by design. Filter results:
# Show only non-skipped results
jq '.results[] | select(.skipped != true)' audit_output.json
Permission denied errors
Containers may need elevated privileges for certain audits:
docker run --privileged --pid=host your-audit-image
Note
Running privileged containers should only be done in controlled environments for auditing purposes.