Packaging Python scripts with Docker
In Part 1 of this post I covered the creation of the initial MyUsps notification script. There’s quite a few dependencies in the environment required for running this script. At a bare minimum you will need a functional Linux or Windows environment with the following dependencies
1 2 3 4 5 6 |
GeckoDriver Firefox v59 Selenium 3.11 (pip install selenium) Python3.6 imgurpython (pip install imgurpython ) Pushbullet Python Library (pip install pushbullet.py) |
There’s some challenges getting all of these things to work well together. It’s also very difficult to keep all of these applications in sync and distribute a working installation script to allow users to clone your environment.
Enter Docker.
Using Docker images we can create a dockerfile that will package images with all the necessary components, and allow for easy distribution of working images. The dockerfile for this project looks like this –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
FROM ubuntu:16.04 MAINTAINER Nick Shores #Install Python 3.6 RUN apt-get update RUN apt-get install -y software-properties-common vim RUN add-apt-repository ppa:jonathonf/python-3.6 RUN apt-get update #install curl RUN apt-get install curl wget RUN apt-get install -y build-essential python3.6 python3.6-dev python3-pip python3.6-venv RUN apt-get install -y git # update pip RUN python3.6 -m pip install pip --upgrade RUN python3.6 -m pip install wheel #Install Pushbullet library RUN pip install pushbullet.py #Install imgrurpython RUN pip install imgurpython #Install MyUsps Library RUN pip install myusps #Update Selenium to 3.6 RUN pip install selenium --upgrade #Clone myusps_notifications repo RUN git clone https://github.com/nshores/my_usps_notifications.git #Install Dependencies RUN apt-get install -y unzip openjdk-8-jre-headless xvfb libxi6 libgconf-2-4 #========= # Firefox #========= ARG FIREFOX_VERSION=latest RUN FIREFOX_DOWNLOAD_URL=$(if [ $FIREFOX_VERSION = "latest" ] || [ $FIREFOX_VERSION = "nightly-latest" ] || [ $FIREFOX_VERSION = "devedition-latest" ]; then echo "https://download.mozilla.org/?product=firefox-$FIREFOX_VERSION-ssl&os=linux64&lang=en-US"; else echo "https://download-installer.cdn.mozilla.net/pub/firefox/releases/$FIREFOX_VERSION/linux-x86_64/en-US/firefox-$FIREFOX_VERSION.tar.bz2"; fi) \ && apt-get update -qqy \ && apt-get -qqy --no-install-recommends install firefox \ && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \ && wget --no-verbose -O /tmp/firefox.tar.bz2 $FIREFOX_DOWNLOAD_URL \ && apt-get -y purge firefox \ && rm -rf /opt/firefox \ && tar -C /opt -xjf /tmp/firefox.tar.bz2 \ && rm /tmp/firefox.tar.bz2 \ && mv /opt/firefox /opt/firefox-$FIREFOX_VERSION \ && ln -fs /opt/firefox-$FIREFOX_VERSION/firefox /usr/bin/firefox # Install geckodriver: RUN export BASE_URL=https://github.com/mozilla/geckodriver/releases/download \ && export VERSION=$(curl -sL \ https://api.github.com/repos/mozilla/geckodriver/releases/latest | \ grep tag_name | cut -d '"' -f 4) \ && curl -sL \ $BASE_URL/$VERSION/geckodriver-$VERSION-linux64.tar.gz | tar -xz \ && mv geckodriver /usr/local/bin/geckodriver # Install Chrome RUN curl -sS -o - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add RUN echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list RUN apt-get -y update RUN apt-get -y install google-chrome-stable #Install Chrome Driver RUN CHROME_DRIVER_VERSION=$(curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE) && wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ RUN unzip ~/chromedriver_linux64.zip -d ~/ RUN rm ~/chromedriver_linux64.zip RUN mv -f ~/chromedriver /usr/local/bin/chromedriver RUN chown root:root /usr/local/bin/chromedriver RUN chmod 0755 /usr/local/bin/chromedriver #Start Main script which runs chromedriver and keeps container open #TODO - Create main start script and loop CMD [ "python3.6", "/my_usps_notifications/mail.py" ] |
After you have this dockerfile created and stored in your github repo, you can connect your repository to Docker Hub . Docker Hub will create images by running the docker build command on your dockerfile, and will store the resulting images on their servers. The manual equivalent of this process is
1 |
sudo docker build . |
In the context of this project, this allows me to distribute my python script as a whole package, that includes all the dependencies in one file, and makes it easier to run. To run my script, all we need to do is run
1 |
sudo docker pull nshores/my_usps_notifications |
Then edit the included docker_run.sh file to start our docker container. Head over to the github repository page for this project if you’d like to grab a copy of this script and get further instructions on usage.
Future Improvements
I’m planning on improving this script and making it a provider agnostic notification agent. I plan to support scraping UPS and Fedex in the future. I’m also going to use the Google Vision API . to extract names from pictures of mail and store that in a database, then notify the person that they have mail via a slack private message. Something like this –
After that’s working I am also going to work on converting this script into a full fledged mail checking slack bot! Check back for updates!
Pingback: Checking your snail mail with Python/Docker and Slack. (Part 1) – Ops and Automation