Let’s just say one day you wake up and ask yourself, could I see a desktop inside a running Docker container? Could I then take that a step further and see an emulator (basically another step of virtualization)? Well then you’re in luck as that is exactly what we’re going to do.
The Original Problem
What leads us to do this? Well I had someone ask how they could scale out testing Android applications in the cloud. My initial thought was to just spin up some EC2 instances pre-configured with the emulators which would work fine but managing this get’s cumbersome when you start looking at large numbers.
The AWS/Docker Solution
A good way to scale this kind of solution is using Elastic Beanstalk with ECS. ECS works hand in hand with Docker images and Elastic Beanstalk and will help manage a fleet of test servers. To get our above solution working we want to setup the following:
- Create a docker image with NoVNC and support for GLX so we can emulate the video card for the Android emulator.
- Setup a android virtual device (AVD).
- Bundle up our Docker image and keep it in a repository such as Docker Hub.
- Use Elastic Beanstalk to launch our custom AMI with our Docker image.
I’m not going into the specifics of how the Docker image was built, you can read through the Dockerfile that is included in both the Github repo or the Docker Hub repo.
Please note that I’m using the AUFS drivers for Docker and not the default Devicemapper. Devicemapper will limit you to 10GB images and a 100GB total bundle for your images. Althrough you can find some information on increasing these values, they just don’t work! At least at the time of writing ;) You will suffer needlessly if you try and your images pushed and pulled via Docker Hub will also incur issues.
When you use the AUFS drivers your Docker image gets full access to the host disk space. You don’t have to limit an image to specific sizes. Unfortunately the AWS Linux used for default Elastic Beanstalk deployments etc doesn’t support AUFS so I’ve been using the Ubuntu 14.04 AMI in the AMI Marketplace.
Building The Docker Host
Here are the instructions for building a compatible Docker Host, these are mirrored again on the Github repository.
Here is the link for the repo, https://github.com/typemismatch/android-emulator
- Setup Ubuntu 14.04 – if on AWS use the Ubuntu Marketplace AMI.
- Make sure your host VM has at least 40GB of space, this image uses ~25GB when running.
- With AUFS Docker can use the entire host file system for image space vs devicemapper which is the docker default but has terrible 10GB limits and increasing it will cause you problems.
- Run the follow commands to install the aufs version of docker.
sudo apt-get update sudo apt-get -y install linux-image-extra-$(uname -r) sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -" sudo sh -c "echo deb http://get.docker.io/ubuntu docker main\ > /etc/apt/sources.list.d/docker.list" sudo apt-get update sudo apt-get -y install lxc-docker
- Setup docker to work without sudo
sudo service docker start sudo usermod -a -G docker ubuntu
- Test Docker – don’t fret if it throws an error, see next step
docker info If that didn't give the information screen do the following (remember skip this step if docker info already works) sudo docker -d ctrl-z sudo service docker start docker info
Build The Docker Image
Next we need to build the Docker image. This is done using a Dockerfile and supporting resource files. The hard work of making a working Dockerfile has already been completed and this is the file you edit if you want some extra goodies installed for a new image.
- Start by cloning the repository into a folder on your running Docker host.
git clone https://github.com/typemismatch/android-emulator
- Change folder into the android-emulator folder or whatever you called it.
- Run the Docker build command to create a new image, note the image name “android-emulator” is just what I called it, if you’re using Docker Hub you’ll want to use your username + /android-emulator.
docker build -t android-emulator .
Using The Image
The build process takes awhile but once completed you should see your image by running docker images. There you’ll see all local images.
The run this new image just use: (if you gave the image a different name then change it below)
docker run -dt -p 6901:6901 android-emulator
You’re mapping port 6901 on the container to 6901 on the host, the container port is always 6901 but your host port can be whatever you want to use and is open on your firewall. Since this was built on AWS my security group allows this port.
You can now surf to the Docker host public IP on port 6901 and you’ll see a list of files, pick vnc_auto.html and you can now login via NoVNC to see the desktop, running in the container, running in a VM :)
The default vnc password is “vncpassword” – so make sure you change this or limit access to just your IP!
Currently the script doesn’t install the Android SDK although all dependencies are already installed for you. To actually get an emulator working following these steps:
- Once connected over NoVNC open the browser and download the Android SDK.
- Extract the SDK and run the Android tool.
- Use the Android tool to install your required SDK API version and Emulator support.
- You can now run AVD’s etc as desired.
Now that everything is working you can push this image to Docker Hub and use it from EB/ECS or just run manually.
I’ll do another post on exactly how to run a custom image in EB and ECS next!
You don’t want to do all this work?? – ok! There is a Docker Hub image with everything above – you’ll still need to setup a Docker host to run the image but that is really pretty straight forward, instructions are in the repo.