Mounting an EBS Volume to Docker on AWS Elastic Beanstalk
Join the DZone community and get the full member experience.
Join For FreeMounting an EBS volume to a Docker instance running on Amazon Elastic Beanstalk (EB) is surprisingly tricky. The good news is that it is possible.
I will describe how to automatically create and mount a new EBS volume (optionally based on a snapshot). If you would prefer to mount a specific, existing EBS volume, you should check out leg100’s docker-ebs-attach (using AWS API to mount the volume) that you can use either in a multi-container setup or just include the relevant parts in your own Dockerfile.
The problem with EBS volumes is that, if I am correct, a volume can only be mounted to a single EC2 instance – and thus doesn’t play well with EB’s autoscaling. That is why EB supports only creating and mounting a fresh volume for each instance.
Why would you want to use an auto-created EBS volume? You can already use a docker VOLUME to mount a directory on the host system’s ephemeral storage to make data persistent across docker restarts/redeploys. The only advantage of EBS is that it survives restarts of the EC2 instance but that is something that, I suppose, happens rarely. I suspect that in most cases EB actually creates a new EC2 instance and then destroys the old one. One possible benefit of an EBS volume is that you can take a snapshot of it and use that to launch future instances. I’m now inclined to believe that a better solution in most cases is to set up automatic backup to and restore from S3, f.ex. using duplicity with its S3 backend (as I do for my NAS).
Anyway, here is how I got EBS volume mounting working. There are 4 parts to the solution:
- Configure EB to create an EBS mount for your instances
- Add custom EB commands to format and mount the volume upon first use
- Restart the Docker daemon after the volume is mounted so that it will see it (see this discussion)
- Configure Docker to mount the (mounted) volume inside the container
1-3.: .ebextensions/01-ebs.config:
# .ebextensions/01-ebs.config commands: 01format-volume: command: mkfs -t ext3 /dev/sdh test: file -sL /dev/sdh | grep -v 'ext3 filesystem' # ^ prints '/dev/sdh: data' if not formatted 02attach-volume: ### Note: The volume may be renamed by the Kernel, e.g. sdh -> xvdh but # /dev/ will then contain a symlink from the old to the new name command: | mkdir /media/ebs_volume mount /dev/sdh /media/ebs_volume service docker restart # We must restart Docker daemon or it wont' see the new mount test: sh -c "! grep -qs '/media/ebs_volume' /proc/mounts" option_settings: # Tell EB to create a 100GB volume and mount it to /dev/sdh - namespace: aws:autoscaling:launchconfiguration option_name: BlockDeviceMappings value: /dev/sdh=:100
4.: Dockerrun.aws.json and Dockerfile:
Dockerrun.aws.json
: mount the host’s /media/ebs_volume
as /var/easydeploy/share
inside the container:
{ "AWSEBDockerrunVersion": "1", "Volumes": [ { "HostDirectory": "/media/ebs_volume", "ContainerDirectory": "/var/easydeploy/share" } ] }
Dockerfile
: Tell Docker to use a directory on the host system as /var/easydeploy/share
– either a randomly generated one or the one given via the -m
mount option to docker run
:
... VOLUME ["/var/easydeploy/share"] ...
Published at DZone with permission of Jakub Holý, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments