• Home
  • About
    • Ka'imi Kahihikolo photo

      Ka'imi Kahihikolo

      Data Scientist, Booz Allen Hamilton

    • Learn More
    • LinkedIn
    • Instagram
    • Github
  • Posts
    • All Posts
    • All Post Tags
  • Recipes
    • All Recipes
    • All Recipe Tags
  • Projects

TF 2.0 Examples in a Docker Environment

07 Mar 2021 (UPDATED: 09 Apr 2021)

Reading time ~15 minutes

  • Introduction
  • Docker Compose Configuration File
  • How to Run Your Container(s)
  • Running the Tensorflow Example Notebooks
  • Spinning Down Your Container
  • Link to Repository

Introduction

This is a simple tutorial on how to run Tensorflow 2.0 example jupyter notebooks in a docker container environment. If you are new to Docker, it is a fantastic tool for developing reproducible applications. This post will not be an indepth tutorial to Docker, if you are interested in an introduction, see https://docs.docker.com/get-started/—I will do a tutorial post soon.

One major benefit of Docker is the ability to share and replicate your development environment with collaborators (and to avoid getting stuck in dependency hell). Assuming your collaborators have Docker (and Docker Compose, if required), standing up an identical and isolated development environment only requires running a few commands!

As data scientists, it is common for us to exclusively live in Jupyter notebooks (for better, or for worse) to perform a variety of tasks—from exploratory data analysis, preprocessing, training, etc. Additionally, we want to ensure our Jupyter environment has the proper dependencies to perform our analysis.

Note: None of these Tensorflow tutorials are my own, they are all available on Tensorflow. The goal of this repository is to replicate these tutorials in a dockerized environment for educational purposes. Any modifications to the content will be indicated accordingly.

Docker Compose Configuration File

In this tutorial, we are keeping things simple. We will first start by creating a docker-compose.yml file. Generally, these files are used to specify the various services you would like for Docker to stand up—if you are dealing with a multi-container environment. In this example, our docker-compose.yml will only contain a single service, however this serves as an example of how to include a simple jupyter server to another docker stack.

version: "3.7"
services:
  tf-jupyter:
    image: jupyter/tensorflow-notebook:latest
    environment:
      - JUPYTER_TOKEN=jupyter
    volumes:
      - ./tutorials:/tf/tutorials
    working_dir: /tf/tutorials/
    ports:
      # Jupyter port
      - "8888:8888"
      # Tensorboard port
      - "6006:6006"

Let’s break things down line-by-line.

First version: "3.7" specifies the version of docker-compose to use. At a high level, different versions of docker-compose have different parameters you can specify.

Second, we define the various services to stand up, however since we only have a single service, we only see a single entry. If wanted multiple services, your file may look like:

version: ...
services:
  service-a:
    ...
  service-b:
    ...
  service-c:
    ...
  ...

Next, we define our service Jupyter notebook service. We start by defining the “image” to start from.

image: jupyter/tensorflow-notebook:latest

As a reminder, an image contains a frozen copy of a development environment. In this example, we are starting from an environment created by the Jupyter team that comes pre-installed with a lot of useful tools for running Tensorflow code. What this line is saying is start from the tensorflow-notebook image made by jupyter, and specifically, grab the latest version of this environment—you can also specify specific versions.

Optionally, we can define environment variables for the container.

environment:
  - JUPYTER_TOKEN=jupyter

In this example, we defining a single environment variable called JUPYTER_TOKEN. If you aren’t familiar with Jupyter, this is essentially a password to access the server. So here, we are setting the password to jupyter—in another post I show you a tip for securing your environment variables. Again, this is optional. If you remove this section of the config, Jupyter will start with no password required.

volumes:
  - ./tutorials:/tf/tutorials

Here we “mount” a volume, which essentially means “copy” files from your local machine to a specific directory in the container (whether or not it exists). Above, we mount the entire tutorials folder into a directory called /tf/tutorials. Note, this directory does not exist in the container, we are instructing docker-compose to make this directory and copy the contents to it. This way, we can access our notebooks from the container and our changes persist upon spinning down the container.

working_dir: /tf/tutorials/

This tells docker-compose to cd us into the /tf/tutorials/ directory upon entering it.

ports:
  # Jupyter port
  - "8888:8888"
  # Tensorboard port
  - "6006:6006"

For this container, we would like to start up two servers, one for Jupyter notebook and another for Tensorboard (if we elect to use it). In order for our local computer to actually access these servers, we must specify the port(s) to expose. Here we tell Jupyter to be accessible on port 8888 by the host (our local computer) and run on port 8888 within the container. What this implies is that we can forward the port to another, if there are port conflicts. Simiarly, for tensorboard, we expose 6006.

And that’s it for the configuration file!

How to Run Your Container(s)

Now here is the time to show the power of Docker. Assuming you are cd‘d into the proper directory, if you run from a terminal/command prompt:

docker-compose up

Docker will start up a service called tf-jupyter.

Creating network "tf_tutorials_default" with the default driver
Creating tf_tutorials_tf-jupyter_1 ...

If this is your first time running the command, it will take a while to execute as it is downloading all of the required dependencies. Note, the next time you run this command, you will not have to wait as long.

After everything downloads, you should finally see the following in your terminal:

tf-jupyter_1  | [I 2021-04-09 04:01:24.038 LabApp] JupyterLab application directory is /opt/conda/share/jupyter/lab
tf-jupyter_1  | [I 04:01:24.043 NotebookApp] Serving notebooks from local directory: /tf/tutorials
tf-jupyter_1  | [I 04:01:24.043 NotebookApp] Jupyter Notebook 6.2.0 is running at:
tf-jupyter_1  | [I 04:01:24.043 NotebookApp] http://23b09491f9c6:8888/?token=...
tf-jupyter_1  | [I 04:01:24.043 NotebookApp]  or http://127.0.0.1:8888/?token=...
tf-jupyter_1  | [I 04:01:24.043 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

You now have a Jupyter notebook server running! If you visit localhost:8888 in your browser, you will arrive on this page:

jupyter notebook password prompt

Recall, the password/token for this Jupyter server is jupyter (defined in the environment variables). Upon logging in, you’ll arrive at the usual Jupyter notebook screen.

jupyter notebook home screen

Running the Tensorflow Example Notebooks

You can then create and execute your Jupyter notebooks like normal, for example, here is the Tensorflow 2 Quickstart for Beginners example from Tensorflow.

tf 2.0 quickstart for beginners

Additionally, you can see we already have tensorflow installed. As of 2021-04-09, the following dependencies are included in the jupyter/tensorflow-notebook:latest image:

(base) jovyan@53e0be54cffe:/tf/tutorials$ pip list
Package                       Version
----------------------------- -------------------
absl-py                       0.11.0
alembic                       1.5.5
anyio                         2.2.0
appdirs                       1.4.4
argon2-cffi                   20.1.0
astunparse                    1.6.3
async-generator               1.10
attrs                         20.3.0
Babel                         2.9.0
backcall                      0.2.0
backports.functools-lru-cache 1.6.1
beautifulsoup4                4.9.3
bleach                        3.3.0
blinker                       1.4
bokeh                         2.2.3
Bottleneck                    1.3.2
brotlipy                      0.7.0
cached-property               1.5.1
cachetools                    4.2.1
certifi                       2020.12.5
certipy                       0.1.3
cffi                          1.14.5
chardet                       4.0.0
click                         7.1.2
cloudpickle                   1.6.0
conda                         4.9.2
conda-package-handling        1.7.2
cryptography                  3.4.4
cycler                        0.10.0
Cython                        0.29.22
cytoolz                       0.11.0
dask                          2021.2.0
decorator                     4.4.2
defusedxml                    0.6.0
dill                          0.3.3
distributed                   2021.2.0
entrypoints                   0.3
flatbuffers                   1.12
fsspec                        0.8.7
gast                          0.3.3
gmpy2                         2.1.0b1
google-auth                   1.27.1
google-auth-oauthlib          0.4.3
google-pasta                  0.2.0
grpcio                        1.32.0
h5py                          2.10.0
HeapDict                      1.0.1
idna                          2.10
imagecodecs                   2021.1.28
imageio                       2.9.0
importlib-metadata            3.7.0
ipykernel                     5.5.0
ipympl                        0.6.3
ipython                       7.21.0
ipython-genutils              0.2.0
ipywidgets                    7.6.3
jedi                          0.18.0
Jinja2                        2.11.3
joblib                        1.0.1
json5                         0.9.5
jsonschema                    3.2.0
jupyter-client                6.1.11
jupyter-core                  4.7.1
jupyter-packaging             0.7.12
jupyter-server                1.4.1
jupyter-telemetry             0.1.0
jupyterhub                    1.3.0
jupyterlab                    3.0.9
jupyterlab-pygments           0.1.2
jupyterlab-server             2.3.0
jupyterlab-widgets            1.0.0
Keras-Preprocessing           1.1.2
kiwisolver                    1.3.1
llvmlite                      0.35.0
locket                        0.2.0
Mako                          1.1.4
mamba                         0.7.14
Markdown                      3.3.4
MarkupSafe                    1.1.1
matplotlib                    3.3.4
mistune                       0.8.4
mock                          4.0.3
mpmath                        1.2.1
msgpack                       1.0.2
nbclassic                     0.2.6
nbclient                      0.5.3
nbconvert                     6.0.7
nbformat                      5.1.2
nest-asyncio                  1.4.3
networkx                      2.5
notebook                      6.2.0
numba                         0.52.0
numexpr                       2.7.2
numpy                         1.19.5
oauthlib                      3.0.1
olefile                       0.46
opt-einsum                    3.3.0
packaging                     20.9
pamela                        1.0.0
pandas                        1.2.3
pandocfilters                 1.4.2
parso                         0.8.1
partd                         1.1.0
patsy                         0.5.1
pexpect                       4.8.0
pickleshare                   0.7.5
Pillow                        8.1.1
pip                           21.0.1
pooch                         1.3.0
prometheus-client             0.9.0
prompt-toolkit                3.0.16
protobuf                      3.15.4
psutil                        5.8.0
ptyprocess                    0.7.0
pyasn1                        0.4.8
pyasn1-modules                0.2.8
pycosat                       0.6.3
pycparser                     2.20
pycurl                        7.43.0.6
Pygments                      2.8.0
PyJWT                         2.0.1
pyOpenSSL                     20.0.1
pyparsing                     2.4.7
pyrsistent                    0.17.3
PySocks                       1.7.1
python-dateutil               2.8.1
python-editor                 1.0.4
python-json-logger            2.0.1
pytz                          2021.1
PyWavelets                    1.1.1
PyYAML                        5.4.1
pyzmq                         22.0.3
requests                      2.25.1
requests-oauthlib             1.3.0
rsa                           4.7.2
ruamel-yaml-conda             0.15.80
ruamel.yaml                   0.16.12
ruamel.yaml.clib              0.2.2
scikit-image                  0.18.1
scikit-learn                  0.24.1
scipy                         1.6.0
seaborn                       0.11.1
Send2Trash                    1.5.0
setuptools                    49.6.0.post20210108
six                           1.15.0
sniffio                       1.2.0
sortedcontainers              2.3.0
soupsieve                     2.0.1
SQLAlchemy                    1.3.23
statsmodels                   0.12.2
sympy                         1.7.1
tables                        3.6.1
tblib                         1.6.0
tensorboard                   2.4.1
tensorboard-plugin-wit        1.8.0
tensorflow                    2.4.1
tensorflow-estimator          2.4.0
termcolor                     1.1.0
terminado                     0.9.2
testpath                      0.4.4
threadpoolctl                 2.1.0
tifffile                      2021.2.26
toolz                         0.11.1
tornado                       6.1
tqdm                          4.58.0
traitlets                     5.0.5
typing-extensions             3.7.4.3
urllib3                       1.26.3
vincent                       0.4.4
wcwidth                       0.2.5
webencodings                  0.5.1
Werkzeug                      1.0.1
wheel                         0.36.2
widgetsnbextension            3.5.1
wrapt                         1.12.1
xlrd                          2.0.1
zict                          2.0.0
zipp                          3.4.0

Note, you can do this a few ways, but here are a couple of options:

  1. Create a terminal in the Jupyter server and execute pip list
  2. From your command prompt, run docker-compose run tf-jupyter pip list

Additionally, since you mounted your notebook directory, all changes made within the container should presist to your local copies. However, warning, if you write to unmounted directories, your changes will disappear when you exit the container.

Spinning Down Your Container

When you are done with your jupyter container, ctrl+c the terminal where you ran the docker-compose up, and you’ll see the following prompt.

Gracefully stopping... (press Ctrl+C again to force)
Stopping tf_tutorials_tf-jupyter_1 ... 
Killing tf_tutorials_tf-jupyter_1  ... done

To ensure the containers fully stop gracefully, execute:

docker-compose down

Link to Repository

For the full code for this tutorial see:

  • https://github.com/kaimibk/TF_Tutorials


dockerjupyterpythontensorflowtutorial Share Tweet +1