Docker v1.10

· by Vincent De Smet · Read in about 5 min · (856 Words)

Docker 1.10 is coming and as with any release in the ever fast moving world of Docker, it is good to find out more about the use cases for the newly introduced commands, below is a list of the interesting changes that stood out for me so far:

Container Mutability and the new docker update command

Relevant pull request

Usage: docker update [OPTIONS] CONTAINER [CONTAINER...]

Updates container resource limits

  --blkio-weight=0           Block IO (relative weight), between 10 and 1000
  --cpu-shares=0             CPU shares (relative weight)
  --cpu-period=0             Limit the CPU CFS (Completely Fair Scheduler) period
  --cpu-quota=0              Limit the CPU CFS (Completely Fair Scheduler) quota
  --cpuset-cpus=""           CPUs in which to allow execution (0-3, 0,1)
  --cpuset-mems=""           Memory nodes (MEMs) in which to allow execution (0-3, 0,1)
  -m, --memory=""            Memory limit
  --memory-reservation=""    Memory soft limit
  --memory-swap=""           Total memory (memory + swap), '-1' to disable swap
  --kernel-memory=""         Kernel memory limit: container must be stopped

The docker update command dynamically updates container resources. Use this command to prevent containers from consuming too many resources from their Docker host. With a single command, you can place limits on a single container or on many. To specify more than one container, provide space-separated list of container names or IDs.

With the exception of the --kernel-memory value, you can specify these options on a running or a stopped container. You can only update --kernel-memory on a stopped container. When you run docker update on stopped container, the next time you restart it, the container uses those values.

Prior to 1.10, once the Docker Daemon created a container for the Image you chose to run, it did not give you an easy way to change the configuration you specified with the docker run command.

From a technical perspective, Docker exposes a layer above a set of technologies (cgroups, namespaces, iptables, filesystems, …) to provide its users an easy way of managing these resources for their applications. One could always dig into these layers to make adjustments behind the daemons’ back.

For example:

  1. Exposing ports on a live container:

    This Stack Overflow question gives us this very usefull snippet

    #get the container IP
    CONTAINER_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' container_name)
    #forward packets from port 8001 on your host to port 8000 on the container
    iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination ${CONTAINER_IP}:8000

    See Also

  2. Managing Docker resources with Cgroups (September 2014)

    Either by interacting with cgroups directly or if running Docker with Systemd, using systemctl to set properties on the systemd scope of the container, also refer to the Redhat Resource Management Guide & systemd resource control:

    sudo systemctl set-property docker-4be96b853089bc6044b29cb873cac460b429cfcbdd0e877c0868eb2a901dbf80.scope CPUShares=512
    #show all the properties:
    systemctl show docker-4be96b853089bc6044b29cb873cac460b429cfcbdd0e877c0868eb2a901dbf80.scope
  3. Attaching Volumes to a running container

But going behind the back of the Docker Daemon does not provide any logs or audit trails and may cause unexpected side effects, moreover - giving users the ability apply these changes through the Docker API only makes sense given it is possible to achieve underneath… but up to what point?

This brings us to a very important question: How much of a container should be mutable?

With Docker 1.9, networks could be connected & disconnected from a Container and containers could be renamed while all other aspects are immutable from the Docker daemon’s perspective.

With the addition of the docker update command in 1.10, CPU/Memory resources can be changed dynamically (except the --kernel-memory setting which requires a container restart) and are persisted in the container definition to ensure they still apply after restarts.

Adding support for exposing ports, changing container restart policies and labels are being worked on , but do not seem to be planned for the 1.10 release, but what about Environment variables?

Container Network Model - Service Discovery

With the 1.9 release, Docker moved its networking libraries from the experimental branch to the production ready branch. Networking brought a big change in the way containers find each other, deprecating Docker links as well as adding cross-host support with overlay (vxlan) networks (replacing the ambassador container pattern).

Docker links worked by modifying the /etc/hosts files within the containers, bypassing DNS lookups. The new networking model built further on this approach to provide cluster wide service discovery. Unfortunately, making changes to a shared resource (/etc/hosts) in a non-atomic way and scaling will never go hand in hand. The service discovery model was in desperate need for a change.

As highlighted by Ahmet Alp Balkan in his excellent DockerCon EU 2015 presentation, most Service Discovery solutions gravitate towards the tested and proven DNS protocol. Some of the drawbacks highlighted such as IP caching and no respect for TLS are solved by Cluster Management Systems such as Kubernetes by fully decoupling the service endpoint from the implementation through labels and fixed IP service resources.

The fix by the Docker networking team for 1.10 would be to bundle a DNS server with the Docker Daemon and expose this service within the namespace of every container. This would certainly be a much better solution than the current one, but the fact that neither the previous /etc/hosts nor the upcoming DNS server are optional is still not making some people happy.