Docker for Python-Dash & R-Shiny. Easy start with Docker &... | by Meinhard Ploner | Towards Data Science

You wanna deploy your data-driven app using Docker & Docker Compose? Then read on, because this article will get you up-and-running in a few minutes. For both the most wide-spread Data Science / Analytics stacks: Python & R.
In my latest Medium stories, I explained how to set up a data-driven web application for the sake of showing case numbers of the Coronavirus. I created the exact same web application with the following two stacks:
Python & Dash (Link)
R & Shiny (Link)
In this article, I will show you how to deploy these apps using Docker & Compose. I will first go through Docker, for Python as well as R, and follow with docker-compose, later-on.
Installing Docker on the server of your choice is easy — there are plenty of instructions out there. As an example, if you have an AWS instance (EC2) running Amazon Linux, simply type:
sudo yum install -y docker  # Install Docker.sudo service docker start   # Start the service.sudo usermod -a -G docker ec2-user  # Add ec2-user to Docker group.sudo chkconfig docker on    # Let docker auto-start.
Perfect. Docker is ready!
First, we have to create the requirements.txt file, including all the necessary libraries. This can be done using the command
pip freeze > requirements.txt
or through manually creating the text-file and entering the name of the libraries. For the mentioned app we need the following libraries (btw, plotly is installed with dash):
dashpandas
Then we are ready to set up the DOCKERFILE itself. For a simply Python-Dash app the following code is sufficient:
FROM python:3.8LABEL maintainer "Meinhard Ploner <dummy@host.com>"WORKDIR /codeCOPY requirements.txt /RUN pip install -r /requirements.txtCOPY ./ ./EXPOSE 8050CMD ["python", "./app.py"]
Description of the individual commands:
FROM ... : pull the Python image with tag 3.8 (=version).
LABEL ... : optional. Name and E-mail of the maintainer.
WORKDIR ... : set the working directory.
COPY requ... : copy the requirements.txt file.
RUN pip ... : install all the libraries listed as requirements.
COPY ./ ... : copy all files to the Docker image.
EXPOSE ... : set the port to listen to.
CMD ... : set the command to be executed when running the image.
Perfect. If we are not interested in the R solution, we can jump to the definition of docker-compose. Otherwise, go ahead...
On R, the packages are usually not listed in a requirements file, but directly part of the DOCKERFILE code. Similar to Python, I propose a DOCKERFILE which works well for simple apps like the one I explained in the other post.
The file is slightly more complex as for Python but still compact:
FROM rocker/shiny:3.6.1LABEL maintainer "Meinhard Ploner <dummy@host.com>"WORKDIR /srv/shiny-serverRUN apt-get update \    && apt-get install -y libsasl2-dev libssl-devRUN echo \  'options(repos=list(CRAN="https://cloud.r-project.org/"))' > \  ".Rprofile"RUN R -e "install.packages(c('dplyr','tidyr', 'plotly'))"ADD https://raw.githubusercontent.com/rocker-org/shiny/master/shiny-server.sh /usr/bin/COPY ./ ./EXPOSE 3838RUN chmod a+w .RUN chmod +x /usr/bin/shiny-server.shCMD /usr/bin/shiny-server.sh
Description of the single commands:
FROM ... : pull the R-Shiny image with tag 3.6.1 (=version).
LABEL ... : optional. Name and E-mail of the maintainer.
WORKDIR ... : set the working directory.
RUN apt-get ... : install libssl, needed for plotly. Might differ on other Linux instances or Windows.
RUN echo ... : write the CRAN repository URL into .Rprofile, which is used in the subsequent R call.
Run R ... : call R to install various packages.
ADD ... : download the shiny-server.sh file and add it to the image.
COPY ./ ... : copy all files to the Docker image.
EXPOSE ... : set the port to listen to.
RUN chmod +w... : make the home directory of the image writable.
RUN chmod +x... : make shiny-server.sh executable.
CMD ... : set the command to be executed when running the image.
That’s it. Let’s move on to the Compose part.
The installation of docker-compose is also straightforward. Copy the appropriate binary from GitHub, and fix the permissions:
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
You might wonder what the command uname is for? uname returns basic information about the operating system. On AWS EC2 with Amazon Linux, it gives “Linux” for “uname -s” and “x86_64” for “uname -m”.
The docker-compose.yml YAML file does not differ between the two stacks. But before creating it, set up an environment file called “.env” with basic app information:
VERSION=1.0.0TARGET=LIVE
Now create the Compose file, which in our case is minimalistic:
version: "3.7"services:  app-name:    build:      context: .    image: app-name:$VERSION    container_name: app-name    ports:      - "to:from"    environment:      - TARGET=$TARGET    restart: unless-stopped
Replace “app-name” by the app name of your choice. The image name will use the version number and is in our case “app-name:1.0.0”.
Further, Python-Dash apps usually run on port 5050, while R-Shiny apps per default use port 3838. Therefore replace the ports (“to:from”) by:
80:5050 for Python-Dash
80:3838 for R-Shiny
Instead of port 80 you can use any other port you want to serve. Save the file as docker-compose.yml and you are done.
To build the image use:
docker-compose build
Having the image built, build and start the container by typing:
docker-compose up -d
The option “-d” ensures the app is running in the background. Without the option, you will directly see the logs, which can be useful for the first few runs, to test the setting.
If you downloaded the app code from GitHub and followed the instructions, your app will be running on the server.
Otherwise, you can also test the apps, which run on my EC2 instance:
Python-Dash app on AWS/EC2: https://go.aws/2xsdb7q
R-Shiny app on AWS/EC2: https://go.aws/3aoYsIW
As you can see, it is no big deal to deploy a simple Dash or Shiny app. And even if an app gets more complex, these examples can be used as a blueprint.
I hope you enjoyed the article and it helped in getting your own app up and running!