Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically build docker images for each Brian release #1503

Merged
merged 35 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
05c75d1
Initial commit
bdevans Feb 12, 2024
e038100
Tidy up
bdevans Feb 14, 2024
55ace74
Add README with instructions
bdevans Feb 15, 2024
40eeebe
Fix sudo
bdevans Feb 21, 2024
7da7e7a
Remove unnecessary use of `buildx`
bdevans Feb 21, 2024
cde781f
Update instructions
bdevans Feb 21, 2024
bb3e4e4
Rename
bdevans Feb 26, 2024
124304e
Update to use slim image and tidy comments
bdevans Feb 26, 2024
1d2409c
Add test instructions
bdevans Feb 26, 2024
43ce0a5
Merge remote-tracking branch 'refs/remotes/origin/docker_images' into…
bdevans Feb 26, 2024
5b56339
Add docker pulls badge
bdevans Mar 7, 2024
d0e94c5
Move docker image action into release
mstimberg Mar 7, 2024
2a15a55
Rename publish action
mstimberg Mar 7, 2024
9e93193
Add publish status badge
bdevans Mar 7, 2024
50ac8ce
Merge remote-tracking branch 'refs/remotes/origin/docker_images' into…
bdevans Mar 7, 2024
50db33d
Use local wheels in docker build
mstimberg Mar 7, 2024
85d1bb6
Only push tags to docker hub
mstimberg Mar 7, 2024
b224f62
Fix use of download-artifact action
mstimberg Mar 7, 2024
fb78e25
Use recommended invocation of pip
bdevans Mar 7, 2024
7051fea
Use compatible download/upload actions
mstimberg Mar 7, 2024
b3f9562
Remove deployment environment (for now)
mstimberg Mar 7, 2024
15f8870
Separate package names for upload-artifact@v4
mstimberg Mar 7, 2024
93bbd60
Even more distinct package names for artifacts
mstimberg Mar 7, 2024
873d355
download with correct package names
mstimberg Mar 7, 2024
9b7f966
Only use manylinux wheels
mstimberg Mar 7, 2024
9c7f64b
Fix expression syntax
mstimberg Mar 7, 2024
43eb956
Misunderstood how the new pattern/merge feature was supposed to work …
mstimberg Mar 8, 2024
4b6962b
Upload docker image as artifact
mstimberg Mar 8, 2024
244d0cc
Cannot use load for multi-arch image, trying again
mstimberg Mar 8, 2024
86a863b
Push docker image to brian-dev repository
mstimberg Mar 8, 2024
67d0242
Document docker build process
mstimberg Mar 8, 2024
f437aa6
Fix formatting for multi-line command
mstimberg Mar 8, 2024
84b2ad8
Use uname -m for architecture
mstimberg Mar 11, 2024
77c7263
Install libgsl-dev for GSL support
mstimberg Mar 11, 2024
6f8a3d8
Rearrange
bdevans Mar 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build and publish to TestPyPI or PyPI
name: Build and publish
on: [push, pull_request]

jobs:
Expand Down Expand Up @@ -43,9 +43,9 @@ jobs:
CIBW_TEST_COMMAND: python {project}/dev/continuous-integration/run_simple_test.py
CIBW_TEST_REQUIRES: pytest
- name: store distribution 📦
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: packages
name: packages-${{ matrix.os }}
path: dist

build-linux:
Expand Down Expand Up @@ -86,9 +86,9 @@ jobs:
CIBW_TEST_COMMAND: python {project}/dev/continuous-integration/run_simple_test.py
CIBW_TEST_REQUIRES: pytest
- name: store distribution 📦
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: packages
name: packages-linux-${{ matrix.arch }}
path: dist

deploy_dev:
Expand All @@ -103,9 +103,10 @@ jobs:
- build-linux
steps:
- name: load distribution 📦
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: packages
pattern: packages-*
merge-multiple: true
path: dist/
- name: Publish distribution 📦 to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Expand All @@ -124,9 +125,83 @@ jobs:
- build-linux
steps:
- name: load distribution 📦
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: packages
pattern: packages-*
merge-multiple: true
path: dist/
- name: Publish distribution release 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

build-docker:
name: Build docker image
runs-on: ubuntu-latest
needs: build-linux
steps:
- name: Checkout repository
uses: actions/checkout@v4
# https://github.com/actions/checkout/
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
# https://github.com/docker/metadata-action
with:
images: |
briansimulator/brian
flavor: latest=true
tags: |
# type=semver,pattern={{raw}}
type=ref,event=tag
labels: |
org.opencontainers.image.title="Brian Docker Image"
org.opencontainers.image.description="Docker image for Brian - a free, open source simulator for spiking neural networks"
org.opencontainers.image.url=https://hub.docker.com/r/briansimulator/brian
org.opencontainers.image.source=https://github.com/brian-team/brian2
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# https://github.com/docker/setup-qemu-action
with:
platforms: 'amd64,arm64'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# https://github.com/docker/setup-buildx-action
- name: Login to DockerHub
uses: docker/login-action@v3
# https://github.com/docker/login-action
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: load Linux x86 distribution 📦
uses: actions/download-artifact@v4
with:
pattern: packages-linux-*
merge-multiple: true
path: packages
- run: |
mkdir dist
cp packages/Brian2*cp312-manylinux*_x86_64.whl dist
cp packages/Brian2*cp312-manylinux*_aarch64.whl dist
- name: Build (and potentially push) the Docker image
uses: docker/build-push-action@v5
# https://github.com/docker/build-push-action
with:
context: .
file: docker/Dockerfile
build-args: |
'BASE_IMAGE_TAG=3.12-bookworm'
platforms: 'amd64,arm64'
push: ${{ github.repository == 'brian-team/brian2' && startsWith(github.ref, 'refs/tags') }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Push docker image to dev repository
if: ${{ github.repository == 'brian-team/brian2' && github.event_name == 'push' && !startsWith(github.ref, 'refs/tags') }}
uses: docker/build-push-action@v5
with:
context: .
file: docker/Dockerfile
build-args: |
'BASE_IMAGE_TAG=3.12-bookworm'
platforms: 'amd64,arm64'
push: true
tags: briansimulator/brian-dev:dev-${{ github.ref_name }}
labels: ${{ steps.meta.outputs.labels }}
8 changes: 7 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ Stimberg, M, Brette, R, Goodman, DFM. “Brian 2, an Intuitive and Efficient Neu
.. image:: https://img.shields.io/conda/vn/conda-forge/brian2.svg
:target: https://anaconda.org/conda-forge/brian2


.. image:: https://img.shields.io/debian/v/python3-brian/testing
:alt: Debian package
:target: https://packages.debian.org/testing/python3-brian
Expand All @@ -40,6 +39,13 @@ Stimberg, M, Brette, R, Goodman, DFM. “Brian 2, an Intuitive and Efficient Neu
:alt: AUR version
:target: https://aur.archlinux.org/packages/python-brian2

.. image:: https://github.com/brian-team/brian2/actions/workflows/publish.yml/badge.svg
:target: https://github.com/brian-team/brian2/actions/workflows/publish.yml
:alt: Publish status on GitHub Actions

.. image:: https://img.shields.io/docker/pulls/briansimulator/brian
:alt: Docker Pulls


.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.8099373.svg
:target: https://doi.org/10.5281/zenodo.8099373
Expand Down
61 changes: 61 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# docker buildx build --push --platform linux/amd64,linux/arm64/v8 -o type=image -t briansimulator/brian -f docker/Dockerfile .
# docker run -it --init --rm -p 8888:8888 briansimulator/brian

ARG BASE_IMAGE_TAG=3.12-slim-bookworm
FROM python:${BASE_IMAGE_TAG}

LABEL maintainer="Ben Evans <[email protected]>" \
org.opencontainers.image.vendor="The Brian Development Team" \
org.opencontainers.image.licenses="CeCILL 2.1" \
org.opencontainers.image.title="Brian Docker Image" \
org.opencontainers.image.description="Docker image for Brian - a free, open source simulator for spiking neural networks" \
org.opencontainers.image.homepage="https://briansimulator.org" \
org.opencontainers.image.url="https://hub.docker.com/r/briansimulator/brian" \
org.opencontainers.image.source="https://github.com/brian-team/brian2" \
org.opencontainers.image.documentation="https://brian2.readthedocs.io/"

# Install dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
g++ \
git \
libgsl-dev \
sudo \
&& rm -rf /var/lib/apt/lists/*

# Copy wheels into the image
COPY dist /tmp/dist

# Install Brian2 and recommended packages
RUN python -m pip install --no-cache-dir --only-binary=:all: \
scipy \
matplotlib \
jupyterlab \
pytest \
pytest-xdist \
&& python -m pip install /tmp/dist/Brian2*_$(uname -m).whl brian2tools \
&& rm -rf /tmp/dist

# Create a non-root user
ARG USER="monty" \
GROUP="monty" \
PASSWORD="monty"
RUN groupadd ${GROUP} && \
useradd -ms /bin/bash -g ${GROUP} -G sudo ${USER} && \
echo "${USER}:${PASSWORD}" | chpasswd
ENV HOME="/home/${USER}"
RUN chown -R ${USER}:${USER} ${HOME}
USER ${USER}

# Copy tutorial notebooks and example scripts to home directory
WORKDIR ${HOME}
RUN git clone https://github.com/brian-team/brian2.git \
&& mv brian2/examples examples \
&& mv brian2/tutorials tutorials \
&& chmod -R +x tutorials \
&& chmod -R +x examples \
&& find . -name '*.ipynb' -exec jupyter trust {} \; \
&& rm -rf brian2

EXPOSE 8888
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--no-browser"]
72 changes: 72 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Docker instructions

## Run docker image
To run the docker image, you can use

`docker run -it --init -p 8888:8888 briansimulator/brian`

This will start a JupyterLab instance inside the container, which you can access from your local browser via the last link
printed to the terminal (`http://127.0.0.1:8888/lab?token=…`)

Or if you prefer a simple `bash` terminal rather than JupyterLab:

`docker run -it --init briansimulator/brian /bin/bash`

Or to run the tests:

`docker run -it --init --rm briansimulator/brian python -c 'import brian2; brian2.test(test_standalone="cpp_standalone")'`

## Build docker image
To build the docker image locally, follow the following instructions:

### Build package wheel
You need to first build the package wheel(s) for linux using [`cibuildwheel`](https://cibuildwheel.readthedocs.io). Install it via
`pip install cibuildwheel` (or use `pipx`)

#### Build wheel for local architecture
Run `cibuildwheel` to build a package for your architecture:
```
export CIBW_BUILD='cp312-manylinux*'
cibuildwheel --platform linux --arch auto64 --output-dir dist
```

#### Build multi-arch wheel
First install `qemu` for cross-compilation, e.g. on Debian/Ubuntu:

`sudo apt install qemu-user-static`

Then, run
```
export CIBW_BUILD='cp312-manylinux*'
cibuildwheel --platform linux --arch auto64,aarch64 --output-dir dist
```

### Build docker image

You can then build the docker image via

`docker build -t briansimulator/brian -f docker/Dockerfile .`

Alternatively, to test multi-architecture builds and push to docker hub, first login:

`docker login`

Create a new builder that uses the docker-container driver (only needed once):
```
docker buildx create \
--name container \
--driver=docker-container \
default
```
Then execute:

```
docker buildx build \
--builder=container \
--push \
--platform linux/amd64,linux/arm64/v8 \
-o type=image \
-t briansimulator/brian \
-f docker/Dockerfile \
.
```
Loading