instruction: How do you implement comprehensive container security scanning?
output: Isolate containers with a user namespace | Docker Docs Get started Guides Manuals Reference Ask&nbsp;AI { switch(e.key) { case 'k': if (e.metaKey || e.ctrlKey) { e.preventDefault(); $el.focus(); } break; } }" tabindex=0> Start typing to search or try Ask AI . Contact support { localStorage.setItem('theme-preference', value); document.firstElementChild.className = value; })" @click="theme = (theme === 'dark' ? 'light' : 'dark')"> { const container = $el; // The div with overflow const item = document.getElementById('sidebar-current-page') if (item) { const containerTop = container.scrollTop; const containerBottom = containerTop + container.clientHeight; const itemTop = item.offsetTop - container.offsetTop; const itemBottom = itemTop + item.offsetHeight; // Scroll only if the item is out of view if (itemBottom > containerBottom - 200) { container.scrollTop = itemTop - (container.clientHeight / 2 - item.offsetHeight / 2); } } })" class="bg-background-toc dark:bg-background-toc fixed top-0 z-40 hidden h-screen w-full flex-none overflow-x-hidden overflow-y-auto md:sticky md:top-16 md:z-auto md:block md:h-[calc(100vh-64px)] md:w-[320px]" :class="{ 'hidden': ! $store.showSidebar }"> Back Ask&nbsp;AI { switch(e.key) { case 'k': if (e.metaKey || e.ctrlKey) { e.preventDefault(); $el.focus(); } break; } }" tabindex=0> Start typing to search or try Ask AI . Contact support { localStorage.setItem('theme-preference', value); document.firstElementChild.className = value; })" @click="theme = (theme === 'dark' ? 'light' : 'dark')"> Manuals Get started Guides Reference Open source Docker Engine Install Ubuntu Debian RHEL Fedora Raspberry Pi OS (32-bit) CentOS SLES (s390x) Binaries Post-installation steps Storage Volumes Bind mounts tmpfs mounts Storage drivers Select a storage driver BTRFS storage driver Device Mapper storage driver (deprecated) OverlayFS storage driver VFS storage driver windowsfilter storage driver ZFS storage driver containerd image store Networking Packet filtering and firewalls Network drivers Bridge network driver Host network driver IPvlan network driver Macvlan network driver None network driver Overlay network driver Tutorials Networking using a macvlan network Networking using the host network Networking with overlay networks Networking with standalone containers CA certificates Legacy container links Containers Start containers automatically Run multiple processes in a container Resource constraints Runtime metrics Running containers CLI Completion Proxy configuration Filter commands Format command and log output OpenTelemetry for the Docker CLI Daemon Start the daemon Use IPv6 networking Daemon proxy configuration Live restore Alternative container runtimes Collect Docker metrics with Prometheus Configure remote access for Docker daemon Read the daemon logs Troubleshooting the Docker daemon Manage resources Docker contexts Docker object labels Prune unused Docker objects Logs and metrics Configure logging drivers Customize log driver output Logging drivers Amazon CloudWatch Logs logging driver ETW logging driver Fluentd logging driver Google Cloud Logging driver Graylog Extended Format logging driver Journald logging driver JSON File logging driver Local file logging driver Splunk logging driver Syslog logging driver Use a logging driver plugin Use docker logs with remote logging drivers Security Rootless mode Antivirus software and Docker AppArmor security profiles for Docker Content trust in Docker Automation with content trust Delegations for content trust Deploy Notary Server with Compose Manage keys for content trust Play in a content trust sandbox Docker security non-events Isolate containers with a user namespace Protect the Docker daemon socket Seccomp security profiles for Docker Verify repository client with certificates Swarm mode Administer and maintain a swarm of Docker Engines Deploy a stack to a swarm Deploy services to a swarm Getting started with Swarm mode Create a swarm Add nodes to the swarm Deploy a service to the swarm Inspect a service on the swarm Scale the service in the swarm Delete the service running on the swarm Apply rolling updates to a service Drain a node on the swarm How swarm works How nodes work How services work Manage swarm security with public key infrastructure (PKI) Swarm task states Join nodes to a swarm Lock your swarm to protect its encryption key Manage nodes in a swarm Manage sensitive data with Docker secrets Manage swarm service networks Raft consensus in swarm mode Run Docker Engine in swarm mode Store configuration data using Docker Configs Swarm mode key concepts Use Swarm mode routing mesh Deprecated features Docker Engine plugins Access authorization plugin Docker log driver plugins Docker network driver plugins Docker Plugin API Docker volume plugins Plugin Config Version 1 of Plugin V2 Use Docker Engine plugins Release notes Engine v28 Engine v27 Engine v26.1 Engine v26.0 Engine v25.0 Engine v24.0 Engine v23.0 Engine v20.10 Engine v19.03 Engine v18.09 Engine v18.06 Engine v18.05 Engine v18.04 Engine v18.03 Engine v18.02 Engine v18.01 Engine v17.12 Engine v17.11 Engine v17.10 Engine v17.09 Engine v17.07 Engine v17.06 Engine v17.05 Engine v17.04 Engine v17.03 Prior releases Docker Build Core concepts Docker Build Overview Dockerfile overview Build context Building Multi-stage Variables Secrets Multi-platform Export binaries Container Device Interface (CDI) Best practices Base images Build checks New Builders Build drivers Docker container driver Docker driver Kubernetes driver Remote driver Manage builders Bake Introduction Targets Inheritance Variables Expressions Functions Matrix targets Contexts Bake file reference Bake standard library functions Building with Bake from a Compose file Overriding configurations Remote Bake file definition Cache Build cache invalidation Build garbage collection Cache storage backends Amazon S3 cache Azure Blob Storage cache GitHub Actions cache Inline cache Local cache Registry cache Optimize cache usage in builds CI GitHub Actions Annotations Attestations Build checks Build secrets Build summary BuildKit configuration Cache management Copy image between registries Export to Docker Local registry Multi-platform image Named contexts Push to multiple registries Reproducible builds Share image between jobs Tags and labels Test before push Update Docker Hub description Metadata Annotations Build attestations Image attestation storage Provenance attestations SBOM attestations SLSA definitions Exporters Image and registry exporters Local and tar exporters OCI and Docker exporters BuildKit buildkitd.toml Configure BuildKit Custom Dockerfile syntax Dockerfile release notes Debugging OpenTelemetry support Build release notes Docker Compose Introduction to Compose How Compose works Why use Compose? History and development Install Plugin Standalone Uninstall Quickstart How-tos Specify a project name Use lifecycle hooks Use service profiles Control startup order Use environment variables Set environment variables Environment variables precedence Pre-defined environment variables Interpolation Best practices Build dependent images Use Compose Watch Secrets in Compose Networking Use multiple Compose files Merge Extend Include Enable GPU support Use Compose in production OCI artifact applications New Use provider services New Compose Bridge Usage Customize Support and feedback FAQs Give feedback Sample apps Releases Release notes Migrate to Compose v2 MCP Gateway Testcontainers AI Ask Gordon Beta Model Context Protocol (MCP) Built-in tools in Gordon Configure MCP servers with YAML Model Runner Beta Get started with DMR DMR REST API DMR examples MCP Catalog and Toolkit Beta MCP Catalog MCP Toolkit Hub MCP server AI and Docker Compose Use AI models in Compose New Products Docker Desktop Setup Install Mac Mac permission requirements Windows Windows permission requirements Linux Ubuntu Debian Fedora Arch RHEL VM or VDI environments Sign in Allowlist Explore Docker Desktop Containers Images Volumes Builds Resource Saver mode Pause Docker Desktop Features and capabilities Networking GPU support USB/IP support Deploy on Kubernetes Synchronized file shares containerd image store Wasm workloads Beta Docker Desktop CLI Virtual Machine Manager WSL Best practices Custom kernels on WSL Use WSL Settings and maintenance Change settings Backup and restore data Troubleshoot and support Troubleshoot and diagnose Common topics Known issues Get support for Docker Desktop FAQs General Mac Windows Linux Releases Give feedback Uninstall Fix startup issue for Mac Release notes Docker Hardened Images New Quickstart About Hardened images Image types Image testing Responsibility overview Features Flexibility Continuous patching Enterprise support Hardened, secure images Seamless integration How-tos Explore images Mirror an image Customize an image Use an image Verify an image Manage images Scan an image Enforce image usage Migrate an app Debug a container Core concepts Attestations CIS Benchmark Code signing CVEs Distroless images FIPS glibc and musl Hardening Image digests Image provenance Immutability SBOMs SLSA Software Supply Chain Security SSDLC STIG VEX Troubleshoot Docker Offload Beta Quickstart About Configure Usage & billing Optimize usage Troubleshoot Give feedback Docker Build Cloud Setup Usage Continuous integration Optimization Builder settings Release notes Docker Hub Quickstart Library Search Trusted content Catalogs Mirror Repositories Create Manage Repository information Access Images Tags Immutable tags Image Management Software artifacts Push images Move images Image security insights Webhooks Automated builds Set up Link accounts Automated repository tests Advanced options Manage autobuilds Troubleshoot Trusted content Docker Official Images Docker Verified Publisher Program Docker-Sponsored Open Source Program Insights and analytics Archive Delete Personal settings Usage and limits Pulls Optimize usage Service accounts Troubleshoot Release notes Docker Scout Install Quickstart Explore Dashboard Docker Scout image analysis Docker Scout metrics exporter Image details view Manage vulnerability exceptions How-tos Create an exception using the GUI Create an exception using the VEX Docker Scout environment variables Docker Scout SBOMs Use Scout with different artifact types Deep dive Advisory database sources and matching service Data collection and storage in Docker Scout Policy Evaluation Configure policies Docker Scout health scores Evaluate policy compliance in CI Remediation with Docker Scout View Docker Scout policy status Integrations Code quality SonarQube Container registries Amazon ECR Azure Container Registry Continuous Integration Azure DevOps Pipelines Circle CI GitHub Actions GitLab CI/CD Jenkins Integrating Docker Scout with environments Generic (CLI) Sysdig Source code management GitHub Team collaboration Slack Release notes CLI release notes Platform release notes Docker for GitHub Copilot EA Install Usage Example prompts Docker Extensions Marketplace extensions Non-marketplace extensions Configure a private marketplace Settings and feedback Extensions SDK The build and publish process Quickstart Part one: Build Create a simple extension Create an advanced frontend extension Add a backend to your extension Part two: Publish Add labels Validate Package and release your extension Share your extension Publish in the Marketplace Build multi-arch extensions Architecture Metadata Security Design and UI styling Guidelines Docker design principles MUI best practices Developer Guides Authentication Interacting with Kubernetes Invoke host binaries Use the Docker socket Developer SDK tools Test and debug Continuous Integration (CI) CLI reference Extension APIs Dashboard Docker Extension Backend Extension UI API Navigation Testcontainers Cloud Deprecated products and features Release lifecycle Platform Billing Add or update a payment method Manage your billing information 3D Secure authentication View billing history Change your billing cycle Submit a tax exemption certificate FAQs Docker accounts Accounts Create an account Manage an account Deactivate an account Security Personal access tokens Two-factor authentication Recover your Docker account FAQs General Container Network and VM Single sign-on General Domains Enforcement Identity providers User management Security announcements Subscription Subscriptions and features Set up your subscription Scale your subscription Manage seats Change your subscription Docker Desktop license agreement FAQs Release notes Enterprise Administration Organization administration Create your organization Onboard your organization Manage organization members Convert an account into an organization Create and manage a team Deactivate an organization Manage Docker products Activity logs Organization information Insights Company administration overview Create a company Manage company members Manage company organizations Manage company owners FAQ Organization Company Deploy Docker Desktop MSI installer PKG installer MS Store Deploy with Intune Deploy with Jamf Pro Microsoft Dev Box FAQs Security Single sign-on Configure Connect Manage Provision Just-in-Time SCIM Group mapping Enforce sign-in Configure Roles and permissions Manage domains Hardened Docker Desktop Enhanced Container Isolation Enable ECI Configure advanced settings Limitations FAQs Settings Management Use a JSON file Use the Admin Console Desktop settings reporting Settings reference Registry Access Management Image Access Management Air-gapped containers Organization access tokens Troubleshoot Troubleshoot provisioning Troubleshoot SSO Home / Manuals / Docker Engine / Security / Isolate containers with a user namespace Isolate containers with a user namespace Page options Copy page as Markdown for LLMs View page as plain text Ask questions with Docs AI Claude Open in Claude Table of contents About remapping and subordinate user and group IDs Prerequisites Enable userns-remap on the daemon Disable namespace remapping for a container User namespace known limitations Linux namespaces provide isolation for running processes, limiting their access to system resources without the running process being aware of the limitations. For more information on Linux namespaces, see Linux namespaces . The best way to prevent privilege-escalation attacks from within a container is to configure your container's applications to run as unprivileged users. For containers whose processes must run as the root user within the container, you can re-map this user to a less-privileged user on the Docker host. The mapped user is assigned a range of UIDs which function within the namespace as normal UIDs from 0 to 65536, but have no privileges on the host machine itself. About remapping and subordinate user and group IDs The remapping itself is handled by two files: /etc/subuid and /etc/subgid . Each file works the same, but one is concerned with the user ID range, and the other with the group ID range. Consider the following entry in /etc/subuid : ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> testuser:231072:65536 This means that testuser is assigned a subordinate user ID range of 231072 and the next 65536 integers in sequence. UID 231072 is mapped within the namespace (within the container, in this case) as UID 0 ( root ). UID 231073 is mapped as UID 1 , and so forth. If a process attempts to escalate privilege outside of the namespace, the process is running as an unprivileged high-number UID on the host, which does not even map to a real user. This means the process has no privileges on the host system at all. Note It is possible to assign multiple subordinate ranges for a given user or group by adding multiple non-overlapping mappings for the same user or group in the /etc/subuid or /etc/subgid file. In this case, Docker uses only the first five mappings, in accordance with the kernel's limitation of only five entries in /proc/self/uid_map and /proc/self/gid_map . When you configure Docker to use the userns-remap feature, you can optionally specify an existing user and/or group, or you can specify default . If you specify default , a user and group dockremap is created and used for this purpose. Warning Some distributions do not automatically add the new group to the /etc/subuid and /etc/subgid files. If that's the case, you may have to manually edit these files and assign non-overlapping ranges. This step is covered in Prerequisites . It is very important that the ranges do not overlap, so that a process cannot gain access in a different namespace. On most Linux distributions, system utilities manage the ranges for you when you add or remove users. This re-mapping is transparent to the container, but introduces some configuration complexity in situations where the container needs access to resources on the Docker host, such as bind mounts into areas of the filesystem that the system user cannot write to. From a security standpoint, it is best to avoid these situations. Prerequisites The subordinate UID and GID ranges must be associated with an existing user, even though the association is an implementation detail. The user owns the namespaced storage directories under /var/lib/docker/ . If you don't want to use an existing user, Docker can create one for you and use that. If you want to use an existing username or user ID, it must already exist. Typically, this means that the relevant entries need to be in /etc/passwd and /etc/group , but if you are using a different authentication back-end, this requirement may translate differently. To verify this, use the id command: ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> $ id testuser uid=1001(testuser) gid=1001(testuser) groups=1001(testuser) The way the namespace remapping is handled on the host is using two files, /etc/subuid and /etc/subgid . These files are typically managed automatically when you add or remove users or groups, but on some distributions, you may need to manage these files manually. Each file contains three fields: the username or ID of the user, followed by a beginning UID or GID (which is treated as UID or GID 0 within the namespace) and a maximum number of UIDs or GIDs available to the user. For instance, given the following entry: ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> testuser:231072:65536 This means that user-namespaced processes started by testuser are owned by host UID 231072 (which looks like UID 0 inside the namespace) through 296607 (231072 + 65536 - 1). These ranges should not overlap, to ensure that namespaced processes cannot access each other's namespaces. After adding your user, check /etc/subuid and /etc/subgid to see if your user has an entry in each. If not, you need to add it, being careful to avoid overlap. If you want to use the dockremap user automatically created by Docker, check for the dockremap entry in these files after configuring and restarting Docker. If there are any locations on the Docker host where the unprivileged user needs to write, adjust the permissions of those locations accordingly. This is also true if you want to use the dockremap user automatically created by Docker, but you can't modify the permissions until after configuring and restarting Docker. Enabling userns-remap effectively masks existing image and container layers, as well as other Docker objects within /var/lib/docker/ . This is because Docker needs to adjust the ownership of these resources and actually stores them in a subdirectory within /var/lib/docker/ . It is best to enable this feature on a new Docker installation rather than an existing one. Along the same lines, if you disable userns-remap you can't access any of the resources created while it was enabled. Check the limitations on user namespaces to be sure your use case is possible. Enable userns-remap on the daemon You can start dockerd with the --userns-remap flag or follow this procedure to configure the daemon using the daemon.json configuration file. The daemon.json method is recommended. If you use the flag, use the following command as a model: ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> $ dockerd --userns-remap = &#34;testuser:testuser&#34; Edit /etc/docker/daemon.json . Assuming the file was previously empty, the following entry enables userns-remap using user and group called testuser . You can address the user and group by ID or name. You only need to specify the group name or ID if it is different from the user name or ID. If you provide both the user and group name or ID, separate them by a colon ( : ) character. The following formats all work for the value, assuming the UID and GID of testuser are 1001 : testuser testuser:testuser 1001 1001:1001 testuser:1001 1001:testuser ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> { &#34;userns-remap&#34; : &#34;testuser&#34; } Note To use the dockremap user and have Docker create it for you, set the value to default rather than testuser . Save the file and restart Docker. If you are using the dockremap user, verify that Docker created it using the id command. ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> $ id dockremap uid=112(dockremap) gid=116(dockremap) groups=116(dockremap) Verify that the entry has been added to /etc/subuid and /etc/subgid : ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> $ grep dockremap /etc/subuid dockremap:231072:65536 $ grep dockremap /etc/subgid dockremap:231072:65536 If these entries are not present, edit the files as the root user and assign a starting UID and GID that is the highest-assigned one plus the offset (in this case, 65536 ). Be careful not to allow any overlap in the ranges. Verify that previous images are not available using the docker image ls command. The output should be empty. Start a container from the hello-world image. ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> $ docker run hello-world Verify that a namespaced directory exists within /var/lib/docker/ named with the UID and GID of the namespaced user, owned by that UID and GID, and not group-or-world-readable. Some of the subdirectories are still owned by root and have different permissions. ]\s+/gm, '')); copying = true; setTimeout(() => copying = false, 2000);"> $ sudo ls -ld /var/lib/docker/231072.231072/ drwx------ 11 231072 231072 11 Jun 21 21:19 /var/lib/docker/231072.231072/ $ sudo ls -l /var/lib/docker/231072.231072/ total 14 drwx------ 5 231072 231072 5 Jun 21 21:19 aufs drwx------ 3 231072 231072 3 Jun 21 21:21 containers drwx------ 3 root root 3 Jun 21 21:19 image drwxr-x--- 3 root root 3 Jun 21 21:19 network drwx------ 4 root root 4 Jun 21 21:19 plugins drwx------ 2 root root 2 Jun 21 21:19 swarm drwx------ 2 231072 231072 2 Jun 21 21:21 tmp drwx------ 2 root root 2 Jun 21 21:19 trust drwx------ 2 231072 231072 3 Jun 21 21:19 volumes Your directory listing may have some differences, especially if you use a different container storage driver than aufs . The directories which are owned by the remapped user are used instead of the same directories directly beneath /var/lib/docker/ and the unused versions (such as /var/lib/docker/tmp/ in the example here) can be removed. Docker does not use them while userns-remap is enabled. Disable namespace remapping for a container If you enable user namespaces on the daemon, all containers are started with user namespaces enabled by default. In some situations, such as privileged containers, you may need to disable user namespaces for a specific container. See user namespace known limitations for some of these limitations. To disable user namespaces for a specific container, add the --userns=host flag to the docker container create , docker container run , or docker container exec command. There is a side effect when using this flag: user remapping will not be enabled for that container but, because the read-only (image) layers are shared between containers, ownership of the containers filesystem will still be remapped. What this means is that the whole container filesystem will belong to the user specified in the --userns-remap daemon config ( 231072 in the example above). This can lead to unexpected behavior of programs inside the container. For instance sudo (which checks that its binaries belong to user 0 ) or binaries with a setuid flag. User namespace known limitations The following standard Docker features are incompatible with running a Docker daemon with user namespaces enabled: Sharing PID or NET namespaces with the host ( --pid=host or --network=host ). External (volume or storage) drivers which are unaware or incapable of using daemon user mappings. Using the --privileged mode flag on docker run without also specifying --userns=host . User namespaces are an advanced feature and require coordination with other capabilities. For example, if volumes are mounted from the host, file ownership must be pre-arranged if you need read or write access to the volume contents. While the root user inside a user-namespaced container process has many of the expected privileges of the superuser within the container, the Linux kernel imposes restrictions based on internal knowledge that this is a user-namespaced process. One notable restriction is the inability to use the mknod command. Permission is denied for device creation within the container when run by the root user. Edit this page Request changes Table of contents About remapping and subordinate user and group IDs Prerequisites Enable userns-remap on the daemon Disable namespace remapping for a container User namespace known limitations Product offerings Pricing About us Contribute Read llms.txt Cookies Settings Terms of Service Status Legal Copyright © 2013-2025 Docker Inc. All rights reserved.