[35] IPython: podstawowa konfiguracja w kontenerze (docker)

Kontener budowany jest na oficjalnych oraz prywatnych obrazach w łańcuchu:

debian [dockerhub] -> python:slim [dockerhub] ->
-> piotrczaja/jupyter-ipython-sqlalchemy:X.X.X-X.X.X-X.X.X-RX [dockerhub] ->
-> kontener skonfigurowany [obraz tworzony lokalnie]

Debian wykorzystywany jest, pomimo dużego rozmiaru podstawowego obrazu, ze względu na łatwą rozbudowę oraz aktualność pakietów (m.in. repozytorium postgresql.org). Python:slim jest najnowszą, dostępną przy budowie obrazu, minimalistyczną instalacją Pythona w gałęzi 3. Obraz piotrczaja/jupyter-ipython-sqlalchemy otagowany jest wykorzystaną wersją jupyter, ipython i sqlalchemy oraz kolejnym numerem wydania i nie uwzględnia opisu latest, więc wymaga podania pełnego taga przy pobieraniu. Wraz z obrazem piotrczaja/jupyter-ipython-sqlalchemy instalowane są pakiety: psycopg2, sqlalchemy, simplejson, jupyter [ipython] wraz z zależnościami.

Obraz budowany lokalnie tworzony jest w oparciu o plik Dockerfile:

# Docker custom ipython image

FROM    piotrczaja/jupyter-ipython-sqlalchemy:X.X.X-X.X.X-X.X.X-RX

MAINTAINER Piotr Czaja <czaja_piotr@o2.pl>
ENV     HOME                /home/ipython
ENV     EXECDR              $HOME/bin
ENV     SERVDR              /srv
ENV     CONFDR              $SERVDR/confs
ENV     DATADR              $SERVDR/files
ENV     BOOKDR              $SERVDR/books
ENV     USRLOC              /usr/local
ENV     ETCDIR              $USRLOC/etc/jupyter
ENV     SHARED              $USRLOC/share/jupyter
ENV     ROOTDR              /root
ENV     DEBIAN_FRONTEND     noninteractive

USER    root

ENV TZ=Europe/Warsaw
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone


COPY    ./bin/                  $EXECDR
COPY    ./config/               $CONFDR
COPY    ./data/                 $DATADR
COPY    ./notebooks/            $BOOKDR

RUN    pip install --no-cache-dir -r $CONFDR/python_requirements.txt

RUN chmod +x $EXECDR/start-notebook.sh  && \
    chown -R ipython:ipython $HOME      && \
    chown -R ipython:ipython $ETCDIR    && \
    chown -R ipython:ipython $SHARED    && \
    chown -R ipython:ipython $EXECDR    && \
    chown -R ipython:ipython $CONFDR    && \
    chown -R ipython:ipython $DATADR    && \
    chown -R ipython:ipython $BOOKDR

EXPOSE 8080

USER    ipython
WORKDIR $BOOKDR

Użytkownik przeznaczony do uruchamiania ipython-notebook to: ipython. Posiada on wszelkie konieczne uprawnienia.

Konfiguracja kopiowana jest z lokalnego katalogu config do katalogu kontenera: /srv/confs/. Dane wykorzystywane do obliczeń kopiowane są z lokalnego katalogu data do katalogu kontenera: /srv/files/. IPython notebooks uruchamiane w kontenerze kopiowane są z lokalnego katalogu notebooks do katalogu kontenera /srv/books/. Skrypty uruchomieniowe aplikacji powinny znajdować się w lokalnym katalogu bin i są kopiowane do katalogu kontenera /home/ipython/bin/. Strefa czasowa ustawiona jest na Europe/Warsaw.

Plik database_creds.json znajdujący się w katalogu lokalnym config zawiera dane potrzebne do połączenia z bazą danych postgresql:

{
    "user_name": "Użytkownik bazy danych",
    "password": "Hasło użytkownika bazy danych",
    "host_name": "nazwa lub IP hosta bazy danych",
    "port_number": "Port na którym nasłuhuje postresql",
    "db_name": "Nazwa bazy danych"
}

Szablon pliku database_creds.json to database_creds.templ. Repozytorium git-a powinno zawierać wpis "database_creds.json" w pliku ".gitignore".

Plik docker-compose.yml powienien zawierać przynajmniej:

version: '2.0'

services:

    ipython:
        build:
            context: .
            dockerfile: ./Dockerfile
        container_name: ipython-ct
        ports:
            - 8001:8080
        command: bash -c "/home/ipython/bin/start-notebook.sh"

volumes: {}

networks: {}

Plik config/python_requirements.txt zawiera wszystkie dodatkowe pakiety pythona. Dla powyższego przykładu należy w nim umieścić conajmniej:

ipython-sql

Jupyter w kontenerze uruchamiany jest skryptem bin/start-notebook.sh, który w minimalistycznej postaci może przybrać postać:

#!/bin/bash

mkdir /home/ipython/.jupyter
mv /srv/confs/jupyter_notebook_config.py /home/ipython/.jupyter/jupyter_notebook_config.py
jupyter notebook

Plik konfiguracyjny jupyter_notebook_config.py umożliwia elastyczną konfigurację. Plik konfiguracyjny mozna wygenerować za pomocą polecenia:

jupyter notebook --generate-config

Każdy IPython-notebook rozpoczyna się standardową treścią:

import psycopg2
import sqlalchemy
import simplejson
%load_ext sql

%config SqlMagic.displaylimit = 5

Psycopg2 jest koniecznym składnikiem do połączenia z bazą danych PostgreSQL. SqlAlchemy jest standardowym pakietem ORM w języku Python. SimpleJson pozwala m.in. na odczytanie danych połączenia i konfiguracji. Kolejne linie służą do obsługi pakietu iPython-SQL który pozwala na wykonywanie bezpośrednich zapytań do bazy danych. Pakiet iPythonSQL udostępnia polecenia:

%sql
%%sql

w notatniku. Obecnie przy uruchomieniu rozszerzenia pakiet powoduje wypisanie wielu ostrzeżeń (brak aktualizacji do najnowszej wersji ipythona) ale działa normalnie.

Dla połączenia z bazą danych należy odczytać dane logowania z pliku json:

with open("/srv/confs/database_creds.json") as db_con_file:
    creds = simplejson.loads(db_con_file.read())

Teraz można połączyć się już z bazą danych, więc potrzebne są parametry połączenia:

connect_to_db = 'postgresql+psycopg2://' + \
                creds['user_name'] + ':' + creds['password'] + '@' + \
                creds['host_name'] + ':' + creds['port_number'] + '/' + \
                creds['db_name']

Zmienna connect_to_db może zostać wykorzystana albo bezpośrednio do połączenia przez ipython-sql:

%sql $connect_to_db

albo do utworzenia sesji sqlalchemy.

Dla sprawdzenia połączenia można wypisać zawartość dowolnej tabeli bazy danych z serwera postgresql:

%%sql

select * from <tabela>

Jeśli tabela zostanie wyświetlona w kolejnej komórce to mamy poprawnie skonfigurowana instalację IPython z dostępem do bazy danych PostgreSQL.