Search code examples
dockerdiskquota

How to define a disk quota for docker containers?


I'm was faced with the requirement to have disk quotas on docker containers. Specifically I want to limit the amount of data that is not in the layers of base image but in the diff. Googling for "docker disk quota" suggests to use either the device mapper or the btrfs backends. While being able to have quotas in both backends (with different semantics) both have their issues:

  • btrfs isn't stable enough for production use
  • device mapper only limits the complete container size including the base image but doesn't allow limiting the diff

What is the best way to solve this?


Solution

  • One way to solve this is to put the diff directory /var/lib/docker/aufs/diff/$CONTAINER_ID into a sparse loopback mounted ext4 directory. This effectively limits the amount of data a user can store/modify in a container. This is the bash code I use:

    do_enable_quota() {
        local ID=$1
        local QUOTA_MB=$2
    
        local LOOPBACK=/var/lib/docker/aufs/diff/$ID-loopback
        local LOOPBACK_MOUNT=/var/lib/docker/aufs/diff/$ID-loopback-mount
        local DIFF=/var/lib/docker/aufs/diff/$ID
    
        docker stop -t=0 $ID
        sudo dd of=$LOOPBACK bs=1M seek=$QUOTA_MB count=0
        sudo mkfs.ext4 -F $LOOPBACK
        sudo mkdir -p $LOOPBACK_MOUNT
        sudo mount -t ext4 -n -o loop,rw $LOOPBACK $LOOPBACK_MOUNT
        sudo rsync -rtv $DIFF/ $LOOPBACK_MOUNT/
        sudo rm -rf $DIFF
        sudo mkdir -p $DIFF
        sudo umount $LOOPBACK_MOUNT
        sudo rm -rf $LOOPBACK_MOUNT
        sudo mount -t ext4 -n -o loop,rw $LOOPBACK $DIFF
        docker start $ID    
    }
    

    This approach works perfectly for me but the drawback is that I need to wrap the "start", "stop" and "rm" commands to take the mount into account.