From db06ad202b5cd87cb19d7d86cbc62f5ba6da744c Mon Sep 17 00:00:00 2001 From: edward-cf Date: Thu, 20 Oct 2022 14:30:11 +0100 Subject: [PATCH 01/32] build: Dockerfile and docker-compose to launch pygenn Run GeNN models from a docker image that launches a jupyter notebook --- .gitignore | 1 + Makefile | 4 ++++ build_steps/.dockerignore | 10 ++++++++++ build_steps/Dockerfile | 24 ++++++++++++++++++++++++ build_steps/docker-compose.yml | 28 ++++++++++++++++++++++++++++ build_steps/entrypoint.sh | 2 ++ pygenn/README.md | 5 +++++ pygenn/notebooks/.gitkeep | 0 8 files changed, 74 insertions(+) create mode 100644 build_steps/.dockerignore create mode 100644 build_steps/Dockerfile create mode 100644 build_steps/docker-compose.yml create mode 100644 build_steps/entrypoint.sh create mode 100644 pygenn/notebooks/.gitkeep diff --git a/.gitignore b/.gitignore index 0995fc81cb..98d63c1393 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ /pygenn.egg-info/ .vscode/ /pygenn/share/ +.idea diff --git a/Makefile b/Makefile index 6047458b34..78c8f30fc6 100644 --- a/Makefile +++ b/Makefile @@ -69,3 +69,7 @@ clean: @# Delete libGeNN @rm -f $(LIBGENN) @rm -f $(BACKEND_LIBS) + +.PHONY docker-build: +docker-build: + @docker build -f ./build_steps/Dockerfile -t pygenn:latest . diff --git a/build_steps/.dockerignore b/build_steps/.dockerignore new file mode 100644 index 0000000000..495b878ad3 --- /dev/null +++ b/build_steps/.dockerignore @@ -0,0 +1,10 @@ +.git +build +dist +docs +doxygenn +lib +obj* +tests +userproject +!userproject/include \ No newline at end of file diff --git a/build_steps/Dockerfile b/build_steps/Dockerfile new file mode 100644 index 0000000000..b430ec270b --- /dev/null +++ b/build_steps/Dockerfile @@ -0,0 +1,24 @@ +FROM nvidia/cuda:11.5.0-devel-ubuntu20.04 + +ARG USERNAME="pygennuser" +ARG PYGENN_HOME="/root" + +RUN apt-get update && \ + apt-get upgrade -y + +RUN apt-get install -yq --no-install-recommends curl vim python3-dev python3-pip + +RUN pip install swig numpy jupyter + +ENV CUDA_PATH=/usr/local/cuda-11.5 +ENV HOME=${PYGENN_HOME} +ENV USERNAME=${USERNAME} + +WORKDIR ${HOME} + +COPY . ${HOME} + +RUN adduser --disabled-password --gecos "" $USERNAME +RUN chown -R ${USERNAME}:${USERNAME} "/root" +RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ +RUN python3 setup.py develop diff --git a/build_steps/docker-compose.yml b/build_steps/docker-compose.yml new file mode 100644 index 0000000000..6538bef983 --- /dev/null +++ b/build_steps/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.4" + +services: + pygenn: + image: pygenn:latest + container_name: pygenn + restart: always + ports: + - 8888:8888 + volumes: + - ../pygenn/notebooks:/root/pygenn/notebooks + networks: + - pygenn + command: /bin/bash /root/build/entrypoint.sh + user: pygennuser:pygennuser + healthcheck: + test: ["CMD", "curl", "-f", "host.docker.internal:8888"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 5m + +volumes: + pygenn_notebooks: + +networks: + pygenn: + driver: bridge diff --git a/build_steps/entrypoint.sh b/build_steps/entrypoint.sh new file mode 100644 index 0000000000..b6dca04fda --- /dev/null +++ b/build_steps/entrypoint.sh @@ -0,0 +1,2 @@ +#!/bin/sh +jupyter notebook --ip 0.0.0.0 --no-browser diff --git a/pygenn/README.md b/pygenn/README.md index 7fb83133b3..e76c834137 100644 --- a/pygenn/README.md +++ b/pygenn/README.md @@ -13,3 +13,8 @@ PyGeNN wraps the C++ GeNN API using SWIG, allowing GeNN to be used either direct - Navigate to the GeNN directory and build GeNN as a dll using ``msbuild genn.sln /t:Build /p:Configuration=Release_DLL`` (if you don't have CUDA installed, building the CUDA backend will fail but it should still build the CPU backend). - Copy the newly built DLLs into pygenn using ``copy /Y lib\genn*Release_DLL.* pygenn\genn_wrapper`` - Build the Python extension with setup tools using ``python setup.py develop`` command + +### Docker + - `make docker-build` (from project root) to build Docker image + - `docker-compose up` (from /buildsteps) to launch the container. This will start a Jupyter notebook that can be accessed at `localhost:8888` with the token printed to screen + - Note that a volume is created so that notebooks created in `pygenn/notebooks` will be persisted \ No newline at end of file diff --git a/pygenn/notebooks/.gitkeep b/pygenn/notebooks/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 From 956621004fcce3587b45165e02ced906f29b3ad5 Mon Sep 17 00:00:00 2001 From: Stevinson Date: Fri, 21 Oct 2022 11:28:06 +0100 Subject: [PATCH 02/32] Add docker run alternative to launch jupyter as opposed to using docker-compose --- Makefile | 4 ++++ build_steps/Dockerfile | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 78c8f30fc6..486ce06dd7 100644 --- a/Makefile +++ b/Makefile @@ -73,3 +73,7 @@ clean: .PHONY docker-build: docker-build: @docker build -f ./build_steps/Dockerfile -t pygenn:latest . + +.PHONY docker-jupyter: +docker-jupyter: + @docker run -p 127.0.0.1:8888:8888/tcp -v '$(CURDIR)'/pygenn/notebooks:/root/pygenn/notebooks pygenn jupyter notebook --ip 0.0.0.0 --no-browser diff --git a/build_steps/Dockerfile b/build_steps/Dockerfile index b430ec270b..854556c58f 100644 --- a/build_steps/Dockerfile +++ b/build_steps/Dockerfile @@ -18,7 +18,9 @@ WORKDIR ${HOME} COPY . ${HOME} -RUN adduser --disabled-password --gecos "" $USERNAME -RUN chown -R ${USERNAME}:${USERNAME} "/root" +RUN adduser --disabled-password --gecos "" $USERNAME && chown -R ${USERNAME}:${USERNAME} "/root" + RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ RUN python3 setup.py develop + +USER $USERNAME From ef24ad8c602e6d8f6dedbc015bb343d0a6fdd0b7 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 09:32:32 +0100 Subject: [PATCH 03/32] remove a few odds and ends --- .gitignore | 1 - Makefile | 4 ---- pygenn/notebooks/.gitkeep | 0 3 files changed, 5 deletions(-) delete mode 100644 pygenn/notebooks/.gitkeep diff --git a/.gitignore b/.gitignore index 98d63c1393..0995fc81cb 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,3 @@ /pygenn.egg-info/ .vscode/ /pygenn/share/ -.idea diff --git a/Makefile b/Makefile index 486ce06dd7..78c8f30fc6 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,3 @@ clean: .PHONY docker-build: docker-build: @docker build -f ./build_steps/Dockerfile -t pygenn:latest . - -.PHONY docker-jupyter: -docker-jupyter: - @docker run -p 127.0.0.1:8888:8888/tcp -v '$(CURDIR)'/pygenn/notebooks:/root/pygenn/notebooks pygenn jupyter notebook --ip 0.0.0.0 --no-browser diff --git a/pygenn/notebooks/.gitkeep b/pygenn/notebooks/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 From a915613a678638d18a5442dadb1e49c09119adb1 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 09:33:16 +0100 Subject: [PATCH 04/32] rename build_steps to docker --- Makefile | 2 +- {build_steps => docker}/.dockerignore | 0 {build_steps => docker}/Dockerfile | 0 {build_steps => docker}/docker-compose.yml | 0 {build_steps => docker}/entrypoint.sh | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename {build_steps => docker}/.dockerignore (100%) rename {build_steps => docker}/Dockerfile (100%) rename {build_steps => docker}/docker-compose.yml (100%) rename {build_steps => docker}/entrypoint.sh (100%) diff --git a/Makefile b/Makefile index 78c8f30fc6..7a7da03fa1 100644 --- a/Makefile +++ b/Makefile @@ -72,4 +72,4 @@ clean: .PHONY docker-build: docker-build: - @docker build -f ./build_steps/Dockerfile -t pygenn:latest . + @docker build -f ./docker/Dockerfile -t pygenn:latest . diff --git a/build_steps/.dockerignore b/docker/.dockerignore similarity index 100% rename from build_steps/.dockerignore rename to docker/.dockerignore diff --git a/build_steps/Dockerfile b/docker/Dockerfile similarity index 100% rename from build_steps/Dockerfile rename to docker/Dockerfile diff --git a/build_steps/docker-compose.yml b/docker/docker-compose.yml similarity index 100% rename from build_steps/docker-compose.yml rename to docker/docker-compose.yml diff --git a/build_steps/entrypoint.sh b/docker/entrypoint.sh similarity index 100% rename from build_steps/entrypoint.sh rename to docker/entrypoint.sh From be32b766474016479476dc489fa8faf56e8ab1d7 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 10:03:50 +0100 Subject: [PATCH 05/32] moved some things around a bit more --- docker/.dockerignore => .dockerignore | 0 Dockerfile | 43 +++++++++++++++++++ .../entrypoint.sh => bin/docker_entrypoint.sh | 0 .../docker-compose.yml => docker-compose.yml | 0 docker/Dockerfile | 26 ----------- 5 files changed, 43 insertions(+), 26 deletions(-) rename docker/.dockerignore => .dockerignore (100%) create mode 100644 Dockerfile rename docker/entrypoint.sh => bin/docker_entrypoint.sh (100%) rename docker/docker-compose.yml => docker-compose.yml (100%) delete mode 100644 docker/Dockerfile diff --git a/docker/.dockerignore b/.dockerignore similarity index 100% rename from docker/.dockerignore rename to .dockerignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..32fe43a11a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +FROM nvidia/cuda:11.5.0-devel-ubuntu20.04 + +# Update APT database and upgrade any outdated packages +RUN apt-get update +#RUN apt-get update && \ +# apt-get upgrade -y + +# Install Python, pip and swig +RUN apt-get install -yq --no-install-recommends python3-dev python3-pip swig + + +# Set CUDA environment variable +ENV CUDA_PATH=/usr/local/cuda-11.5 + +# From username, configure environment variable containing home directory +ENV USERNAME=pygenn +ENV HOME=/home/${USERNAME} + +# Add local bin to path +ENV PATH="${PATH}:${HOME}/.local/bin" + +# Add user non-interactively +RUN adduser --disabled-password --gecos "" $USERNAME + +# Set home directory as current working directory +WORKDIR ${HOME} + +# Switch to user +USER $USERNAME + +# Upgrade pip itself +RUN pip install --upgrade pip + +# Install numpy and jupyter +RUN pip install numpy jupyter + +# Copy GeNN into home directory +COPY . ${HOME} + +# Install PyGeNN +#RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ -j 8 +#RUN python3 setup.py develop + diff --git a/docker/entrypoint.sh b/bin/docker_entrypoint.sh similarity index 100% rename from docker/entrypoint.sh rename to bin/docker_entrypoint.sh diff --git a/docker/docker-compose.yml b/docker-compose.yml similarity index 100% rename from docker/docker-compose.yml rename to docker-compose.yml diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 854556c58f..0000000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM nvidia/cuda:11.5.0-devel-ubuntu20.04 - -ARG USERNAME="pygennuser" -ARG PYGENN_HOME="/root" - -RUN apt-get update && \ - apt-get upgrade -y - -RUN apt-get install -yq --no-install-recommends curl vim python3-dev python3-pip - -RUN pip install swig numpy jupyter - -ENV CUDA_PATH=/usr/local/cuda-11.5 -ENV HOME=${PYGENN_HOME} -ENV USERNAME=${USERNAME} - -WORKDIR ${HOME} - -COPY . ${HOME} - -RUN adduser --disabled-password --gecos "" $USERNAME && chown -R ${USERNAME}:${USERNAME} "/root" - -RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ -RUN python3 setup.py develop - -USER $USERNAME From f730e6b53003112a393e33455d8192f576b8fd9b Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 10:40:55 +0100 Subject: [PATCH 06/32] fixed docker ignore issues, dockerfile now builds non-root --- .dockerignore | 8 +++++--- Dockerfile | 14 +++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.dockerignore b/.dockerignore index 495b878ad3..74ca1971cf 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,10 +1,12 @@ .git build dist -docs -doxygenn +documentation +doxygen lib obj* tests userproject -!userproject/include \ No newline at end of file +!userproject/include +**/*.so +**/*.lib diff --git a/Dockerfile b/Dockerfile index 32fe43a11a..43ce4bf83b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,10 +20,7 @@ ENV HOME=/home/${USERNAME} ENV PATH="${PATH}:${HOME}/.local/bin" # Add user non-interactively -RUN adduser --disabled-password --gecos "" $USERNAME - -# Set home directory as current working directory -WORKDIR ${HOME} +RUN adduser --disabled-password --gecos "" ${USERNAME} # Switch to user USER $USERNAME @@ -35,9 +32,12 @@ RUN pip install --upgrade pip RUN pip install numpy jupyter # Copy GeNN into home directory -COPY . ${HOME} +COPY --chown=${USERNAME}:${USERNAME} . ${HOME} + +# Set GeNN directory as current working directory +WORKDIR ${HOME} # Install PyGeNN -#RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ -j 8 -#RUN python3 setup.py develop +RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ -j 8 +RUN python3 setup.py develop --user From 964c89bf34a9ae8ae20ad4a2641d39486277ed83 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 10:59:35 +0100 Subject: [PATCH 07/32] I think installing pygenn as root makes more sense --- Dockerfile | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index 43ce4bf83b..c876e07720 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,36 +8,29 @@ RUN apt-get update # Install Python, pip and swig RUN apt-get install -yq --no-install-recommends python3-dev python3-pip swig - # Set CUDA environment variable ENV CUDA_PATH=/usr/local/cuda-11.5 -# From username, configure environment variable containing home directory -ENV USERNAME=pygenn -ENV HOME=/home/${USERNAME} - -# Add local bin to path -ENV PATH="${PATH}:${HOME}/.local/bin" - -# Add user non-interactively -RUN adduser --disabled-password --gecos "" ${USERNAME} - -# Switch to user -USER $USERNAME - # Upgrade pip itself RUN pip install --upgrade pip # Install numpy and jupyter RUN pip install numpy jupyter -# Copy GeNN into home directory -COPY --chown=${USERNAME}:${USERNAME} . ${HOME} +# Copy GeNN into /tmp +COPY . /tmp/genn -# Set GeNN directory as current working directory -WORKDIR ${HOME} +# Use this as working directory +WORKDIR /tmp/genn # Install PyGeNN -RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${HOME}/pygenn/genn_wrapper/ -j 8 -RUN python3 setup.py develop --user +RUN make DYNAMIC=1 LIBRARY_DIRECTORY=/tmp/genn/pygenn/genn_wrapper/ -j 8 +RUN python3 setup.py install +RUN python3 setup.py install + +# Add non-elevated user non-interactively +ENV USERNAME=pygenn +RUN adduser --disabled-password --gecos "" ${USERNAME} +# Switch to user +USER ${USERNAME} From 1373ab52b7cc5e6106eea134d29dadd2c8bdec6a Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 11:31:05 +0100 Subject: [PATCH 08/32] renamed and +x'd entry point --- bin/docker-entrypoint.sh | 31 +++++++++++++++++++++++++++++++ bin/docker_entrypoint.sh | 2 -- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100755 bin/docker-entrypoint.sh delete mode 100644 bin/docker_entrypoint.sh diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh new file mode 100755 index 0000000000..617833e141 --- /dev/null +++ b/bin/docker-entrypoint.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Run commands in the Docker container with a particular UID and GID. +# The idea is to run the container like +# docker run -i \ +# -v `pwd`:/work \ +# -e LOCAL_USER_ID=`id -u $USER` \ +# -e LOCAL_GROUP_ID=`id -g $USER` \ +# image-name bash +# where the -e flags pass the env vars to the container, which are read by this script. +# By setting copying this script to the container and setting it to the +# ENTRYPOINT, and subsequent commands run in the container will run as the user +# who ran `docker` on the host, and so any output files will have the correct +# permissions. + +USER_ID=${LOCAL_USER_ID:-9001} +GROUP_ID=${LOCAL_GROUP_ID:-$USER_ID} + +echo "Starting with UID : $USER_ID, GID: $GROUP_ID" +groupadd -g $GROUP_ID thegroup +useradd --shell /bin/bash -u $USER_ID -g thegroup -o -c "" -m user +export HOME=/home/user + + +if [[ "$1" = "interactive" ]]; then + shift + exec gosu user:thegroup python3 "$@" +elif [[ "$2" = "notebook" ]]; then + exec gosu user:group "jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser" +else + exec gosu user:thegroup "$@" +fi diff --git a/bin/docker_entrypoint.sh b/bin/docker_entrypoint.sh deleted file mode 100644 index b6dca04fda..0000000000 --- a/bin/docker_entrypoint.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -jupyter notebook --ip 0.0.0.0 --no-browser From 09e0e3a2be5ff70aca8d751e574a08fe8c629c0e Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 12:34:16 +0100 Subject: [PATCH 09/32] use gosu to switch user so dockerfile should remain elevated --- Dockerfile | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index c876e07720..3c33ebf763 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,31 +6,29 @@ RUN apt-get update # apt-get upgrade -y # Install Python, pip and swig -RUN apt-get install -yq --no-install-recommends python3-dev python3-pip swig +RUN apt-get install -yq --no-install-recommends python3-dev python3-pip swig gosu nano # Set CUDA environment variable ENV CUDA_PATH=/usr/local/cuda-11.5 +ENV GENN_PATH=/opt/genn + # Upgrade pip itself RUN pip install --upgrade pip # Install numpy and jupyter -RUN pip install numpy jupyter +RUN pip install numpy jupyter matplotlib -# Copy GeNN into /tmp -COPY . /tmp/genn +# Copy GeNN into /opt +COPY . ${GENN_PATH} # Use this as working directory -WORKDIR /tmp/genn +WORKDIR ${GENN_PATH} # Install PyGeNN -RUN make DYNAMIC=1 LIBRARY_DIRECTORY=/tmp/genn/pygenn/genn_wrapper/ -j 8 -RUN python3 setup.py install -RUN python3 setup.py install - -# Add non-elevated user non-interactively -ENV USERNAME=pygenn -RUN adduser --disabled-password --gecos "" ${USERNAME} +RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${GENN_PATH}/pygenn/genn_wrapper/ -j 8 +RUN python3 setup.py develop -# Switch to user -USER ${USERNAME} +# Start entrypoint +# **NOTE** in 'exec' mode shell arguments aren't expanded so can't use environment variables +ENTRYPOINT ["/opt/genn/bin/docker-entrypoint.sh"] From 0a3c97b3ae0d1cfca8439df12472529895276b23 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 14:16:10 +0100 Subject: [PATCH 10/32] more entrypoint fiddling --- bin/docker-entrypoint.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index 617833e141..163b17b6c6 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -15,17 +15,19 @@ USER_ID=${LOCAL_USER_ID:-9001} GROUP_ID=${LOCAL_GROUP_ID:-$USER_ID} -echo "Starting with UID : $USER_ID, GID: $GROUP_ID" -groupadd -g $GROUP_ID thegroup -useradd --shell /bin/bash -u $USER_ID -g thegroup -o -c "" -m user -export HOME=/home/user - +# Add PyGeNN user with matching user and group ID +groupadd -g $GROUP_ID pygenn +useradd --shell /bin/bash -u $USER_ID -g pygenn -o -c "" -m pygenn +export HOME=/home/pygenn +# If interactive command passed, pass remainder of arguments to python interpreter if [[ "$1" = "interactive" ]]; then shift - exec gosu user:thegroup python3 "$@" -elif [[ "$2" = "notebook" ]]; then - exec gosu user:group "jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser" + exec gosu pygenn:pygenn python3 "$@" +# Otherwise, if notebook is passes, launch notebook +elif [[ "$1" = "notebook" ]]; then + exec gosu pygenn:pygenn /usr/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser +# Otherwise, execute arguments else - exec gosu user:thegroup "$@" + exec gosu pygenn:pygenn "$@" fi From 2090712d3440238eb964c15e0049f7a15ebf949b Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 15:06:26 +0100 Subject: [PATCH 11/32] automatically figure out suitable number of cores for make --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3c33ebf763..392a4416f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ COPY . ${GENN_PATH} WORKDIR ${GENN_PATH} # Install PyGeNN -RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${GENN_PATH}/pygenn/genn_wrapper/ -j 8 +RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${GENN_PATH}/pygenn/genn_wrapper/ -j `lscpu -p | egrep -v '^#' | sort -u -t, -k 2,4 | wc -l` RUN python3 setup.py develop # Start entrypoint From e03f48fcb41fc2509b0fcaaa80d5ef92e183c90b Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 15:06:53 +0100 Subject: [PATCH 12/32] fixed typo in entrypoint --- bin/docker-entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index 163b17b6c6..670573f48b 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -26,7 +26,7 @@ if [[ "$1" = "interactive" ]]; then exec gosu pygenn:pygenn python3 "$@" # Otherwise, if notebook is passes, launch notebook elif [[ "$1" = "notebook" ]]; then - exec gosu pygenn:pygenn /usr/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser + exec gosu pygenn:pygenn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser # Otherwise, execute arguments else exec gosu pygenn:pygenn "$@" From 16fbdfdf7b473840a765824782cdc87c5b51c562 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 15:07:44 +0100 Subject: [PATCH 13/32] removed docker compose - too many limitations --- docker-compose.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 6538bef983..0000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: "3.4" - -services: - pygenn: - image: pygenn:latest - container_name: pygenn - restart: always - ports: - - 8888:8888 - volumes: - - ../pygenn/notebooks:/root/pygenn/notebooks - networks: - - pygenn - command: /bin/bash /root/build/entrypoint.sh - user: pygennuser:pygennuser - healthcheck: - test: ["CMD", "curl", "-f", "host.docker.internal:8888"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 5m - -volumes: - pygenn_notebooks: - -networks: - pygenn: - driver: bridge From da2b4c0e3a7f4ae6027b639db2052b25b143ed52 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 17:16:28 +0100 Subject: [PATCH 14/32] ben's suggestions to renmae interactive and add a default CMD --- Dockerfile | 8 +++++--- bin/docker-entrypoint.sh | 11 ++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 392a4416f0..5f2048c20c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,8 @@ FROM nvidia/cuda:11.5.0-devel-ubuntu20.04 # Update APT database and upgrade any outdated packages -RUN apt-get update -#RUN apt-get update && \ -# apt-get upgrade -y +RUN apt-get update && \ + apt-get upgrade -y # Install Python, pip and swig RUN apt-get install -yq --no-install-recommends python3-dev python3-pip swig gosu nano @@ -29,6 +28,9 @@ WORKDIR ${GENN_PATH} RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${GENN_PATH}/pygenn/genn_wrapper/ -j `lscpu -p | egrep -v '^#' | sort -u -t, -k 2,4 | wc -l` RUN python3 setup.py develop +# Default command will be to launch bash +CMD ["/bin/bash"] + # Start entrypoint # **NOTE** in 'exec' mode shell arguments aren't expanded so can't use environment variables ENTRYPOINT ["/opt/genn/bin/docker-entrypoint.sh"] diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index 670573f48b..35933ba9e2 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -20,10 +20,15 @@ groupadd -g $GROUP_ID pygenn useradd --shell /bin/bash -u $USER_ID -g pygenn -o -c "" -m pygenn export HOME=/home/pygenn -# If interactive command passed, pass remainder of arguments to python interpreter -if [[ "$1" = "interactive" ]]; then +# If script command passed +if [[ "$1" = "script" ]]; then + # Shift script command itself off arguments shift - exec gosu pygenn:pygenn python3 "$@" + + # Change to directory script is in and launch + # **YUCK** this should not really be necessary but PyGeNN does + # not work nicely running scripts not in working directory + exec gosu pygenn:pygenn /bin/bash -c 'cd `dirname "'$2'"` && python3 "'$@'"' # Otherwise, if notebook is passes, launch notebook elif [[ "$1" = "notebook" ]]; then exec gosu pygenn:pygenn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser From 314c12d75fc5610101b4dd1d5ea4008aa591b0e9 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Tue, 25 Oct 2022 18:00:15 +0100 Subject: [PATCH 15/32] working script entrypoint but still needs more thought --- bin/docker-entrypoint.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index 35933ba9e2..c2e4c115ee 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -28,7 +28,9 @@ if [[ "$1" = "script" ]]; then # Change to directory script is in and launch # **YUCK** this should not really be necessary but PyGeNN does # not work nicely running scripts not in working directory - exec gosu pygenn:pygenn /bin/bash -c 'cd `dirname "'$2'"` && python3 "'$@'"' + CWD=$(dirname "$1") + CMD="cd $CWD && python3 \"$@\"" + exec gosu pygenn:pygenn /bin/bash -c "$CMD" # Otherwise, if notebook is passes, launch notebook elif [[ "$1" = "notebook" ]]; then exec gosu pygenn:pygenn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser From c42e6078739712cdffe3979ecb4296d6fbc849fe Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 09:28:20 +0100 Subject: [PATCH 16/32] added label and adjustable base image to docker file and tidied and renamed entrypoint --- Dockerfile | 11 +++++++++-- ...docker-entrypoint.sh => genn-docker-entrypoint.sh} | 3 +-- 2 files changed, 10 insertions(+), 4 deletions(-) rename bin/{docker-entrypoint.sh => genn-docker-entrypoint.sh} (94%) diff --git a/Dockerfile b/Dockerfile index 5f2048c20c..37556f39b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,11 @@ -FROM nvidia/cuda:11.5.0-devel-ubuntu20.04 +ARG BASE=11.5.0-devel-ubuntu20.04 +FROM nvidia/cuda:${BASE} + +LABEL maintainer="J.C.Knight@sussex.ac.uk" +LABEL version="4.8.0" +LABEL org.opencontainers.image.documentation="https://genn-team.github.io/" +LABEL org.opencontainers.image.source="https://github.com/genn-team/genn" +LABEL org.opencontainers.image.title="PyGeNN Docker image" # Update APT database and upgrade any outdated packages RUN apt-get update && \ @@ -33,4 +40,4 @@ CMD ["/bin/bash"] # Start entrypoint # **NOTE** in 'exec' mode shell arguments aren't expanded so can't use environment variables -ENTRYPOINT ["/opt/genn/bin/docker-entrypoint.sh"] +ENTRYPOINT ["/opt/genn/bin/genn-docker-entrypoint.sh"] diff --git a/bin/docker-entrypoint.sh b/bin/genn-docker-entrypoint.sh similarity index 94% rename from bin/docker-entrypoint.sh rename to bin/genn-docker-entrypoint.sh index c2e4c115ee..7f6b469766 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/genn-docker-entrypoint.sh @@ -29,8 +29,7 @@ if [[ "$1" = "script" ]]; then # **YUCK** this should not really be necessary but PyGeNN does # not work nicely running scripts not in working directory CWD=$(dirname "$1") - CMD="cd $CWD && python3 \"$@\"" - exec gosu pygenn:pygenn /bin/bash -c "$CMD" + exec gosu pygenn:pygenn /bin/bash -c "cd \"$CWD\" && python3 \"$@\"" # Otherwise, if notebook is passes, launch notebook elif [[ "$1" = "notebook" ]]; then exec gosu pygenn:pygenn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser From 38c652ec8024ab57aac46fb502c7f065ca0b0f7e Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 09:39:32 +0100 Subject: [PATCH 17/32] also do system-level C++ installation of GenN --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 37556f39b5..e8e62f3563 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,7 +31,8 @@ COPY . ${GENN_PATH} # Use this as working directory WORKDIR ${GENN_PATH} -# Install PyGeNN +# Install GeNN and PyGeNN +RUN make install -j `lscpu -p | egrep -v '^#' | sort -u -t, -k 2,4 | wc -l` RUN make DYNAMIC=1 LIBRARY_DIRECTORY=${GENN_PATH}/pygenn/genn_wrapper/ -j `lscpu -p | egrep -v '^#' | sort -u -t, -k 2,4 | wc -l` RUN python3 setup.py develop From 3be2fa13d5efc4299e72ce6dc9232b425528be6a Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 10:33:32 +0100 Subject: [PATCH 18/32] renamed from PyGeNN->GeNN --- Dockerfile | 2 +- Makefile | 2 +- pygenn/README.md | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index e8e62f3563..96953c017d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ LABEL maintainer="J.C.Knight@sussex.ac.uk" LABEL version="4.8.0" LABEL org.opencontainers.image.documentation="https://genn-team.github.io/" LABEL org.opencontainers.image.source="https://github.com/genn-team/genn" -LABEL org.opencontainers.image.title="PyGeNN Docker image" +LABEL org.opencontainers.image.title="GeNN Docker image" # Update APT database and upgrade any outdated packages RUN apt-get update && \ diff --git a/Makefile b/Makefile index 7a7da03fa1..b787652621 100644 --- a/Makefile +++ b/Makefile @@ -72,4 +72,4 @@ clean: .PHONY docker-build: docker-build: - @docker build -f ./docker/Dockerfile -t pygenn:latest . + @docker build -t genn:latest . diff --git a/pygenn/README.md b/pygenn/README.md index e76c834137..7fb83133b3 100644 --- a/pygenn/README.md +++ b/pygenn/README.md @@ -13,8 +13,3 @@ PyGeNN wraps the C++ GeNN API using SWIG, allowing GeNN to be used either direct - Navigate to the GeNN directory and build GeNN as a dll using ``msbuild genn.sln /t:Build /p:Configuration=Release_DLL`` (if you don't have CUDA installed, building the CUDA backend will fail but it should still build the CPU backend). - Copy the newly built DLLs into pygenn using ``copy /Y lib\genn*Release_DLL.* pygenn\genn_wrapper`` - Build the Python extension with setup tools using ``python setup.py develop`` command - -### Docker - - `make docker-build` (from project root) to build Docker image - - `docker-compose up` (from /buildsteps) to launch the container. This will start a Jupyter notebook that can be accessed at `localhost:8888` with the token printed to screen - - Note that a volume is created so that notebooks created in `pygenn/notebooks` will be persisted \ No newline at end of file From 14e82ce4e00a3092270314854cd5a1403d25812b Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 11:15:46 +0100 Subject: [PATCH 19/32] renamed user to genn as well --- bin/genn-docker-entrypoint.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/genn-docker-entrypoint.sh b/bin/genn-docker-entrypoint.sh index 7f6b469766..e72b1d2dba 100755 --- a/bin/genn-docker-entrypoint.sh +++ b/bin/genn-docker-entrypoint.sh @@ -15,10 +15,10 @@ USER_ID=${LOCAL_USER_ID:-9001} GROUP_ID=${LOCAL_GROUP_ID:-$USER_ID} -# Add PyGeNN user with matching user and group ID -groupadd -g $GROUP_ID pygenn -useradd --shell /bin/bash -u $USER_ID -g pygenn -o -c "" -m pygenn -export HOME=/home/pygenn +# Add GeNN user with matching user and group ID +groupadd -g $GROUP_ID genn +useradd --shell /bin/bash -u $USER_ID -g genn -o -c "" -m genn +export HOME=/home/genn # If script command passed if [[ "$1" = "script" ]]; then @@ -29,11 +29,11 @@ if [[ "$1" = "script" ]]; then # **YUCK** this should not really be necessary but PyGeNN does # not work nicely running scripts not in working directory CWD=$(dirname "$1") - exec gosu pygenn:pygenn /bin/bash -c "cd \"$CWD\" && python3 \"$@\"" + exec gosu genn:genn /bin/bash -c "cd \"$CWD\" && python3 \"$@\"" # Otherwise, if notebook is passes, launch notebook elif [[ "$1" = "notebook" ]]; then - exec gosu pygenn:pygenn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser + exec gosu genn:genn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser # Otherwise, execute arguments else - exec gosu pygenn:pygenn "$@" + exec gosu genn:genn "$@" fi From 4915ab0d280dcfa64c72e5b9d41209092b7ccd1d Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 15:42:21 +0100 Subject: [PATCH 20/32] sensible, writable starting directory for ipython --- bin/genn-docker-entrypoint.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bin/genn-docker-entrypoint.sh b/bin/genn-docker-entrypoint.sh index e72b1d2dba..ef770b0b53 100755 --- a/bin/genn-docker-entrypoint.sh +++ b/bin/genn-docker-entrypoint.sh @@ -30,9 +30,11 @@ if [[ "$1" = "script" ]]; then # not work nicely running scripts not in working directory CWD=$(dirname "$1") exec gosu genn:genn /bin/bash -c "cd \"$CWD\" && python3 \"$@\"" -# Otherwise, if notebook is passes, launch notebook +# Otherwise, if notebook is passes elif [[ "$1" = "notebook" ]]; then - exec gosu genn:genn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser + # Extract working directory from next command line argument, otherwise use home + CWD=${2:-$HOME} + exec gosu genn:genn /bin/bash -c "/usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser --notebook-dir=\"$CWD\"" # Otherwise, execute arguments else exec gosu genn:genn "$@" From d46ea77da718922c5ae170eb95d5baadc6c29e9c Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 17:09:49 +0100 Subject: [PATCH 21/32] no need for bash wrapper to jupyter-notebook --- bin/genn-docker-entrypoint.sh | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/bin/genn-docker-entrypoint.sh b/bin/genn-docker-entrypoint.sh index ef770b0b53..11db87df9d 100755 --- a/bin/genn-docker-entrypoint.sh +++ b/bin/genn-docker-entrypoint.sh @@ -1,17 +1,5 @@ #!/bin/bash -# Run commands in the Docker container with a particular UID and GID. -# The idea is to run the container like -# docker run -i \ -# -v `pwd`:/work \ -# -e LOCAL_USER_ID=`id -u $USER` \ -# -e LOCAL_GROUP_ID=`id -g $USER` \ -# image-name bash -# where the -e flags pass the env vars to the container, which are read by this script. -# By setting copying this script to the container and setting it to the -# ENTRYPOINT, and subsequent commands run in the container will run as the user -# who ran `docker` on the host, and so any output files will have the correct -# permissions. - +# Read desired user and group ID from environment varibles (typically set on docker command line with -e) USER_ID=${LOCAL_USER_ID:-9001} GROUP_ID=${LOCAL_GROUP_ID:-$USER_ID} @@ -34,7 +22,7 @@ if [[ "$1" = "script" ]]; then elif [[ "$1" = "notebook" ]]; then # Extract working directory from next command line argument, otherwise use home CWD=${2:-$HOME} - exec gosu genn:genn /bin/bash -c "/usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser --notebook-dir=\"$CWD\"" + exec gosu genn:genn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser --notebook-dir="$CWD" # Otherwise, execute arguments else exec gosu genn:genn "$@" From 7a7ced7b685450bce55395d769757b5c7003bb8f Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 17:09:54 +0100 Subject: [PATCH 22/32] docker readme --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ef059644fa..6904c81273 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@ GeNN is a GPU-enhanced Neuronal Network simulation environment based on code gen ## Installation -You can download GeNN either as a zip file of a stable release or a -snapshot of the most recent stable version or the unstable development -version using the Git version control system. +You can download GeNN either as a zip file of a stable release, checkout the development +version using the Git version control system or use our Docker image. ### Downloading a release Point your browser to https://github.com/genn-team/genn/releases @@ -102,6 +101,51 @@ environment already set up by navigating to Start - All Programs - Microsoft Visual Studio - Visual Studio Tools - x64 Native Tools Command Prompt. You may also wish to create a shortcut for this tool on the desktop, for convenience. +### Docker +We have also developed an Ubuntu-based docker container with GeNN pre-installed. +You can build this yourself or download it from Dockerhub + +### Building the container +The following command can be used from the GeNN source directory to build the GeNN container: + +```bash +make docker-build +``` + +### Running Jupyter Notebooks +A Jupyter Notebook environment running in the container can be launched using the ``notebook'' command: + +```bash +docker run -p 8080:8080 --gpus=all gennteam/genn:latest notebook +``` +The ``-p`` option 'publishes' port 8080 allowing the notebook server to be accessed on the host. + +### Running PyGeNN scripts +Assuming they have no additional dependencies, Python scripts using PyGeNN can be run directly using the container with the ``script`` command: + +```bash +docker run --gpus=all -v .:/home gennteam/genn:latest script /home/test.py +``` +Typically, this script will be in a volume mounted into the container. Here the current directory on the host is mounted as ``/home`` inside the container. +In order for this command to work correctly, you typically need to use the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables described below to give the container correct permissions. + +### Interactive mode +If you want to use the GeNN C++ tools or install some additional packages you can also launch your own executable in the GeNN container. +For examples you could run an interactive dash shell with: +```bash +docker run -it --gpus=all gennteam/genn:latest /bin/sh +``` +If the last argument is omitted, the default is to launch a bash shell. + +### Accessing your files +All of the above options are performed using a non-elevated 'genn' user inside the container. +This user won't necessarily have the correct permissions to access files in volumes mounted into the container and files they write may also not have correct permissions. +However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables like: +```bash +docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` gennteam/genn:latest +``` +the 'genn' user will be created with the same UID and GID as your local user user, meaning that output files will have correct permissions. + ## Usage ### Sample projects From 3d58108392d31b8755bafe400eb2751269b69bb9 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 17:14:39 +0100 Subject: [PATCH 23/32] readme tweaks --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6904c81273..c7c54f33dd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ GeNN is a GPU-enhanced Neuronal Network simulation environment based on code gen ## Installation You can download GeNN either as a zip file of a stable release, checkout the development -version using the Git version control system or use our Docker image. +version using the Git version control system or use our Docker container. ### Downloading a release Point your browser to https://github.com/genn-team/genn/releases @@ -102,7 +102,7 @@ Microsoft Visual Studio - Visual Studio Tools - x64 Native Tools Command Prompt. create a shortcut for this tool on the desktop, for convenience. ### Docker -We have also developed an Ubuntu-based docker container with GeNN pre-installed. +You can also use GeNN by using our CUDA-enabled docker container which comes with GeNN pre-installed. You can build this yourself or download it from Dockerhub ### Building the container @@ -126,11 +126,11 @@ Assuming they have no additional dependencies, Python scripts using PyGeNN can b ```bash docker run --gpus=all -v .:/home gennteam/genn:latest script /home/test.py ``` -Typically, this script will be in a volume mounted into the container. Here the current directory on the host is mounted as ``/home`` inside the container. +Typically, such scripts will be in a volume mounted into the container. Here the current directory on the host is mounted as ``/home`` inside the container. In order for this command to work correctly, you typically need to use the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables described below to give the container correct permissions. ### Interactive mode -If you want to use the GeNN C++ tools or install some additional packages you can also launch your own executable in the GeNN container. +If you want to use the GeNN C++ tools, install some additional packages etc you can also launch your own executable with the GeNN container. For examples you could run an interactive dash shell with: ```bash docker run -it --gpus=all gennteam/genn:latest /bin/sh @@ -138,13 +138,13 @@ docker run -it --gpus=all gennteam/genn:latest /bin/sh If the last argument is omitted, the default is to launch a bash shell. ### Accessing your files -All of the above options are performed using a non-elevated 'genn' user inside the container. -This user won't necessarily have the correct permissions to access files in volumes mounted into the container and files they write may also not have correct permissions. -However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables like: +All of the above options are performed using a non-elevated user called 'genn' created inside the container. +By default, this user probably won't have the correct permissions to access files in volumes mounted into the container and files they write will also not have correct permissions. +However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container: ```bash docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` gennteam/genn:latest ``` -the 'genn' user will be created with the same UID and GID as your local user user, meaning that output files will have correct permissions. +the 'genn' user will be created with the same UID and GID as your local user, meaning that output files will have correct permissions. ## Usage From 40c2ee99b4ccb3a5c7eba19f905c9b2228722f5a Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 17:17:52 +0100 Subject: [PATCH 24/32] more readme --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c7c54f33dd..4ce735d90a 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,8 @@ Microsoft Visual Studio - Visual Studio Tools - x64 Native Tools Command Prompt. create a shortcut for this tool on the desktop, for convenience. ### Docker -You can also use GeNN by using our CUDA-enabled docker container which comes with GeNN pre-installed. -You can build this yourself or download it from Dockerhub +You can also use GeNN through our CUDA-enabled docker container which comes with GeNN pre-installed. +You can build this container yourself or download it from Dockerhub ### Building the container The following command can be used from the GeNN source directory to build the GeNN container: @@ -112,6 +112,8 @@ The following command can be used from the GeNN source directory to build the Ge make docker-build ``` +This builds a container tagged as ``genn:latest`` so, to use this container rather than downloading the prebuild one from dockerhub, just replace ``gennteam/genn:latest`` with ``genn:latest`` in the following instructions. + ### Running Jupyter Notebooks A Jupyter Notebook environment running in the container can be launched using the ``notebook'' command: From 1de18c5b2af11020a5db6ae9e3fac67924b7dee1 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 17:21:33 +0100 Subject: [PATCH 25/32] more more readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4ce735d90a..ff529e4971 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ make docker-build This builds a container tagged as ``genn:latest`` so, to use this container rather than downloading the prebuild one from dockerhub, just replace ``gennteam/genn:latest`` with ``genn:latest`` in the following instructions. ### Running Jupyter Notebooks -A Jupyter Notebook environment running in the container can be launched using the ``notebook'' command: +A Jupyter Notebook environment running in the container can be launched using the ``notebook`` command: ```bash docker run -p 8080:8080 --gpus=all gennteam/genn:latest notebook @@ -128,11 +128,11 @@ Assuming they have no additional dependencies, Python scripts using PyGeNN can b ```bash docker run --gpus=all -v .:/home gennteam/genn:latest script /home/test.py ``` -Typically, such scripts will be in a volume mounted into the container. Here the current directory on the host is mounted as ``/home`` inside the container. +Typically, such scripts will be in a volume mounted into the container and, here the current directory on the host is mounted into ``/home`` in the container. In order for this command to work correctly, you typically need to use the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables described below to give the container correct permissions. ### Interactive mode -If you want to use the GeNN C++ tools, install some additional packages etc you can also launch your own executable with the GeNN container. +If you want to use the GeNN C++ tools or install some additional packages etc you can also launch your own executable from the GeNN container. For examples you could run an interactive dash shell with: ```bash docker run -it --gpus=all gennteam/genn:latest /bin/sh @@ -141,7 +141,7 @@ If the last argument is omitted, the default is to launch a bash shell. ### Accessing your files All of the above options are performed using a non-elevated user called 'genn' created inside the container. -By default, this user probably won't have the correct permissions to access files in volumes mounted into the container and files they write will also not have correct permissions. +By default, this user probably won't have the correct permissions to create files in volumes mounted into the container. However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container: ```bash docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` gennteam/genn:latest From d67347e44aca2c3c80612d9bac70ae4e322682aa Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Wed, 26 Oct 2022 17:23:31 +0100 Subject: [PATCH 26/32] more more more readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff529e4971..2e8d394501 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Assuming they have no additional dependencies, Python scripts using PyGeNN can b ```bash docker run --gpus=all -v .:/home gennteam/genn:latest script /home/test.py ``` -Typically, such scripts will be in a volume mounted into the container and, here the current directory on the host is mounted into ``/home`` in the container. +Typically, such scripts will be located in a volume mounted into the container. For example, here, ``test.py`` is in the current directory on the host which is mounted into ``/home`` in the container. In order for this command to work correctly, you typically need to use the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables described below to give the container correct permissions. ### Interactive mode From 62cfb7e131346d6e8b3735733ba3df27331993e7 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Thu, 27 Oct 2022 09:52:32 +0100 Subject: [PATCH 27/32] yet another go at the readme --- README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 2e8d394501..8d5611c979 100644 --- a/README.md +++ b/README.md @@ -114,39 +114,39 @@ make docker-build This builds a container tagged as ``genn:latest`` so, to use this container rather than downloading the prebuild one from dockerhub, just replace ``gennteam/genn:latest`` with ``genn:latest`` in the following instructions. -### Running Jupyter Notebooks -A Jupyter Notebook environment running in the container can be launched using the ``notebook`` command: - +### Interactive mode +If you want to use GeNN or PyGeNN interactively you can launch a bash shell in the GeNN container using the following command: ```bash -docker run -p 8080:8080 --gpus=all gennteam/genn:latest notebook +docker run -it --gpus=all gennteam/genn:latest ``` -The ``-p`` option 'publishes' port 8080 allowing the notebook server to be accessed on the host. +You can also provide a final argument to launch a different executable e.g. ``/bin/sh`` to launch a dash shell. -### Running PyGeNN scripts -Assuming they have no additional dependencies, Python scripts using PyGeNN can be run directly using the container with the ``script`` command: +### Accessing your files +Internally, all of the commands provided by the GeNN container operate using a non-elevated, internal user called 'genn'. +By default, this user won't necessarily have the correct permissions to create files in volumes mounted into the container. +However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container like: +```bash +docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` gennteam/genn:latest +``` +the 'genn' user will be created with the same UID and GID as your local user, meaning that they will have the same permissions. Typically you would combine this with the ``-v`` option to mount a directory owned by your local user into the container. For example: ```bash -docker run --gpus=all -v .:/home gennteam/genn:latest script /home/test.py +docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest ``` -Typically, such scripts will be located in a volume mounted into the container. For example, here, ``test.py`` is in the current directory on the host which is mounted into ``/home`` in the container. -In order for this command to work correctly, you typically need to use the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables described below to give the container correct permissions. +mounts the local users home directory into ``/home`` within the container. -### Interactive mode -If you want to use the GeNN C++ tools or install some additional packages etc you can also launch your own executable from the GeNN container. -For examples you could run an interactive dash shell with: +### Running Jupyter Notebooks +A Jupyter Notebook environment running in the container can be launched using the ``notebook`` command. Typically, you would combine this with the ``-p 8080:8080`` option to 'publish' port 8080, allowing the notebook server to be accessed on the host. By default, notebooks are created in the home directory of the 'genn' user inside the container. However, to create notebooks which persist beyond the lifetime of the container, the notebook command needs to be combined with the options discussed previously. For example: ```bash -docker run -it --gpus=all gennteam/genn:latest /bin/sh +docker run --gpus=all -p 8080:8080 -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest notebook /home ``` -If the last argument is omitted, the default is to launch a bash shell. +will create notebooks in the current users home directory. -### Accessing your files -All of the above options are performed using a non-elevated user called 'genn' created inside the container. -By default, this user probably won't have the correct permissions to create files in volumes mounted into the container. -However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container: +### Running PyGeNN scripts +Assuming they have no additional dependencies, Python scripts using PyGeNN can be run directly using the container with the ``script`` command. As scripts are likely to be located outside of the container, the script command is often combined with the options discussed previously. For example, to run a script called ``test.py`` in your home directory, the script command could be invoked with: ```bash -docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` gennteam/genn:latest +docker run --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest script /home/test.py ``` -the 'genn' user will be created with the same UID and GID as your local user, meaning that output files will have correct permissions. ## Usage From 6f96b0e4f55be150868052b49a907b2bf3ce9a4c Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Thu, 27 Oct 2022 09:56:04 +0100 Subject: [PATCH 28/32] installation --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d5611c979..8c6650e366 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,8 @@ create a shortcut for this tool on the desktop, for convenience. ### Docker You can also use GeNN through our CUDA-enabled docker container which comes with GeNN pre-installed. -You can build this container yourself or download it from Dockerhub +To work with such CUDA-enabled containers, you need to first install CUDA on your host system as described above and then install docker and the NVIDIA Container Toolkit as described in https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker. +You can then build the GeNN container yourself or download it from Dockerhub ### Building the container The following command can be used from the GeNN source directory to build the GeNN container: From 741c10af31f35b8c074c63343276a7b71db76119 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Thu, 27 Oct 2022 10:01:47 +0100 Subject: [PATCH 29/32] another tweak --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8c6650e366..258e4a79ad 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ create a shortcut for this tool on the desktop, for convenience. ### Docker You can also use GeNN through our CUDA-enabled docker container which comes with GeNN pre-installed. To work with such CUDA-enabled containers, you need to first install CUDA on your host system as described above and then install docker and the NVIDIA Container Toolkit as described in https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker. -You can then build the GeNN container yourself or download it from Dockerhub +You can then build the GeNN container yourself or download it from Dockerhub. ### Building the container The following command can be used from the GeNN source directory to build the GeNN container: @@ -116,25 +116,25 @@ make docker-build This builds a container tagged as ``genn:latest`` so, to use this container rather than downloading the prebuild one from dockerhub, just replace ``gennteam/genn:latest`` with ``genn:latest`` in the following instructions. ### Interactive mode -If you want to use GeNN or PyGeNN interactively you can launch a bash shell in the GeNN container using the following command: +If you wish to use GeNN or PyGeNN interactively, you can launch a bash shell in the GeNN container using the following command: ```bash docker run -it --gpus=all gennteam/genn:latest ``` You can also provide a final argument to launch a different executable e.g. ``/bin/sh`` to launch a dash shell. ### Accessing your files -Internally, all of the commands provided by the GeNN container operate using a non-elevated, internal user called 'genn'. -By default, this user won't necessarily have the correct permissions to create files in volumes mounted into the container. -However, by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container like: +When using the GeNN container you often want to access files on your host system. +This can be easily configured using the ``-v`` option to mount a local directory into the container. For example: ```bash -docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` gennteam/genn:latest +docker run -it --gpus=all -v $HOME:/home gennteam/genn:latest ``` -the 'genn' user will be created with the same UID and GID as your local user, meaning that they will have the same permissions. Typically you would combine this with the ``-v`` option to mount a directory owned by your local user into the container. For example: - +mounts the local users home directory into ``/home`` within the container. +However, all of the commands provided by the GeNN container operate using a non-elevated, internal user called 'genn' who, by default, won't have the correct permissions to create files in volumes mounted into the container. +This can be resolved by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container like: ```bash docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest ``` -mounts the local users home directory into ``/home`` within the container. +which will create the 'genn' with the same UID and GID as your local user, meaning that they will have the same permissions to access the files mountd into ``/home``. ### Running Jupyter Notebooks A Jupyter Notebook environment running in the container can be launched using the ``notebook`` command. Typically, you would combine this with the ``-p 8080:8080`` option to 'publish' port 8080, allowing the notebook server to be accessed on the host. By default, notebooks are created in the home directory of the 'genn' user inside the container. However, to create notebooks which persist beyond the lifetime of the container, the notebook command needs to be combined with the options discussed previously. For example: @@ -144,7 +144,7 @@ docker run --gpus=all -p 8080:8080 -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP will create notebooks in the current users home directory. ### Running PyGeNN scripts -Assuming they have no additional dependencies, Python scripts using PyGeNN can be run directly using the container with the ``script`` command. As scripts are likely to be located outside of the container, the script command is often combined with the options discussed previously. For example, to run a script called ``test.py`` in your home directory, the script command could be invoked with: +Assuming they have no additional dependencies, PyGeNN scripts can be run directly using the container with the ``script`` command. As scripts are likely to be located outside of the container, the script command is often combined with the options discussed previously. For example, to run a script called ``test.py`` in your home directory, the script command could be invoked with: ```bash docker run --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest script /home/test.py ``` From d077c8c0a349c0399635436d734d3cdc73717621 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Thu, 27 Oct 2022 10:03:46 +0100 Subject: [PATCH 30/32] typos --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 258e4a79ad..45d28e9480 100644 --- a/README.md +++ b/README.md @@ -124,17 +124,17 @@ You can also provide a final argument to launch a different executable e.g. ``/b ### Accessing your files When using the GeNN container you often want to access files on your host system. -This can be easily configured using the ``-v`` option to mount a local directory into the container. For example: +This can be easily achieved by using the ``-v`` option to mount a local directory into the container. For example: ```bash docker run -it --gpus=all -v $HOME:/home gennteam/genn:latest ``` -mounts the local users home directory into ``/home`` within the container. +mounts the local user's home directory into ``/home`` within the container. However, all of the commands provided by the GeNN container operate using a non-elevated, internal user called 'genn' who, by default, won't have the correct permissions to create files in volumes mounted into the container. This can be resolved by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container like: ```bash docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest ``` -which will create the 'genn' with the same UID and GID as your local user, meaning that they will have the same permissions to access the files mountd into ``/home``. +which will ensure that that 'genn' user has the same UID and GID as the local user, meaning that they will have the same permissions to access the files mountd into ``/home``. ### Running Jupyter Notebooks A Jupyter Notebook environment running in the container can be launched using the ``notebook`` command. Typically, you would combine this with the ``-p 8080:8080`` option to 'publish' port 8080, allowing the notebook server to be accessed on the host. By default, notebooks are created in the home directory of the 'genn' user inside the container. However, to create notebooks which persist beyond the lifetime of the container, the notebook command needs to be combined with the options discussed previously. For example: From 3081c0f45ebe08e98fe557dba80c4f0c47d387f1 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Thu, 27 Oct 2022 10:59:17 +0100 Subject: [PATCH 31/32] use /local_home as mountpoint --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 45d28e9480..87dc22ed05 100644 --- a/README.md +++ b/README.md @@ -126,27 +126,27 @@ You can also provide a final argument to launch a different executable e.g. ``/b When using the GeNN container you often want to access files on your host system. This can be easily achieved by using the ``-v`` option to mount a local directory into the container. For example: ```bash -docker run -it --gpus=all -v $HOME:/home gennteam/genn:latest +docker run -it --gpus=all -v $HOME:/local_home gennteam/genn:latest ``` -mounts the local user's home directory into ``/home`` within the container. +mounts the local user's home directory into ``/local_home`` within the container. However, all of the commands provided by the GeNN container operate using a non-elevated, internal user called 'genn' who, by default, won't have the correct permissions to create files in volumes mounted into the container. This can be resolved by setting the ``LOCAL_USER_ID`` and ``LOCAL_GROUP_ID`` environment variables when running the container like: ```bash -docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest +docker run -it --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/local_home gennteam/genn:latest ``` -which will ensure that that 'genn' user has the same UID and GID as the local user, meaning that they will have the same permissions to access the files mountd into ``/home``. +which will ensure that that 'genn' user has the same UID and GID as the local user, meaning that they will have the same permissions to access the files mounted into ``/local_home``. ### Running Jupyter Notebooks A Jupyter Notebook environment running in the container can be launched using the ``notebook`` command. Typically, you would combine this with the ``-p 8080:8080`` option to 'publish' port 8080, allowing the notebook server to be accessed on the host. By default, notebooks are created in the home directory of the 'genn' user inside the container. However, to create notebooks which persist beyond the lifetime of the container, the notebook command needs to be combined with the options discussed previously. For example: ```bash -docker run --gpus=all -p 8080:8080 -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest notebook /home +docker run --gpus=all -p 8080:8080 -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/local_home gennteam/genn:latest notebook /local_home ``` will create notebooks in the current users home directory. ### Running PyGeNN scripts Assuming they have no additional dependencies, PyGeNN scripts can be run directly using the container with the ``script`` command. As scripts are likely to be located outside of the container, the script command is often combined with the options discussed previously. For example, to run a script called ``test.py`` in your home directory, the script command could be invoked with: ```bash -docker run --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/home gennteam/genn:latest script /home/test.py +docker run --gpus=all -e LOCAL_USER_ID=`id -u $USER` -e LOCAL_GROUP_ID=`id -g $USER` -v $HOME:/local_home gennteam/genn:latest script /local_home/test.py ``` ## Usage From 0dc3d72f7712d1ca26e8bc04b37a6f81d5bda656 Mon Sep 17 00:00:00 2001 From: neworderofjamie Date: Thu, 27 Oct 2022 14:39:30 +0100 Subject: [PATCH 32/32] cd works fine --- bin/genn-docker-entrypoint.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/genn-docker-entrypoint.sh b/bin/genn-docker-entrypoint.sh index 11db87df9d..0f3aaaf636 100755 --- a/bin/genn-docker-entrypoint.sh +++ b/bin/genn-docker-entrypoint.sh @@ -17,13 +17,15 @@ if [[ "$1" = "script" ]]; then # **YUCK** this should not really be necessary but PyGeNN does # not work nicely running scripts not in working directory CWD=$(dirname "$1") - exec gosu genn:genn /bin/bash -c "cd \"$CWD\" && python3 \"$@\"" + cd "$CWD" + exec gosu genn:genn python3 "$@" # Otherwise, if notebook is passes elif [[ "$1" = "notebook" ]]; then - # Extract working directory from next command line argument, otherwise use home + # Extract notebook directory from next command line argument, otherwise use home CWD=${2:-$HOME} exec gosu genn:genn /usr/local/bin/jupyter-notebook --ip=0.0.0.0 --port=8080 --no-browser --notebook-dir="$CWD" -# Otherwise, execute arguments +# Otherwise, change directory to home directory and execute arguments else + cd $HOME exec gosu genn:genn "$@" fi