Using Docker to Learn a Programming Language

Using Docker to Learn Programming

Basic Use Case

Docker is a fantastic tool for use when learning any programming language. The ability to have a virtual, independent environment that can be manipulated a near infinite variety of ways is indispensable as you progress through learning a new language, especially if you are working on different versions. A Docker image can provide a clean environment on each use or be extended with volumes. It is easy to setup multiple environments using a minimum of space especially if you take the time to really plan, since Docker uses a system of layers when making images you can build up from a vanilla install to multiple package configurations without a separate virtual machine install for each case.

In this description I will be using PHP as my example since that is what I am learning right now. I’ve used it extensively for Python as well, and for learning about WordPress. In cases of server side languages like PHP and Python (useful especially when learning Django) Docker provides an added benefit of running a stand alone server for you to connect to.

I run docker on Debian Linux, utilizing a VirtualBox machine if not as my native operating system. There are OS specific solutions, however. For this post I will assume you are working on the command line in a Debian based environment with Docker already installed, as well as sudo (pre-installed on Ubuntu). Also, the instructions will be for a basic PHP setup but the principles can be easily transferred or built upon.

Preparing the Data Container

I like to prepare a data container for the shared, persistent volumes that I will need during the learning process. There are many ways to control and maintain persistent directories, or volumes, within Docker – and probably better ones than this, but this method has always been useful for me.

The first decision to make is what directories you are going to want to remain persistent throughout the process. Keep in mind that unless you specify a shared volume and/or reuse a container, whatever changes you make in a running docker environment will be lost when you shut it down. One solution is to create a persistent container and then have successive, disposable containers share those volumes. I decided in this case to make /etc/apache2 /var/www and /usr/local/etc persistently available. For Python I would add the directory for installing packages, such as /usr/local/lib/python2.7/dist-packages.

I use a small image to make the data container, in my case busybox. However, because these are not empty directories and contain important system configuration files, they have to be re-populated before they can be shared. In other words, if I create the busybox container with /etc/apache2/ as a persistent volume, docker will create it as an empty directory – not very useful when trying to start up a new PHP container if I want a functioning web-server!

So the next step is retrieving the contents of those directories from the image that we’ll be using so that they can be copied into the data container’s image when we build it. The image that I’m going to use for learning PHP is the official version of PHP 7 with Apache. For this step you will need to create a directory on the host machine to put all the necessary directories into – in this case /etc/apache2 and /usr/local/etc since they contain configuration files – which may as well be the folder we’ll use to build the data container.

:$ mkdir dockerPHP && cd dockerPHP

Now from within our new directory we will pull the necessary files from the PHP image that we’ll use for the busybox data container image.

dockerPHP:$ docker run --rm -it -v $(pwd):/backup php:7-apache /bin/bash

If this is the first time using this image, Docker will download the various layers first. Then you should be met with a command prompt that is brought up using the -it switch and /bin/bash command added to the end to prevent the PHP server from its default action of starting. The prompt will specify root @ container id and begin in the image’s working directory, /var/www/html/. Quickly confirm that a backup directory was created in the container – ls /backup. This container directory is created and ‘mirrored’ with the host folder by the -v command. Unless you have already put files here, it will be empty.

Now we just copy the directories we decided on earlier into the container’s /backup directory and they should show up in the host’s corresponding directory.

root@id: cp -r /usr/local/etc /etc/apache2 /backup

The result is a copy of these directories on your host system. Be aware that these directories are owned by root, so you’ll have to be root to do anything to them.

Now you can close the container with exit and ‘POOF’ – it’s gone, but our precious directories remain. We are going to now use them to build a busybox image that will serve as the basis for our data container.

Building the Data Container’s Image

This will be accomplished using a basic dockerfile in the same directory as the copied directories, in addition to a file you create titled index.php that I use as a template. Basically this just contains the code copied from example.com then stripped down to bare bones which I can use for all my practice scripts. The dockerfile looks like this:

FROM busybox

VOLUME /etc/ /var/www/ /usr/local/etc/
COPY ./etc /etc
COPY ./local /usr/local/etc
COPY index.php /var/www/html/
RUN chown -R root:root /var/www/html/

Since the directories we will be copying are owned by root, we have to build the image with sudo (you won’t have to run the container as root, however).

sudo docker build -t digitalap3/busybox:php7 .

Now that we have an image with the necessary, shared directories, we create our persistent container.

docker run --name php7-data digitalap3/busybox:php7

Keep in mind this container is crucial to preserving our work (though we’ll keep it backed up ’cause we’re smart like that) so be very careful about deleting it!!

Doing the Work

So now the hard part is done and we are ready to start learning! Basically all you are going to do now is run the docker image you pulled the directories from using the volumes from your data container in a disposable (removed upon closing) container.

docker run --rm --volumes-from php7-data -v $(pwd):/var/www/html -p 7050:80 php:7-apache

An additional step is sharing the html directory with the host so that I can create and manipulate scripts using the host’s editor (which has to be run as root since all files in this directory are owned by root). Keep in mind you will have to keep this console window active for the duration of your session. Simply access the server by going to localhost:7050 in your browser. Generally I’ll make my practice script – practice.php – then check it out at localhost:7050/practice.php.

Congratulations and happy developing!

Important Note: Be aware that all files to be used in the docker container must be on a Linux partition so that they can be given root ownership.

Leave a Reply