The problem

On a course called embedded linux drivers the given method of development was a premade virtual machine. It was only available in a single computer classroom that was often crowded. To avoid using the class and work on my own machine three options were given. I could copy the existing VM image from the classroom, make my own image or install it directly on my machine.

Using a VM was not ideal on my machine. It introduces a lot of overhead and requires a lot of disk space which my machine simply does not have. Installing directly on the host was also out of question as the project required a lot of outdated dependencies.

The solution

I wanted a solution which would require the least amount of disk usage and which could be quickly ported to other machines. The solution would also need to make management of dependencies easy. A perfect situation for using Docker!

I created a Dockerfile which installs all the needed dependencies and uses the ancient ubuntu version required by the ancient version of Yocto. I also created bash scripts for automating the workflow.

Now I can just quickly clone the project repository, run a script and the whole environment is built!

Advantages compared to the old environment

Now working on a new machine can be started in minutes. Compared to the old environment which required installation of virtual machines, the amount of time saved is huge. Setup time was reduced from an hour or two to a couple of minutes.

Even continuing to work on the project was made faster. The old environment required starting from a snapshot and cloning the project every time. Also all the build caches and stuff would disappear when closing the vm. Now the project is simply mounted from the host and work can continue immediately.

Technical details

With docker all versions can be specified easily. For example the Yocto version used is recommended to be run with ubuntu version 18.04. This can be achieved simply by using the ubuntu base image and specifying the tag:

FROM ubuntu:18.04

And the dependencies can be installed easily during the building of the container:

RUN apt-get update && apt-get install -y \
     gawk wget git-core diffstat unzip texinfo gcc-multilib \
     build-essential chrpath socat cpio python python3 python3-pip python3-pexpect \
     xz-utils debianutils iputils-ping

The shell scripts I created help fasten the development. There is no complex logic or similar in the scripts. They mainly aid the development so that you don’t need to remember specific commands. For example running the container can be done with a simple script which contains the complex volume mounts and such:

docker run -it --rm \
    -v "$REPO_ROOT:/home/yocto/yocto" \
    -v "$REPO_ROOT/cache:/opt" \
    $IMAGE_NAME \
    bash -c "source /home/yocto/yocto/poky/oe-init-build-env /home/yocto/yocto/build && exec bash"

Sharing the solution

I tried to make my solution as portable as possible so that other students can use my solution aswell. I added documentation so that you don’t need to know that much about docker.

Finally I shared my environment as a git patch file. As all of the student repositories were based on the same upstream repository this was easy. A student only needs to apply the patch and run the scripts provided.

The base repository with the added Docker environment can be found here. Note the repository only contains the base repository without yocto installed yet.

Conclusion

I believe I should be able to install all the programs that I use. This has been one of the hardest ones to install. Mainly because of the dependencies. Docker has been a powerfull tool to manage all these dependencies.

Building this environment has given me valuable experience on how to automate and containerize embedded development environments.