10. ARM

Thus far, we assumed that you are building your Docker containers on a x86 CPU architecture. However, you may also build Docker containers for the ARM CPU architecture too, such as the Raspberr Pi. Typically, you build x86 CPU targeted Docker containers on a computer with a x86 CPU, and likewise, you build ARM CPU targeted Docker containers on a ARM CPU computer. However, you may also build ARM CPU targeted Docker containers from a x86 CPU computer by typing in the following.

1docker run --rm --privileged hypriot/qemu-register

10.1. Basic ARM container

An example Dockerfile to build a basic ARM container is as follows.

 1FROM arm32v7/ubuntu
 2
 3ENV DEBIAN_FRONTEND=noninteractive
 4
 5RUN apt-get update -y && \
 6    apt-get upgrade -y
 7
 8RUN apt-get install -y \
 9    wget \
10    build-essential \
11    tk-dev \
12    libncurses5-dev \
13    libncursesw5-dev \
14    libreadline6-dev \
15    libdb5.3-dev \
16    libgdbm-dev \
17    libsqlite3-dev \
18    libssl-dev \
19    libbz2-dev \
20    libexpat1-dev \
21    liblzma-dev \
22    zlib1g-dev \
23    libffi-dev \
24    gfortran \
25    libopenblas-dev \
26    liblapack-dev \
27    python-dev \
28    default-libmysqlclient-dev \
29    libfreetype6-dev \
30    libxml2-dev \
31    libxslt1-dev
32
33RUN apt-get clean

Notice the following.

  • The base image is arm32v7/ubuntu.

  • The ENV DEBIAN_FRONTEND=noninteractive instruction is to enable non-interactive installs (so we do not get prompted for Yes or No).

  • We install a lot of system libraries since we want to do interesting things later on.

Build.

1docker build --no-cache -t rpi-base:local .

Run.

1docker run -it rpi-base:local

10.2. Jupyter Lab

What if we want to have a reproducible, consistent data science work environment on the Raspberry Pi? We can build a container to spin up a Jupyter Lab instance.

 1FROM rpi-base:local
 2
 3ENV CONDA_HOME=/root/miniconda
 4ENV PATH=${CONDA_HOME}/bin:${PATH}
 5ENV JUPYTER_TYPE=lab
 6
 7# setup OS
 8RUN apt-get update -y && \
 9    apt-get upgrade -y && \
10    apt-get install supervisor -y
11
12# setup supervisor
13COPY jupyter.conf /etc/supervisor/conf.d/
14
15# setup miniconda
16RUN wget -q http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-armv7l.sh -O /tmp/miniconda.sh && \
17    /bin/bash /tmp/miniconda.sh -b -p /root/miniconda && \
18    conda update -n root conda -y && \
19    conda update --all -y && \
20    pip install --upgrade pip && \
21    conda config --add channels rpi && \
22    conda install python=3.6 -y && \
23    conda install jupyter jupyterlab nodejs scikit-learn numpy scipy matplotlib -y -c anaconda -c conda-forge
24
25# setup mount point
26RUN mkdir /ipynb
27VOLUME ["/ipynb"]
28
29# setup ports
30EXPOSE 8888
31
32# clean up
33RUN apt-get clean
34
35CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf", "-n"]

Notice the following.

  • We use the previous rpi-base:local image to bootstrap this image.

  • We install miniconda to manage our Python environments and dependencies.

  • We setup a mount volume at /ipynb so that we can mout our local notebooks onto the container at runtime.

  • We expose port 8888, which is what Jupyer Lab is running on.

  • We use supervisor to start up Jupyter Lab at runtime.

  • If you do not like Jupyer Lab and want the old Jupyter Notebook, override at runtime with -e JUPYTER_TYPE=notebook.

Build.

1docker build --no-cache -t rpi-jupyter:local .

Run.

1docker run \
2    -it \
3    --rm \
4    -p 8888:8888 \
5    -v `pwd`/ipynb:/ipynb \
6    rpi-jupyter:local

You may now access the Jupyter Lab at http://localhost:8888.