Repository: opensafely-core/cohort-extractor (language: python)

Issue:
We should use the same base docker image as other OpenSAFELY projects
And we should apt install Python rather than compiling it with `pyenv` as we do here:
https://github.com/opensafely/job-runner/blob/master/Dockerfile


Discussion / hints:

Fix patch:
diff --git a/Dockerfile b/Dockerfile
index 8ff7a29a..882fc4b5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,64 +1,39 @@
-FROM ubuntu:bionic
+FROM ghcr.io/opensafely-core/base-docker
+
+RUN \
+  apt-get update --fix-missing && \
+  apt-get install -y python3.8 python3.8-dev python3-pip git curl unixodbc-dev && \
+  update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1
+
+# Install mssql tools
+RUN \
+  apt-get install -y gnupg && \
+  curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \
+  curl https://packages.microsoft.com/config/ubuntu/18.04/prod.list > /etc/apt/sources.list.d/mssql-release.list && \
+  apt-get update && \
+  ACCEPT_EULA=Y apt-get install -y msodbcsql17 && \
+  ACCEPT_EULA=Y apt-get install -y mssql-tools
 
-# PYTHON_VERSION can be changed, by passing `--build-arg
-# PYTHON_VERSION=<new version>` during docker build
-ARG PYTHON_VERSION=3.7.8
-ENV PYTHON_VERSION=${PYTHON_VERSION}
-
-ENV DEBIAN_FRONTEND noninteractive
-ENV DEBCONF_NONINTERACTIVE_SEEN true
-ENV UBUNTU_VERSION $ubuntuversion
-RUN apt-get update
-RUN apt-get -y upgrade
-
-# Python dependencies
-RUN apt-get install -y --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
-# Pyenv dependencies
-RUN apt-get install -y ca-certificates git
-
-# Install pyenv
-RUN curl https://pyenv.run | bash
-ENV PATH="/root/.pyenv/shims:/root/.pyenv/bin:${PATH}"
-ENV PYENV_SHELL=bash
-
-# Install python
-RUN pyenv install $PYTHON_VERSION
-RUN pyenv global $PYTHON_VERSION
-
-# Setting this in the environment takes precendence over
-# `.python-version` files, thus making a clash with any pyenv
-# configuration on the docker host less likely
-ENV PYENV_VERSION $PYTHON_VERSION
-
-# Install mssql
-RUN apt-get install -y gnupg
-RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
-RUN curl https://packages.microsoft.com/config/ubuntu/18.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
-RUN apt-get update
-RUN ACCEPT_EULA=Y apt-get install -y msodbcsql17
-RUN ACCEPT_EULA=Y apt-get install -y mssql-tools
 ENV PATH=$PATH:/opt/mssql-tools/bin
 
-RUN mkdir /workspace
-RUN mkdir /app
-WORKDIR /app
-
-# Install pip and requirements
-COPY requirements.txt /app
-# Extra dependencies needed by python packages
-RUN apt-get install -y unixodbc-dev
-RUN curl https://bootstrap.pypa.io/get-pip.py | python
-RUN pip install --requirement requirements.txt
-RUN apt-get update
-RUN apt-get install -y docker.io
-
+# Copy in app code and install requirements
+RUN \
+  mkdir /app && \
+  mkdir /workspace
 COPY . /app
 
-# .python-version is not needed but can make its way into the image when built
-# locally
-RUN rm -f .python-version
-RUN python setup.py develop
-RUN pyenv rehash
+# We have to set this because requirements.txt contains relative path
+# references
+WORKDIR /app
+
+# We run `cohortextractor --help` at the end to force dependencies to import
+# because the first time we import matplotlib we get a "generated new
+# fontManager" message and we want to trigger that now rather than every time
+# we run the docker image
+RUN \
+  python -m pip install --upgrade 'pip>=21,<22' && \
+  python -m pip install --requirement requirements.txt && \
+  cohortextractor --help
 
 WORKDIR /workspace
 
diff --git a/requirements.in b/requirements.in
index 707ee6d5..d4568780 100644
--- a/requirements.in
+++ b/requirements.in
@@ -9,7 +9,7 @@
 # For more background on this see:
 # https://github.com/opensafely/cohort-extractor/pull/286
 #
-https://github.com/opensafely/ctds-binary/raw/b76175dd04baace2327518a78536d35bac6c7e2b/dist/ctds-1.12.0-cp37-cp37m-manylinux2014_x86_64.whl ; sys_platform == "linux"
+https://github.com/opensafely/ctds-binary/raw/9466f4bdb8eb70318256115c3bbb6b3ecc9351d0/dist/ctds-1.13.0-cp38-cp38-manylinux2014_x86_64.whl ; sys_platform == "linux"
 
 # We still use pyODBC in our tests because we use SQLAlchemy to set up our test
 # data and there's currently no SQLAlchemy adapter for cTDS. I managed to get
diff --git a/requirements.txt b/requirements.txt
index 73c5685b..8fd95c6c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -34,7 +34,7 @@ click==7.1.2
     #   presto-python-client
 cryptography==3.3.1
     # via pyopenssl
-https://github.com/opensafely/ctds-binary/raw/b76175dd04baace2327518a78536d35bac6c7e2b/dist/ctds-1.12.0-cp37-cp37m-manylinux2014_x86_64.whl ; sys_platform == "linux"
+https://github.com/opensafely/ctds-binary/raw/9466f4bdb8eb70318256115c3bbb6b3ecc9351d0/dist/ctds-1.13.0-cp38-cp38-manylinux2014_x86_64.whl ; sys_platform == "linux"
     # via -r requirements.in
 cycler==0.10.0
     # via matplotlib
@@ -52,13 +52,6 @@ identify==1.5.11
     # via pre-commit
 idna==2.9
     # via requests
-importlib-metadata==3.3.0
-    # via
-    #   flake8
-    #   pluggy
-    #   pre-commit
-    #   pytest
-    #   virtualenv
 isort==5.7.0
     # via -r requirements.in
 kiwisolver==1.2.0
@@ -181,10 +174,7 @@ toml==0.10.2
 typed-ast==1.4.2
     # via black
 typing-extensions==3.7.4.3
-    # via
-    #   black
-    #   importlib-metadata
-    #   structlog
+    # via black
 urllib3==1.25.9
     # via requests
 virtualenv==20.2.2
@@ -193,8 +183,6 @@ wcwidth==0.1.9
     # via
     #   prettytable
     #   pytest
-zipp==3.4.0
-    # via importlib-metadata
 
 # The following packages are considered to be unsafe in a requirements file:
 # pip


Test patch:
diff --git a/.github/workflows/test_runner.yaml b/.github/workflows/test_runner.yaml
index 8a16d415..482abc8c 100644
--- a/.github/workflows/test_runner.yaml
+++ b/.github/workflows/test_runner.yaml
@@ -14,7 +14,7 @@ jobs:
       - uses: actions/checkout@v2
       - uses: actions/setup-python@v2
         with:
-          python-version: "3.7"
+          python-version: "3.8"
       - name: Install
         run: |
           set -xe
@@ -36,7 +36,7 @@ jobs:
       - uses: actions/checkout@v2
       - uses: actions/setup-python@v2
         with:
-          python-version: "3.7"
+          python-version: "3.8"
       - uses: actions/cache@v2
         with:
           path: ${{ github.workspace }}/venv
@@ -55,7 +55,7 @@ jobs:
       - uses: actions/checkout@v2
       - uses: actions/setup-python@v2
         with:
-          python-version: "3.7"
+          python-version: "3.8"
       - uses: actions/cache@v2
         with:
           path: ${{ github.workspace }}/venv
@@ -75,7 +75,7 @@ jobs:
     - uses: actions/checkout@v2
     - uses: actions/setup-python@v2
       with:
-        python-version: "3.7"
+        python-version: "3.8"
     - name: Install wheel package
       run: pip install wheel
     - name: Build package