Skip to content

Commit 7c3a11c

Browse files
JHopeCollinspbrubeck
authored andcommitted
More flexible dockerfile and build dev containers on CI. (#4533)
1 parent 68226c5 commit 7c3a11c

File tree

7 files changed

+199
-21
lines changed

7 files changed

+199
-21
lines changed

.github/workflows/core.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ jobs:
108108
# Make sure the current directory is empty
109109
run: find . -delete
110110

111+
# Check that the Dockerfile is using the latest Ubuntu version.
112+
# The version is hardcoded into the Dockerfile so that the OS
113+
# for each release is fixed.
114+
- name: Check Dockerfile Ubuntu version
115+
run: |
116+
latest_version=$(grep "VERSION_ID=" /etc/os-release | cut -d '"' -f 2)
117+
docker_version=$(grep FROM docker/Dockerfile.vanilla | cut -d ':' -f 2)
118+
if [[ "$docker_version" != "$latest_version" ]]; then
119+
echo "Ubuntu version ${docker_version} in Dockerfile is out of date with latest version ${latest_version}"
120+
exit 1
121+
fi
122+
111123
# Use a different mirror to fetch apt packages from to get around
112124
# temporary outage.
113125
# (https://askubuntu.com/questions/1549622/problem-with-archive-ubuntu-com-most-of-the-servers-are-not-responding)

.github/workflows/docker.yml

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ on:
66
tag:
77
description: Docker image tag
88
type: string
9+
build_dev:
10+
description: Whether to build a developer vanilla-default container
11+
type: boolean
12+
default: false
13+
branch:
14+
description: Which Firedrake branch to build the containers from
15+
type: string
16+
default: "release"
917
secrets:
1018
DOCKERHUB_USER:
1119
required: true
@@ -16,6 +24,14 @@ on:
1624
tag:
1725
description: Docker image tag
1826
type: string
27+
build_dev:
28+
description: Whether to build a developer vanilla-default container
29+
type: boolean
30+
default: false
31+
branch:
32+
description: Which Firedrake branch to build the containers from
33+
type: string
34+
default: "release"
1935

2036
jobs:
2137
# Firedrake only
@@ -25,18 +41,26 @@ jobs:
2541
matrix:
2642
os: [Linux, macOS]
2743
arch: [default, complex]
28-
include:
44+
platform: [linux/amd64, linux/arm64]
45+
# Cannot use inputs in exclude clauses, so add a dummy matrix dim
46+
build_dev:
47+
- ${{ inputs.build_dev }}
48+
# exclude incompatible os+platform, and only build linux dev containers
49+
exclude:
2950
- os: Linux
51+
platform: linux/arm64
52+
- os: macOS
3053
platform: linux/amd64
3154
- os: macOS
32-
platform: linux/arm64
55+
build_dev: true
3356
uses: ./.github/workflows/docker_build.yml
3457
with:
3558
os: ${{ matrix.os }}
3659
platform: ${{ matrix.platform }}
3760
arch: ${{ matrix.arch }}
3861
target: firedrake-vanilla-${{ matrix.arch }}
3962
tag: ${{ inputs.tag }}
63+
branch: ${{ inputs.branch }}
4064
dockerfile: docker/Dockerfile.vanilla
4165
secrets: inherit
4266

@@ -50,10 +74,12 @@ jobs:
5074
with:
5175
target: firedrake-vanilla-${{ matrix.arch }}
5276
tag: ${{ inputs.tag }}
77+
tag_latest: ${{ ! inputs.build_dev }}
5378
secrets: inherit
5479

5580
# Firedrake and friends
5681
docker_build_firedrake:
82+
if: ${{ ! inputs.build_dev }}
5783
needs: docker_merge_vanilla
5884
uses: ./.github/workflows/docker_build.yml
5985
# Only build the 'firedrake' container for 'linux/amd64' because
@@ -69,15 +95,18 @@ jobs:
6995
secrets: inherit
7096

7197
docker_merge_firedrake:
98+
if: ${{ ! inputs.build_dev }}
7299
uses: ./.github/workflows/docker_merge.yml
73100
needs: docker_build_firedrake
74101
with:
75102
target: firedrake
76103
tag: ${{ inputs.tag }}
104+
tag_latest: ${{ ! inputs.build_dev }}
77105
secrets: inherit
78106

79107
# Firedrake with Jupyter notebooks
80108
docker_build_jupyter:
109+
if: ${{ ! inputs.build_dev }}
81110
needs: docker_merge_firedrake
82111
uses: ./.github/workflows/docker_build.yml
83112
with:
@@ -89,9 +118,11 @@ jobs:
89118
secrets: inherit
90119

91120
docker_merge_jupyter:
121+
if: ${{ ! inputs.build_dev }}
92122
uses: ./.github/workflows/docker_merge.yml
93123
needs: docker_build_jupyter
94124
with:
95125
target: firedrake-jupyter
96126
tag: ${{ inputs.tag }}
127+
tag_latest: ${{ ! inputs.build_dev }}
97128
secrets: inherit

.github/workflows/docker_build.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ on:
3232
description: 'Firedrake arch to build'
3333
required: false
3434
type: string
35+
default: 'default'
36+
branch:
37+
description: 'Firedrake branch to build'
38+
required: false
39+
type: string
40+
default: 'release'
3541
secrets:
3642
# Docker login information
3743
DOCKERHUB_USER:
@@ -77,6 +83,7 @@ jobs:
7783
file: ${{ inputs.dockerfile }}
7884
build-args: |
7985
ARCH=${{ inputs.arch }}
86+
BRANCH=${{ inputs.branch }}
8087
outputs: type=image,name=firedrakeproject/${{ inputs.target }},push-by-digest=true,name-canonical=true,push=true
8188

8289
- name: Export digest

.github/workflows/docker_merge.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ on:
1414
description: Docker image tag
1515
required: true
1616
type: string
17+
tag_latest:
18+
description: Whether to add additional 'latest' tag to containers
19+
default: false
20+
type: boolean
1721
secrets:
1822
# Docker login information
1923
DOCKERHUB_USER:
@@ -50,10 +54,16 @@ jobs:
5054
- name: Merge and push the per-platform images
5155
working-directory: ${{ runner.temp }}/digests
5256
run: |
53-
docker buildx imagetools create \
54-
-t firedrakeproject/${{ inputs.target }}:${{ inputs.tag }} \
55-
-t firedrakeproject/${{ inputs.target }}:latest \
56-
$(printf 'firedrakeproject/${{ inputs.target }}@sha256:%s ' *)
57+
if [[ "${{ inputs.tag_latest }}" == "true" ]]; then
58+
docker buildx imagetools create \
59+
-t firedrakeproject/${{ inputs.target }}:${{ inputs.tag }} \
60+
-t firedrakeproject/${{ inputs.target }}:latest \
61+
$(printf "firedrakeproject/${{ inputs.target }}@sha256:%s " *)
62+
else
63+
docker buildx imagetools create \
64+
-t firedrakeproject/${{ inputs.target }}:${{ inputs.tag }} \
65+
$(printf "firedrakeproject/${{ inputs.target }}@sha256:%s " *)
66+
fi
5767
5868
- name: Inspect image
5969
run: |

.github/workflows/push.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,12 @@ jobs:
1515
test_macos: true
1616
deploy_website: true
1717
secrets: inherit
18+
19+
docker:
20+
name: Build developer Docker containers
21+
uses: ./.github/workflows/docker.yml
22+
with:
23+
tag: dev-${{ github.ref_name }}
24+
branch: ${{ github.ref_name }}
25+
build_dev: true
26+
secrets: inherit

.github/workflows/release.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ jobs:
1919
uses: ./.github/workflows/docker.yml
2020
with:
2121
tag: ${{ github.ref_name }}
22+
branch: ${{ github.ref_name }}
23+
build_dev: false
2224
secrets: inherit

docker/Dockerfile.vanilla

Lines changed: 122 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,70 @@
11
# Dockerfile for a plain Firedrake suitable for testing Firedrake components and applications
2+
# Firedrake is installed as a system package so doesn't require activating a venv.
3+
#
4+
# Three types of build are available:
5+
# 1. A "release" build for a specific version (e.g. 2025.4.2).
6+
# 2. A "release" build with the "release" branch at the latest commit.
7+
# 3. A "developer" build with the "main" branch at the latest commit
8+
#
9+
# A release build will install:
10+
# - Firedrake in editable mode from the specified release tag or branch.
11+
# - PETSc and SLEPc from the corresponding release (specified by firedrake-configure).
12+
# A developer build will install:
13+
# - Firedrake in editable mode from the main branch.
14+
# - PETSc and SLEPc from the main branch.
15+
# - Python dependencies in editable mode that firedrake/main requires the latest main branch for (pyadjoint, ufl, etc).
16+
#
17+
# The two main command line arguments are:
18+
#
19+
# ARCH:
20+
# The `--arch` argument to firedrake-configure, e.g. default, complex
21+
#
22+
# BRANCH:
23+
# Whether to build a release version of Firedrake.
24+
# Options:
25+
# - "release" Build from the latest release branch.
26+
# - <release tag> Build a specific release (e.g. 2025.4.2).
27+
# - "main" Build a developer install from the latest main branch.
28+
#
29+
# Extra apt packages and PETSc configure arguments can also be
30+
# provided with the following command line arguments:
31+
#
32+
# APT_EXTRA_PACKAGES:
33+
# Extra packages to pass to `apt install`
34+
#
35+
# PETSC_EXTRA_ARGS:
36+
# Extra arguments to pass to PETSc's `configure` script
37+
#
38+
# Example usage for a specific firedrake release with complex scalars:
39+
# $ docker build \
40+
# --file=Dockerfile.vanilla \
41+
# --tag=firedrake:2025.4.2-complex \
42+
# --build-arg ARCH=complex \
43+
# --build-arg BRANCH=2025.4.2
44+
#
45+
# Example usage for building from firedrake main with real scalars, ml installed with PETSc, and valgrind installed with apt:
46+
# $ docker build \
47+
# --file=Dockerfile.vanilla \
48+
# --tag=firedrake:main-latest \
49+
# --build-arg ARCH=default \
50+
# --build-arg BRANCH=main \
51+
# --build-arg PETSC_EXTRA_ARGS="--download-ml" \
52+
# --build-arg APT_EXTRA_PACKAGES="valgrind"
253

3-
FROM ubuntu:latest
54+
FROM ubuntu:24.04
455

556
# Firedrake arch to build
657
ARG ARCH="default"
758

59+
# Is this a release build?
60+
ARG BRANCH="release"
61+
62+
# Extra system packages
63+
ARG APT_EXTRA_PACKAGES=
64+
65+
# Extra PETSc configuration options
66+
ARG PETSC_EXTRA_ARGS=
67+
868
# Set '-o pipefail' to avoid linter error (https://github.com/hadolint/hadolint/wiki/DL4006)
969
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
1070

@@ -18,48 +78,95 @@ ENV TZ=Europe/London
1878

1979
# Install 'parallel' because it is needed by 'firedrake-run-split-tests'
2080
RUN apt-get update \
21-
&& apt-get -y install curl parallel python3 python3-pip python3-venv sudo \
81+
&& apt-get -y install curl parallel python3 python3-pip python3-venv sudo graphviz graphviz-dev \
2282
&& rm -rf /var/lib/apt/lists/*
2383

2484
# Allow pip to install into system package locations without prompting
2585
ENV PIP_BREAK_SYSTEM_PACKAGES=1
2686
ENV OMP_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1
2787

28-
# Download firedrake-configure
29-
RUN curl -O --output-dir /opt https://raw.githubusercontent.com/firedrakeproject/firedrake/release/scripts/firedrake-configure
88+
# Where to download firedrake-configure from
89+
RUN curl -O --output-dir /opt https://raw.githubusercontent.com/firedrakeproject/firedrake/${BRANCH}/scripts/firedrake-configure
3090

3191
# Install system dependencies
3292
RUN apt-get update \
3393
&& apt-get -y install \
3494
$(python3 /opt/firedrake-configure --arch $ARCH --show-system-packages) \
95+
${APT_EXTRA_PACKAGES} \
3596
&& rm -rf /var/lib/apt/lists/*
3697

3798
# OpenMPI will complain if mpiexec is invoked as root unless these are set
3899
ENV OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
39100

40-
# Install PETSc. We set the compiler optimisation flags manually here to
41-
# remove the default of '-march=native -mtune=native' which is not suitable for Docker images.
42-
RUN git clone --depth 1 --branch $(python3 /opt/firedrake-configure --show-petsc-version) https://gitlab.com/petsc/petsc.git /opt/petsc \
101+
# Install PETSc.
102+
# 1. Clone the release tag of PETSc if we're installing a Firedrake release.
103+
# 2. We set the compiler optimisation flags manually here to remove the default
104+
# of '-march=native -mtune=native' which is not suitable for Docker images.
105+
# 3. Remove non-essential files to reduce container size (keep SLEPc for slepc4py).
106+
RUN if [ "${BRANCH}" != "main" ]; then \
107+
CLONE_ARGS="--branch $(python3 /opt/firedrake-configure --show-petsc-version)"; \
108+
fi; \
109+
git clone --depth 1 ${CLONE_ARGS} https://gitlab.com/petsc/petsc.git /opt/petsc \
43110
&& cd /opt/petsc \
44111
&& python3 /opt/firedrake-configure --arch $ARCH --show-petsc-configure-options | \
45112
sed "s/-march=native -mtune=native/-mtune=generic/g" | \
46-
xargs -L1 ./configure --with-make-np=8 --download-slepc \
47-
&& make \
48-
&& make check \
49-
&& rm -rf ./**/externalpackages \
50-
&& rm -rf ./src/docs \
113+
xargs -L1 ./configure --with-make-np=8 --download-slepc ${PETSC_EXTRA_ARGS} \
114+
&& make; \
115+
if [ $? -eq 1 ]; then \
116+
cat configure.log; \
117+
exit; \
118+
fi; \
119+
make check || exit; \
120+
for pkg in $(ls ./arch-firedrake-${ARCH}/externalpackages/); do \
121+
if [ "${pkg}" != "git.slepc" ]; then \
122+
rm -rf ./arch-firedrake-${ARCH}/${pkg} || exit; \
123+
fi; \
124+
done; \
125+
rm -rf ./src/docs \
51126
&& rm -f ./src/**/tutorials/output/* \
52127
&& rm -f ./src/**/tests/output/* \
53128
&& cd - || exit
54129

55130
ENV PETSC_DIR=/opt/petsc PETSC_ARCH=arch-firedrake-$ARCH
131+
ENV SLEPC_DIR=$PETSC_DIR/$PETSC_ARCH
56132
ENV PATH="$PETSC_DIR/$PETSC_ARCH/bin:$PATH"
57133

58134
ENV HDF5_MPI=ON
59135
ENV CC=mpicc CXX=mpicxx
60-
ENV CFLAGS="-mtune=generic" CPPFLAGS="-mtune=generic"
61136
ENV MPICC=$CC
137+
ENV CFLAGS="-O3 -mtune=generic" CPPFLAGS="-O3 -mtune=generic"
62138

63139
# Install Firedrake
64-
RUN pip install --verbose --no-binary h5py --src /opt \
65-
--editable git+https://github.com/firedrakeproject/firedrake.git@release#egg=firedrake[docker]
140+
# - petsc4py and slepc4py are installed from source in PETSc repo.
141+
# - slepc4py is installed without build isolation so it links against
142+
# the correct petsc4py version.
143+
# - Firedrake main branch requires main/master branch of some upstream
144+
# packages. These are installed in editable mode.
145+
# The order these are installed is important, e.g. FIAT must be installed
146+
# before UFL otherwise `pip install fiat` will reinstall pypi ufl.
147+
RUN git clone --branch ${BRANCH} \
148+
https://github.com/firedrakeproject/firedrake.git /opt/firedrake \
149+
&& pip cache purge \
150+
&& pip install --verbose ${PETSC_DIR}/src/binding/petsc4py \
151+
&& pip install --verbose -r /opt/firedrake/requirements-build.txt \
152+
&& pip install --verbose --no-build-isolation \
153+
${SLEPC_DIR}/externalpackages/git.slepc/src/binding/slepc4py \
154+
&& pip install --verbose --no-binary h5py --no-build-isolation \
155+
--editable '/opt/firedrake[docker]' || exit; \
156+
if [ ${BRANCH} == "main" ]; then \
157+
for pkg in \
158+
"git+https://github.com/dolfin-adjoint/pyadjoint.git#egg=pyadjoint-ad" \
159+
"git+https://github.com/firedrakeproject/fiat.git#egg=firedrake-fiat" \
160+
"git+https://github.com/FEniCS/ufl.git#egg=fenics-ufl" \
161+
; do \
162+
pip install --verbose --src /opt --editable ${pkg} || exit; \
163+
done; \
164+
fi
165+
166+
# Force '-mtune=generic' for JIT-ed code
167+
ENV PYOP2_CFLAGS=$CFLAGS
168+
169+
# Run the smoke tests.
170+
RUN cd /opt/firedrake/ \
171+
&& firedrake-check \
172+
&& firedrake-clean

0 commit comments

Comments
 (0)