Counting bandwidth from a Docker container

Solution 1:

The problem is related to namespaces. Docker uses them to isolate resources, which also means they don't count to the host's totals.

When you run iptables on the host, you're basically only looking into the host's namespace, and the packets you are interested in are tallied to the container's namespace. To work around this issue you can use ip netns to still run iptables on the host, but in the container's network namespace.

First, ip netns has a somewhat counter intuitive interface. In order to attach to the namespace of an existing process (in this case your container), you have to create a link in /var/run/netns/ to the process' namespace:

# ln -sf /proc/`docker inspect -f '{{ .State.Pid }}' YOUR_CONTAINER`/ns/net /var/run/netns/SOME_NAME

(you may have to mkdir /var/run/netns)

Now you're free to run iptables in your container's namespace:

# ip netns exec SOME_NAME iptables -L -nv

Note that this outputs iptables' ruleset inside the container, which will probably be empty.

If you're currently using --uid-owner just to have per-user counters, you don't even need it anymore, because in this case the chain counters apply only to the container and should then be enough.

Finally, you can cleanup /var/run/netns.

Multiple containers per user

If you have multiple containers per user and want to tally them together, you can start your containers with --net=container:OTHER_CONTAINER_FROM_USER, so that their namespaces are merged.

This has the disadvantage of merging all aspects of the network stack, including open ports, so you can't have two containers for the same user listening on the same port.

If this is a prohibitive limitation, you can tally the containers individually and group based on uid later.

You can find some more information about this issue here.