Run it with no network, a read only filesystem, a small writable scratch area, all capabilities dropped, no new privileges, a non root user, and limits on memory, CPU and process count. Remove the container afterward. This lowers risk for casual checks, but a container still shares the host kernel.
The command
docker run --rm \
--network none \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=64m \
--cap-drop ALL \
--security-opt no-new-privileges \
--user 65534:65534 \
--pids-limit 100 \
--memory 256m \
--cpus 1 \
-v "$PWD/script:/work:ro" \
python:3 python /work/check.py
The image name and script are placeholders. Pin the image by digest in real use, and scan it first.
What each flag does
| Flag | Effect, per Docker's documentation |
|---|---|
| rm | Removes the container and its anonymous volumes when it exits |
| network none | Only a loopback device exists inside, so no outside connections |
| read-only | Mounts the root filesystem read only, so writes go only to listed volumes |
| tmpfs with noexec and nosuid | A memory backed scratch directory that cannot run programs or setuid binaries |
| cap-drop ALL | Removes the capabilities Docker grants by default |
| no-new-privileges | Stops processes gaining privilege, so su and sudo stop working |
| user | Runs as the named user and group IDs, not root |
| pids-limit | Caps the number of processes |
| memory and cpus | Cap memory and CPU through the container's cgroup |
| ro suffix on the mount | Stops the container modifying your script folder |
Docker notes the minimum memory limit is 6 megabytes, and that a CPU value of 1.5 on a two CPU host guarantees at most one and a half CPUs.
Why no network matters most
The most common harm from a hostile script is sending your data out or fetching a second stage. Docker's none network driver gives the container only a loopback interface. If the script needs a package download, do that in a separate, reviewed build step and copy the result in.
What this setup cannot do
A container is a process on your host kernel. Docker's security page lists the kernel's own security among the areas to review, and gVisor's documentation says a workload using kernel security primitives is still one system call away from the host kernel. Seccomp, capabilities and namespaces shrink that exposure. They do not remove it.
For code that is plainly hostile, use an application kernel or a virtual machine. See which sandbox fits which code.
Also remember what you did not isolate: the image itself. An image with vulnerable packages or unknown provenance is a risk before your script even runs, so scan it.
Try it yourself
Click through it at your own pace, or open it full screen.
Run through the scan and look at how findings are grouped by layer and package, which is what you want to see before you run an unfamiliar image.
Quick check
Is a read only root filesystem enough on its own?
No. It blocks writes to the image, but the process can still use the network, memory and CPU unless you limit them.
Why drop all capabilities if I run as a non root user?
Defense in depth. A non root user already holds fewer privileges, and dropping capabilities removes what remains if the process finds a way to raise its privilege.
Safeguard scans images and dependencies, with a free scan at gold.safeguard.sh/scan.
Sources
- docker container run reference, Docker Docs
- None network driver, Docker Docs
- Resource constraints, Docker Docs
- Docker security, Docker Docs
- Introduction to gVisor security, gVisor
Last reviewed: 19 October 2026.