1# Build an image containing all prerequisites needed for all CHART applications
  2
  3# Requires a more recent docker version than v1.13.1 so don't build from a Centos 7.9 machine
  4
  5# Start from Ubuntu 22.04 as it's fast, well maintained and has a good package library
  6# FROM ubuntu:22.04
  7
  8# 20.04 is the last ubuntu release which can run in a centos 7.9 container
  9# 23.04 is the first version to include python 3.11 and should be our target
 10FROM ubuntu:23.04
 11
 12# Install all Python modules and various other tools needed by CHART projects
 13# libaio1 is a dependancy of instantclient - don't omit it otherwise the client fails at runtime
 14# gfortran is used by the semalerts module of CHART-EPS
 15# vim, git, sudo are basically nice-to-have for debugging runtime machines
 16# the python dev and statis analysis tools are so we can run the automated tests
 17# inside docker
 18RUN apt update && \
 19    apt upgrade --yes && \
 20    apt install --yes --no-install-recommends tzdata  && \
 21    ln -fs /usr/share/zoneinfo/Zulu /etc/localtime && \
 22    dpkg-reconfigure --frontend noninteractive tzdata && \
 23    apt install --yes --no-install-recommends \
 24    ansible \
 25    aspell \
 26    aspell-en \
 27    build-essential \
 28    expect \
 29    gettext-base \
 30    gfortran \
 31    git \
 32    gunicorn \
 33    iputils-ping \
 34    libaio1 \
 35    libxml2-utils \
 36    postgresql \
 37    pylint \
 38    python3 \
 39    python3-argcomplete \
 40    python3-astor \
 41    python3-cartopy \
 42    python3-dev \
 43    python3-django \
 44    python3-docutils \
 45    python3-fabulous \
 46    python3-invoke \
 47    python3-lxml \
 48    python3-matplotlib \
 49    python3-mysql.connector \
 50    python3-numpy \
 51    python3-pandas \
 52    python3-paramiko \
 53    python3-pip \
 54    python3-prettytable \
 55    python3-psycopg2 \
 56    python3-pycodestyle \
 57    python3-pydocstyle \
 58    python3-pygments \
 59    python3-pymysql \
 60    python3-pytest \
 61    python3-scipy \
 62    python3-setuptools \
 63    python3-venv \
 64    python3-wheel \
 65    python3-xlrd \
 66    python3-rapidjson \
 67    python3-oracledb \
 68    rlwrap \
 69    slimit \
 70    sudo \
 71    supervisor \
 72    trang \
 73    unzip \
 74    vim \
 75    wget \
 76    wkhtmltopdf
 77
 78# 2nd attempt to install rapidjson as the one above isn't working
 79# RUN apt install --yes --no-install-recommends python3-rapidjson
 80
 81# Set application dir in container
 82WORKDIR /app
 83
 84# get wkhtmltopdf version with patched qt
 85RUN mkdir -p packages && \
 86    cd packages && \
 87    echo "Downloading wkhtmltopdf version with patched qt" && \
 88    wget --quiet https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz && \
 89    tar xvf /app/packages/wkhtmltox*.tar.xz && \
 90    mv wkhtmltox/bin/wkhtmlto* /usr/local/bin/ && \
 91    cd ..
 92
 93# Not currently used, but under Ubuntu 22.04 base the following is required to get PDF report export
 94# working:
 95# strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
 96
 97# Download Oracle instantclient files
 98RUN cd /app && \
 99    mkdir -p packages && \
100    cd packages && \
101    echo Downloading instantclient base && \
102    wget --quiet https://download.oracle.com/otn_software/linux/instantclient/211000/instantclient-basic-linux.x64-21.1.0.0.0.zip && \
103    echo Downloading instantclient sqlplus && \
104    wget --quiet https://download.oracle.com/otn_software/linux/instantclient/211000/instantclient-sqlplus-linux.x64-21.1.0.0.0.zip && \
105    cd ..
106    # echo Downloading instantclient sdk && \
107    # wget --quiet https://download.oracle.com/otn_software/linux/instantclient/211000/instantclient-sdk-linux.x64-21.1.0.0.0.zip && \
108
109# Unpack Oracle instantclient to /usr/local
110# Fixing a missing symlink as we go
111# And adding instantclient to the system library configuration
112# oracledb can run in thin client mode which doesn't need instanceclient
113# but our CHART-EPS database isn't compatible
114RUN cd /usr/local && \
115    unzip -q /app/packages/instantclient-basic-linux.x64-21.1.0.0.0.zip && \
116    unzip -q /app/packages/instantclient-sqlplus-linux.x64-21.1.0.0.0.zip && \
117    cd instantclient_21_1 && \
118    ln -sf libclntsh.so.12.1 libclntsh.so && \
119    ln -sf /usr/local/instantclient_21_1/sqlplus /usr/local/bin && \
120    cd /app && \
121    echo "/usr/local/instantclient_21_1" > /etc/ld.so.conf.d/instanctclient.conf && \
122    ldconfig
123# ENV ORACLE_HOME=/usr/local/instantclient_21_1
124# unzip -q /app/packages/instantclient-sdk-linux.x64-21.1.0.0.0.zip && \
125
126# Patch pytest with the expected name and fix a weird bug in the packaged basemap
127# RUN ln -s /usr/bin/pytest-3 /usr/bin/pytest
128# RUN    perl -p -i -e 's#from matplotlib\.cbook import dedent#from inspect import cleandoc as dedent#' /usr/lib/python3/dist-packages/mpl_toolkits/basemap/proj.py
129
130# Virtual envs aren't working with pytest inside docker, so we do it as root
131# with fixed package versions to avoid potential backward compatibility problems in future.
132# (The install of django-unslashed pulls in django from pypi which I don't like and am not sure
133# how to stop)
134# Expandvars is barely needed as it's just used by the "invoke dev" tool but we're including
135# everything else so why not
136# CHART-EPS and CHART-JCS at least use geoplot widget which hasn't been converted to cartopy
137# so we pull in the obsolete basemap (ubuntu no longer packages it)
138# pip install pytz==2021.1 && \
139    # pip install wheel==0.36.2 && \
140# ubuntu 23.04 comes with oracledb v1.21 which isn't compatible with thick clients
141# so we upgrade
142RUN pip install --break-system-packages basemap
143RUN pip install --break-system-packages --upgrade oracledb && \
144    ORACLE_HOME=/usr/local/instantclient_21_1 pip install --break-system-packages cx_Oracle==8.2.1
145
146
147# Install multipartposthandler2 (required by ucmclient), patching for python3.
148# Disabled because CHART-EPS doesn't currently use it and no other project ever did
149# RUN cd build &&\
150#    tar xf ../packages/MultipartPostHandler2-0.1.5.tar.gz &&\
151#    cd MultipartPostHandler2-0.1.5 &&\
152#    2to3 --write --no-diffs --nobackups MultipartPostHandler.py &&\
153#    cat ../../chart/dist/patches/multipartposthandler/MultipartPostHandler.py.patch | patch -p0 &&\
154#    cp MultipartPostHandler.py /usr/local/lib/python3.8/dist-packages &&\
155#    cd ../..
156
157# Install ucmclient (required for CHART-EPS report publishing), patching for python3
158# Disabled as CHART-EPS doesn't currently use it and no other project ever did
159# RUN cd build &&\
160#    tar xf ../packages/ucmclient-0.1.0.tar.gz &&\
161#    cd ucmclient-0.1.0/ucmclient &&\
162#    2to3 --write --no-diffs --nobackups ucmclient.py &&\
163#    perl -p -i -e 's/import simplejson as json/import json/' ucmclient.py &&\
164#    cp ucmclient.py /usr/local/lib/python3.8/dist-packages &&\
165#    cd ../..
166
167# Cleanup of installation media
168RUN rm -rf packages && \
169    apt clean
170
171# Fix runtime error if basemap doesn't find user matplotlibrc
172RUN mkdir -p .config/matplotlib && \
173    chmod 777 .config/matplotlib && \
174    cp /usr/share/matplotlib/mpl-data/matplotlibrc .config/matplotlib
175
176# Transfer autotest of environment into the image so we've got something to run
177COPY tests/environment/test_prereq.py .
178
179# Run the environment automated test
180CMD pytest -v test_prereq.py