diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f1aee7ee0c7a8ce7b5d31543feaedf33fdb60cf4..b82d03020c636b47c1b57b215c98677b0280551f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,14 +20,14 @@ stages:
 # Check author list is up to date
 authors:
   stage: initial
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
   script:
     - python test/check_author_list.py
 
 # Test containers scripts are up to date
 containers:
   stage: initial
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
   script:
     - cd containers
     - python write_dockerfiles.py #HACK
@@ -59,10 +59,6 @@ containers:
           ${script} --help;
       done
 
-# basic-3.8:
-#   <<: *test-python
-#   image: python:3.8
-
 basic-3.9:
   <<: *test-python
   image: python:3.9
@@ -78,10 +74,6 @@ basic-3.10:
     - python -m pip list installed
     - python test/test_samplers_import.py
 
-# import-samplers-3.8:
-#   <<: *test-samplers-import
-#   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python38
-
 import-samplers-3.9:
   <<: *test-samplers-import
   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
@@ -102,13 +94,6 @@ import-samplers-3.10:
     # Run precommits (flake8, spellcheck, isort, no merge conflicts, etc)
     - pre-commit run --all-files --verbose --show-diff-on-failure
 
-# precommits-py3.8:
-#   <<: *precommits
-#   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python38
-#   variables:
-#     CACHE_DIR: ".pip38"
-#     PYVERSION: "python38"
-
 precommits-py3.9:
   <<: *precommits
   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
@@ -128,7 +113,7 @@ install:
   parallel:
     matrix:
       - EXTRA: [gw, mcmc, all]
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
   script:
     - pip install .[$EXTRA]
 
@@ -142,15 +127,15 @@ install:
 
     - pytest --cov=bilby --durations 10
 
-# python-3.8:
-#   <<: *unit-test
-#   needs: ["basic-3.8", "precommits-py3.8"]
-#   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python38
-
 python-3.9:
   <<: *unit-test
   needs: ["basic-3.9", "precommits-py3.9"]
   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
+
+python-3.10:
+  <<: *unit-test
+  needs: ["basic-3.10", "precommits-py3.10"]
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
   after_script:
     - coverage html
     - coverage xml
@@ -164,11 +149,6 @@ python-3.9:
       - htmlcov/
     expire_in: 30 days
 
-python-3.10:
-  <<: *unit-test
-  needs: ["basic-3.10", "precommits-py3.10"]
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
-
 .test-sampler: &test-sampler
   stage: test
   script:
@@ -176,11 +156,6 @@ python-3.10:
     - python -m pip list installed
     - pytest test/integration/sampler_run_test.py --durations 10 -v
 
-# python-3.8-samplers:
-#   <<: *test-sampler
-#   needs: ["basic-3.8", "precommits-py3.8"]
-#   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python38
-
 python-3.9-samplers:
   <<: *test-sampler
   needs: ["basic-3.9", "precommits-py3.9"]
@@ -191,10 +166,10 @@ python-3.10-samplers:
   needs: ["basic-3.10", "precommits-py3.10"]
   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
 
-integration-tests-python-3.9:
+integration-tests-python-3.10:
   stage: test
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
-  needs: ["basic-3.9", "precommits-py3.9"]
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
+  needs: ["basic-3.10", "precommits-py3.10"]
   only:
     - schedules
   script:
@@ -212,12 +187,6 @@ integration-tests-python-3.9:
     - python -m pip list installed
     - pytest test/gw/plot_test.py
 
-
-# plotting-python-3.8:
-#   <<: *plotting
-#   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python38
-#   needs: ["basic-3.8", "precommits-py3.8"]
-
 plotting-python-3.9:
   <<: *plotting
   image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
@@ -232,7 +201,7 @@ plotting-python-3.10:
 
 docs:
   stage: docs
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
   before_script:
     - conda install -c conda-forge pandoc ipython jupyter nbconvert
     - python -m pip install ipykernel
@@ -254,7 +223,7 @@ docs:
 
 pages:
   stage: deploy
-  needs: ["docs", "python-3.9"]
+  needs: ["docs", "python-3.10"]
   script:
     - mkdir public/
     - mv htmlcov/ public/
@@ -285,11 +254,6 @@ pages:
     - docker image tag v3-bilby-$PYVERSION containers.ligo.org/lscsoft/bilby/v2-bilby-$PYVERSION:latest
     - docker image push containers.ligo.org/lscsoft/bilby/v2-bilby-$PYVERSION:latest
 
-# build-python38-container:
-#   <<: *build-container
-#   variables:
-#     PYVERSION: "python38"
-
 build-python39-container:
   <<: *build-container
   variables:
@@ -302,7 +266,7 @@ build-python310-container:
 
 pypi-release:
   stage: deploy
-  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python39
+  image: containers.ligo.org/lscsoft/bilby/v2-bilby-python310
   variables:
     TWINE_USERNAME: $PYPI_USERNAME
     TWINE_PASSWORD: $PYPI_PASSWORD
diff --git a/containers/v3-dockerfile-test-suite-python38 b/containers/v3-dockerfile-test-suite-python38
deleted file mode 100644
index 7ee33e7509f7443f36eef2a6dae4e81df0740d11..0000000000000000000000000000000000000000
--- a/containers/v3-dockerfile-test-suite-python38
+++ /dev/null
@@ -1,61 +0,0 @@
-# This dockerfile is written automatically and should not be modified by hand.
-
-FROM containers.ligo.org/docker/base:conda
-LABEL name="bilby CI testing" \
-maintainer="Gregory Ashton <gregory.ashton@ligo.org>"
-
-RUN conda update -n base -c defaults conda
-
-ENV conda_env python38
-
-RUN conda create -n ${conda_env} python=3.8
-RUN echo "source activate ${conda_env}" > ~/.bashrc
-ENV PATH /opt/conda/envs/${conda_env}/bin:$PATH
-RUN /bin/bash -c "source activate ${conda_env}"
-RUN conda info
-RUN python --version
-
-# Install conda-installable programs
-RUN conda install -n ${conda_env} -y matplotlib numpy scipy pandas astropy flake8
-RUN conda install -n ${conda_env} -c anaconda coverage configargparse future dill
-RUN conda install -n ${conda_env} -c conda-forge black pytest-cov deepdish arviz
-
-# Install pip-requirements
-RUN pip install --upgrade pip
-RUN pip install --upgrade setuptools coverage-badge parameterized
-
-# Install documentation requirements
-RUN pip install sphinx numpydoc nbsphinx sphinx_rtd_theme sphinx-tabs autodoc
-
-# Install testing requirements
-RUN conda install -n ${conda_env} -c conda-forge scikit-image celerite george
-
-# Install dependencies and samplers
-RUN pip install corner healpy cython tables
-RUN conda install -n ${conda_env} dynesty emcee nestle ptemcee pymultinest ultranest cpnest kombine dnest4 zeus-mcmc pytorch 'pymc>=4' nessai ptmcmcsampler -c conda-forge -c pytorch
-
-# Install Polychord
-RUN apt-get update --allow-releaseinfo-change
-RUN apt-get install -y build-essential
-RUN apt-get install -y libblas3 libblas-dev
-RUN apt-get install -y liblapack3 liblapack-dev
-RUN apt-get install -y libatlas3-base libatlas-base-dev
-RUN apt-get install -y gfortran
-
-RUN git clone https://github.com/PolyChord/PolyChordLite.git \
-&& (cd PolyChordLite && python setup.py --no-mpi install)
-
-# Install GW packages
-RUN conda install -n ${conda_env} -c conda-forge python-lalsimulation bilby.cython pyseobnr
-RUN pip install ligo-gracedb gwpy ligo.skymap
-
-# Add the ROQ data to the image
-RUN mkdir roq_basis \
-    && cd roq_basis \
-    && wget https://git.ligo.org/lscsoft/ROQ_data/raw/master/IMRPhenomPv2/4s/B_linear.npy \
-    && wget https://git.ligo.org/lscsoft/ROQ_data/raw/master/IMRPhenomPv2/4s/B_quadratic.npy \
-    && wget https://git.ligo.org/lscsoft/ROQ_data/raw/master/IMRPhenomPv2/4s/fnodes_linear.npy \
-    && wget https://git.ligo.org/lscsoft/ROQ_data/raw/master/IMRPhenomPv2/4s/fnodes_quadratic.npy \
-    && wget https://git.ligo.org/lscsoft/ROQ_data/raw/master/IMRPhenomPv2/4s/params.dat \
-    && wget https://git.ligo.org/soichiro.morisaki/roq_basis/raw/main/IMRPhenomD/16s_nospins/basis_addcal.hdf5 \
-    && wget https://git.ligo.org/soichiro.morisaki/roq_basis/raw/main/IMRPhenomD/16s_nospins/basis_multiband_addcal.hdf5
diff --git a/containers/write_dockerfiles.py b/containers/write_dockerfiles.py
index a90d117766a094dea9efe37307c0f93a4c8ea063..60dbf751f080e546ddab7dd63941e4f07b199526 100644
--- a/containers/write_dockerfiles.py
+++ b/containers/write_dockerfiles.py
@@ -3,7 +3,7 @@ from datetime import date
 with open("dockerfile-template", "r") as ff:
     template = ff.read()
 
-python_versions = [(3, 8), (3, 9), (3, 10)]
+python_versions = [(3, 9), (3, 10)]
 today = date.today().strftime("%Y%m%d")
 
 samplers = [
diff --git a/setup.py b/setup.py
index e8b575d2949fb429fa569af8ee7a575815c2e4d3..4ddb9744230089dcddb86a10e967316ee51a9737 100644
--- a/setup.py
+++ b/setup.py
@@ -5,8 +5,8 @@ import sys
 import os
 
 python_version = sys.version_info
-if python_version < (3, 8):
-    sys.exit("Python < 3.8 is not supported, aborting setup")
+if python_version < (3, 9):
+    sys.exit("Python < 3.9 is not supported, aborting setup")
 
 
 def get_long_description():
@@ -85,7 +85,6 @@ setup(
         ]
     },
     classifiers=[
-        "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
         "License :: OSI Approved :: MIT License",