Host example#
make demo
./demo --sleepps aux | grep demoDisplay process namespace association:
ls -l /proc/$(pidof demo)/nsCompare namespaces with your shell:
ls -l /proc/$$/nsBuild docker image#
docker build -t demo .docker image list demodocker run demo
docker run -it --name demo_sleep --rm demo --sleepNote PID = 1 here. However, from host perspective there is a regular process demo with a high PID:
ps aux | grep demodocker top lists processes within a single container:
docker top demo_sleepdocker ps lists containers:
docker ps -aInspect containerized process namespace association:
HOST_PID=$(docker inspect -f '{{.State.Pid}}' demo_sleep)
echo $HOST_PID
sudo ls -l /proc/$HOST_PID/ns/Note the differences from what we’ve seen before.
PID Namespace#
Containerized processes see only other processes within the same container.
Try running forking process and observe PIDs:
docker run -it --rm demo --forkTry running it multiple times in parallel.
Containers cannot access host PIDs.
HOST_PID=$$
echo $HOST_PID
docker run -it --rm demo --kill $HOST_PIDDIY PID namespace#
make pidnssudo ./pidnsNote that child PID from perspective of parent is different from what child sees.
NET namespace#
./demo --ifTry listing container interfaces:
docker run -it --rm demo --ifNow bind port 8080 within host and then within the container:
nc -u -l 8080docker run -it --rm --name=demo_udp demo --udpSend datagram to host:
echo "Hello Host" | nc -u -w1 127.0.0.1 8080And to the container:
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' demo_udp)
echo "Container IP: $CONTAINER_IP"
echo "Hello Container" | nc -u -w1 $CONTAINER_IP 8080Show a host route installed by docker:
ip routeSee interfaces from the container:
docker exec demo_udp ip aNote network namespaces created by docker live in a different directory compared to the standard ones created by
ip netns tool. You can find them with:
SANDBOX_KEY=$(docker inspect -f '{{.NetworkSettings.SandboxKey}}' demo_udp)
echo $SANDBOX_KEYPort exporting#
docker run -it --rm --name=demo_cpu -p 80:8080/udp demo --udpShow iptables rules:
sudo iptables -t nat -L DOCKER -nShow auxiliary process:
ps aux | grep docker-proxySend something:
echo "Hello!" | nc -u -w1 localhost 80MNT Namespace#
docker run -it --name demo_fs demo --writels -l /tmp/container_secret.txtHOST_PID=$(docker inspect -f '{{.State.Pid}}' demo_fs)
sudo cat /proc/$HOST_PID/mountinfo | grep '/ / 'HOST_PID=$(docker inspect -f '{{.State.Pid}}' demo_fs)
UPPER_DIR=$(sudo cat /proc/$HOST_PID/mountinfo | grep '/ / ' | grep -o 'upperdir=[^,]*' | cut -d= -f2)
LOWER_DIR=$(sudo cat /proc/$HOST_PID/mountinfo | grep '/ / ' | grep -o 'lowerdir=[^,]*' | cut -d= -f2)
echo $UPPER_DIR
echo $LOWER_DIRHOST_PID=$(docker inspect -f '{{.State.Pid}}' demo_fs)
UPPER_DIR=$(sudo cat /proc/$HOST_PID/mountinfo | grep '/ / ' | grep -o 'upperdir=[^,]*' | cut -d= -f2)
sudo tree $UPPER_DIRdocker container rm demo_fsDIY virtual root#
make mntnssudo ./mntns ./rootBind mounts#
docker run -it --name demo_bind -v ./root:/data demo --write /data/persistent.txtHOST_PID=$(docker inspect -f '{{.State.Pid}}' demo_bind)
sudo cat /proc/$HOST_PID/mountinfo | grep '/data'stat ./root/persistent.txt
cat ./root/persistent.txtsudo rm ./root/persistent.txtdocker rm -f demo_bindControl Groups#
docker run -it --rm -m 50m demo --memCONTAINER_ID=$(docker inspect -f '{{.Id}}' demo_sleep)
echo $CONTAINER_ID
ls /sys/fs/cgroup/system.slice/docker-$CONTAINER_ID.scope/docker run -it --rm --name=demo_cpu --cpus="0.1" demo --cpuHOST_PID=$(docker inspect -f '{{.State.Pid}}' demo_cpu)
htop -p $HOST_PIDCONTAINER_ID=$(docker inspect -f '{{.Id}}' demo_cpu)
echo $CONTAINER_ID
cat /sys/fs/cgroup/system.slice/docker-$CONTAINER_ID.scope/cpu.maxCleanup#
Ensure there are no leftovers:
docker container psStop if anything is still running with docker kill.
docker container prune