diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml new file mode 100644 index 0000000..5314567 --- /dev/null +++ b/.github/workflows/container.yml @@ -0,0 +1,60 @@ +name: Container + +on: + push: + branches: [ "master" ] + workflow_dispatch: + +env: + IMAGE_NAME: pynucleus + IMAGE_TAGS: latest ${{ github.sha }} + IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }} + REGISTRY_USER: ${{ github.actor }} + REGISTRY_PASSWORD: ${{ github.token }} + +jobs: + + container: + runs-on: ubuntu-latest + timeout-minutes: 300 + + steps: + - name: Check out + if: always() + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - uses: hadolint/hadolint-action@v3.1.0 + with: + dockerfile: Dockerfile + ignore: 'DL3008,DL3013' + + - name: Build Image + id: build_image + uses: redhat-actions/buildah-build@v2 + with: + image: ${{ env.IMAGE_NAME }} + tags: ${{ env.IMAGE_TAGS }} + containerfiles: | + ./Dockerfile + + - name: Run tests + run: | + podman run -e MPIEXEC_FLAGS="--allow-run-as-root --oversubscribe" --rm ${{ steps.build_image.outputs.image }}:${{ github.sha }} python3 -m pytest --junit-xml=test-results.xml tests/ + + - name: Push To GHCR + uses: redhat-actions/push-to-registry@v2 + id: push + with: + image: ${{ steps.build_image.outputs.image }} + tags: ${{ steps.build_image.outputs.tags }} + registry: ${{ env.IMAGE_REGISTRY }} + username: ${{ env.REGISTRY_USER }} + password: ${{ env.REGISTRY_PASSWORD }} + extra-args: | + --disable-content-trust + + - name: Echo outputs + run: | + echo "${{ toJSON(steps.push.outputs) }}" diff --git a/Dockerfile b/Dockerfile index 841fbb7..2a21c62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,14 +8,9 @@ LABEL maintainer Christian Glusa ENV LANG C.UTF-8 -# based on recommendations from -# https://docs.nersc.gov/development/shifter/how-to-use/ - -# add contrib and non-free debian repos -RUN sed -i "s#deb http://deb.debian.org/debian testing main#deb http://deb.debian.org/debian testing main contrib non-free#g" /etc/apt/sources.list - # install packages needed for build -RUN apt-get update && \ +RUN sed -i 's/Components: main/Components: main contrib non-free/' /etc/apt/sources.list.d/debian.sources \ + && apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ autoconf automake gcc g++ make gfortran wget zlib1g-dev libffi-dev \ tk-dev \ @@ -25,30 +20,31 @@ RUN apt-get update && \ hdf5-tools \ libsuitesparse-dev \ libarpack2-dev \ - libmkl-avx2 libmkl-dev \ mpi-default-bin mpi-default-dev \ - python3 python3-dev python3-pip python3-mpi4py cython3 python3-numpy python3-scipy python3-matplotlib python3-tk \ + python3 python3-dev python-is-python3 python3-pip python3-mpi4py cython3 python3-numpy python3-scipy python3-matplotlib python3-tk python3-venv \ libmetis-dev libparmetis-dev \ texlive texlive-extra-utils texlive-latex-extra ttf-staypuft dvipng cm-super \ + jupyter-notebook python3-jupyterlab \ --no-install-recommends \ && rm -rf /var/lib/apt/lists/* -ENV LD_LIBRARY_PATH /usr/local/lib - -RUN echo "alias ls='ls --color=auto -FN'" >> /root/.bashrc - -RUN /sbin/ldconfig - - -# copy code to container and build -# we copy only the packages over, not any run scripts - -COPY PyNucleus /home/pynucleus-build/PyNucleus -COPY packageTools /home/pynucleus-build/packageTools -COPY base /home/pynucleus-build/base -COPY metisCy /home/pynucleus-build/metisCy -COPY fem /home/pynucleus-build/fem -COPY multilevelSolver /home/pynucleus-build/multilevelSolver -COPY nl /home/pynucleus-build/nl -COPY setup.py setup.cfg versioneer.py MANIFEST.in Makefile README.rst LICENSE /home/pynucleus-build/ -RUN cd /home/pynucleus-build && make +COPY . /pynucleus +ENV VIRTUAL_ENV=/pynucleus/venv +RUN python3 -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" +WORKDIR /pynucleus +RUN make prereq && \ + make prereq-extra && \ + make install && \ + python -m pip install --no-cache-dir ipykernel && \ + rm -rf build packageTools/build base/build metisCy/build fem/build multilevelSolver/build nl/build + +RUN echo "alias ls='ls --color=auto -FN'" >> /root/.bashrc \ + && echo 'set completion-ignore-case On' >> /root/.inputrc + +# allow running MPI as root in the container +# bind MPI ranks to hwthreads +ENV OMPI_MCA_hwloc_base_binding_policy=hwthread \ + MPIEXEC_FLAGS=--allow-run-as-root + +RUN python -m ipykernel install --name=PyNucleus diff --git a/Makefile b/Makefile index 74372aa..11be666 100644 --- a/Makefile +++ b/Makefile @@ -139,26 +139,23 @@ docker: # rm -rf docker-build docker-linux: - # enable access to xserver (so that we can see some plots) - xhost + - # run the container - docker run -it \ - -v $(XAUTHORITY):/.Xauthority -e XAUTHORITY=/.Xauthority \ - -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" -e DISPLAY=$(DISPLAY) \ + podman run -it \ + -v $(XAUTHORITY):/root/.Xauthority \ + -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" \ + -e DISPLAY=$(DISPLAY) \ + --network "host" \ -e HTTP_PROXY=$(HTTP_PROXY) \ -e HTTPS_PROXY=$(HTTPS_PROXY) \ -e http_proxy=$(http_proxy) \ -e https_proxy=$(https_proxy) \ -v $(PWD):/home/pynucleus \ -w "/home/pynucleus/" \ - dockerized-pynucleus - # disable access to xserver - xhost - - + localhost/pynucleus-test docker-mac: docker run -it \ -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$(DISPLAY) \ + --network host \ -e HTTP_PROXY=$(HTTP_PROXY) \ -e HTTPS_PROXY=$(HTTPS_PROXY) \ -e http_proxy=$(http_proxy) \ @@ -167,8 +164,6 @@ docker-mac: -w "/home/pynucleus/" \ dockerized-pynucleus - - prereq: $(PYTHON) -m pip install $(PIP_FLAGS) $(PIP_INSTALL_FLAGS) wheel Cython cython numpy scipy matplotlib pyyaml h5py pybind11 MeshPy tabulate modepy mpi4py pyamg meshio $(PYTHON) -m pip install $(PIP_FLAGS) $(PIP_INSTALL_FLAGS) scikit-sparse diff --git a/README.rst b/README.rst index 9231610..8f8daec 100644 --- a/README.rst +++ b/README.rst @@ -73,9 +73,56 @@ and open ``docs/build/index.html`` in your browser. Possible ways to install and use PyNucleus ================================== -* Spack install, -* manual install, -* Docker container. +* container image +* Spack installation +* manual installation + + +Container image +---------------- + +The simplest way to use PyNucleus is to pull a container image from the GitHub Container Registry. +This requires an installation of either + +* podman (https://podman.io/) and podman-compose (https://github.com/containers/podman-compose) or +* Docker (https://www.docker.com/) and Docker Compose (https://docs.docker.com/compose/install/). + +For many Linux distributions these can be installed from the package repositories. +In what follows we will assume that we are using podman. +All commands for Docker should be identical up to the substitution of `podman` with `docker`. + +For example, on Ubuntu podman can be installed with + +.. code-block:: shell + + sudo apt-get install podman podman-compose + +Instructions for other platforms can be found here: https://podman.io/docs/installation + +Once podman is installed, we can download a copy of https://github.com/sandialabs/PyNucleus/compose.yaml and save it to an empty directory. +In that directory we then run + +.. code-block:: shell + + podman compose run pynucleus + +This launches a shell on the container with PyNucleus. +A simple way to test if things work is to run + +.. code-block:: shell + + drivers/runFractional.py + +This should print some information about the solution of a fractional Laplacian problem and open up several plots. + +For development using PyNucleus it can be useful to launch a Jupyter notebook server: + +.. code-block:: shell + + podman compose up pynucleus-jupyter + +and then open the access the Jupyter notebook interface at https://localhost:8889 + Spack install ------------- @@ -157,28 +204,6 @@ PyNucleus depends on other Python packages that will be installed automatically: * scikit-sparse -Docker container ----------------- - -A Docker container that contains all the required dependencies can be built as well: - -.. code-block:: shell - - make docker - -Once the build is done, it can be launched as - -.. code-block:: shell - - make docker-linux - -or - -.. code-block:: shell - - make docker-mac - - Funding ======= diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..7cf4574 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,44 @@ +version: 3 + +services: + + # Launch with: + # docker compose run --profile interactive pynucleus + pynucleus: + image: ghcr.io/sandialabs/pynucleus:latest + build: . + environment: + # host display server + - DISPLAY=${DISPLAY} + # expose host proxies + - http_proxy=${http_proxy} + - https_proxy=${https_proxy} + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + volumes: + # The current directory on host gets mapped to /pynucleus/user in the container + - $PWD:/pynucleus/user + # map files to container to allow GUI windows + - /tmp/.X11-unix:/tmp/.X11-unix + - $XAUTHORITY:/root/.Xauthority + network_mode: host + + # Launch with: + # docker compose up + # Then open localhost:8888 in your browser + pynucleus-jupyter: + image: ghcr.io/sandialabs/pynucleus:latest + build: . + command: jupyter notebook --port=8888 --no-browser --ip=0.0.0.0 --allow-root --NotebookApp.token='' --NotebookApp.password='' --notebook-dir=/pynucleus/user --KernelSpecManager.ensure_native_kernel=False --KernelSpecManager.allowed_kernelspecs=pynucleus + environment: + # expose host proxies + - http_proxy=${http_proxy} + - https_proxy=${https_proxy} + - HTTP_PROXY=${HTTP_PROXY} + - HTTPS_PROXY=${HTTPS_PROXY} + volumes: + # The current directory on host gets mapped to /pynucleus/user in the container + - $PWD/notebooks:/pynucleus/user + ports: + # Expose a Jupyter notebook server from the container + - 8889:8888 diff --git a/docs/installation.rst b/docs/installation.rst index 4aa6c6c..c2df9cf 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -2,9 +2,56 @@ Possible ways to install and use PyNucleus ========================================== -* Spack installation, -* manual installation, -* Docker container. +* container image +* Spack installation +* manual installation + + +Container image +---------------- + +The simplest way to use PyNucleus is to pull a container image from the GitHub Container Registry. +This requires an installation of either + +* podman (https://podman.io/) and podman-compose (https://github.com/containers/podman-compose) or +* Docker (https://www.docker.com/) and Docker Compose (https://docs.docker.com/compose/install/). + +For many Linux distributions these can be installed from the package repositories. +In what follows we will assume that we are using podman. +All commands for Docker should be identical up to the substitution of `podman` with `docker`. + +For example, on Ubuntu podman can be installed with + +.. code-block:: shell + + sudo apt-get install podman podman-compose + +Instructions for other platforms can be found here: https://podman.io/docs/installation + +Once podman is installed, we can download a copy of https://github.com/sandialabs/PyNucleus/compose.yaml and save it to an empty directory. +In that directory we then run + +.. code-block:: shell + + podman compose run pynucleus + +This launches a shell on the container with PyNucleus. +A simple way to test if things work is to run + +.. code-block:: shell + + drivers/runFractional.py + +This should print some information about the solution of a fractional Laplacian problem and open up several plots. + +For development using PyNucleus it can be useful to launch a Jupyter notebook server: + +.. code-block:: shell + + podman compose up pynucleus-jupyter + +and then open the access the Jupyter notebook interface at https://localhost:8889 + Spack install ------------- @@ -48,7 +95,7 @@ On Debian, Ubuntu etc, the required dependencies can be installed with sudo apt-get install python3 mpi-default-bin mpi-default-dev libmetis-dev libparmetis-dev libsuitesparse-dev -On MacOS the required dependencies can be installed with +On MacOS the required dependencies can be installed with Homebrew (https://brew.sh/) via .. code-block:: shell @@ -88,25 +135,3 @@ PyNucleus depends on other Python packages that will be installed automatically: * modepy * meshpy * scikit-sparse - - -Docker container ----------------- - -A Docker container that contains all the required dependencies can be built as well: - -.. code-block:: shell - - make docker - -Once the build is done, it can be launched as - -.. code-block:: shell - - make docker-linux - -or - -.. code-block:: shell - - make docker-mac