diff options
Diffstat (limited to 'lib/spack/docs/containers.rst')
-rw-r--r-- | lib/spack/docs/containers.rst | 423 |
1 files changed, 295 insertions, 128 deletions
diff --git a/lib/spack/docs/containers.rst b/lib/spack/docs/containers.rst index 2590fec8b6..f5bd5602bc 100644 --- a/lib/spack/docs/containers.rst +++ b/lib/spack/docs/containers.rst @@ -9,28 +9,48 @@ Container Images ================ -Spack can be an ideal tool to setup images for containers since all the -features discussed in :ref:`environments` can greatly help to manage -the installation of software during the image build process. Nonetheless, -building a production image from scratch still requires a lot of -boilerplate to: +Spack :ref:`environments` are a great tool to create container images, but +preparing one that is suitable for production requires some more boilerplate +than just: -- Get Spack working within the image, possibly running as root -- Minimize the physical size of the software installed -- Properly update the system software in the base image +.. code-block:: docker + + COPY spack.yaml /environment + RUN spack -e /environment install + +Additional actions may be needed to minimize the size of the +container, or to update the system software that is installed in the base +image, or to set up a proper entrypoint to run the image. These tasks are +usually both necessary and repetitive, so Spack comes with a command +to generate recipes for container images starting from a ``spack.yaml``. + +-------------------- +A Quick Introduction +-------------------- + +Consider having a Spack environment like the following: + +.. code-block:: yaml + + spack: + specs: + - gromacs+mpi + - mpich -To facilitate users with these tedious tasks, Spack provides a command -to automatically generate recipes for container images based on -Environments: +Producing a ``Dockerfile`` from it is as simple as moving to the directory +where the ``spack.yaml`` file is stored and giving the following command: .. code-block:: console - $ ls - spack.yaml + $ spack containerize > Dockerfile + +The ``Dockerfile`` that gets created uses multi-stage builds and +other techniques to minimize the size of the final image: + +.. code-block:: docker - $ spack containerize # Build stage with Spack pre-installed and ready to be used - FROM spack/centos7:latest as builder + FROM spack/ubuntu-bionic:latest as builder # What we want to install and how we want to install it # is specified in a manifest file (spack.yaml) @@ -45,7 +65,7 @@ Environments: && echo " view: /opt/view") > /opt/spack-environment/spack.yaml # Install the software, remove unnecessary deps - RUN cd /opt/spack-environment && spack env activate . && spack install && spack gc -y + RUN cd /opt/spack-environment && spack env activate . && spack install --fail-fast && spack gc -y # Strip all the binaries RUN find -L /opt/view/* -type f -exec readlink -f '{}' \; | \ @@ -58,45 +78,34 @@ Environments: RUN cd /opt/spack-environment && \ spack env activate --sh -d . >> /etc/profile.d/z10_spack_environment.sh - # Bare OS image to run the installed executables - FROM centos:7 + FROM ubuntu:18.04 COPY --from=builder /opt/spack-environment /opt/spack-environment COPY --from=builder /opt/software /opt/software COPY --from=builder /opt/view /opt/view COPY --from=builder /etc/profile.d/z10_spack_environment.sh /etc/profile.d/z10_spack_environment.sh - RUN yum update -y && yum install -y epel-release && yum update -y \ - && yum install -y libgomp \ - && rm -rf /var/cache/yum && yum clean all - - RUN echo 'export PS1="\[$(tput bold)\]\[$(tput setaf 1)\][gromacs]\[$(tput setaf 2)\]\u\[$(tput sgr0)\]:\w $ "' >> ~/.bashrc - - - LABEL "app"="gromacs" - LABEL "mpi"="mpich" - ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l"] -In order to build and run the image, execute: +The image itself can then be built and run in the usual way, with any of the +tools suitable for the task. For instance, if we decided to use ``docker``: .. code-block:: bash $ spack containerize > Dockerfile $ docker build -t myimage . + [ ... ] $ docker run -it myimage -The bits that make this automation possible are discussed in details -below. All the images generated in this way will be based on -multi-stage builds with: +The various components involved in the generation of the recipe and their +configuration are discussed in details in the sections below. -- A fat ``build`` stage containing common build tools and Spack itself -- A minimal ``final`` stage containing only the software requested by the user +.. _container_spack_images: ------------------ -Spack Base Images ------------------ +-------------------------- +Spack Images on Docker Hub +-------------------------- Docker images with Spack preinstalled and ready to be used are built on `Docker Hub <https://hub.docker.com/u/spack>`_ @@ -131,19 +140,20 @@ All the images are tagged with the corresponding release of Spack: with the exception of the ``latest`` tag that points to the HEAD of the ``develop`` branch. These images are available for anyone to use and take care of all the repetitive tasks that are necessary -to setup Spack within a container. All the container recipes generated -automatically by Spack use them as base images for their ``build`` stage. - +to setup Spack within a container. The container recipes generated +by Spack use them as default base images for their ``build`` stage, +even though handles to use custom base images provided by users are +available to accommodate complex use cases. -------------------------- -Environment Configuration -------------------------- +--------------------------------- +Creating Images From Environments +--------------------------------- Any Spack Environment can be used for the automatic generation of container recipes. Sensible defaults are provided for things like the base image or the -version of Spack used in the image. If a finer tuning is needed it can be -obtained by adding the relevant metadata under the ``container`` attribute -of environments: +version of Spack used in the image. +If a finer tuning is needed it can be obtained by adding the relevant metadata +under the ``container`` attribute of environments: .. code-block:: yaml @@ -157,9 +167,10 @@ of environments: # singularity or anything else that is currently supported format: docker - # Select from a valid list of images - base: - image: "centos:7" + # Sets the base images for the stages where Spack builds the + # software or where the software gets installed after being built.. + images: + os: "centos:7" spack: develop # Whether or not to strip binaries @@ -167,7 +178,8 @@ of environments: # Additional system packages that are needed at runtime os_packages: - - libgomp + final: + - libgomp # Extra instructions extra_instructions: @@ -179,7 +191,210 @@ of environments: app: "gromacs" mpi: "mpich" -The tables below describe the configuration options that are currently supported: +A detailed description of the options available can be found in the +:ref:`container_config_options` section. + +------------------- +Setting Base Images +------------------- + +The ``images`` subsection is used to select both the image where +Spack builds the software and the image where the built software +is installed. This attribute can be set in two different ways and +which one to use depends on the use case at hand. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Use Official Spack Images From Dockerhub +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To generate a recipe that uses an official Docker image from the +Spack organization to build the software and the corresponding official OS image +to install the built software, all the user has to do is specify: + +1. An operating system under ``images:os`` +2. A Spack version under ``images:spack`` + +Any combination of these two values that can be mapped to one of the images +discussed in :ref:`container_spack_images` is allowed. For instance, the +following ``spack.yaml``: + +.. code-block:: yaml + + spack: + specs: + - gromacs+mpi + - mpich + + container: + images: + os: centos/7 + spack: 0.15.4 + +uses ``spack/centos7:0.15.4`` and ``centos:7`` for the stages where the +software is respectively built and installed: + +.. code-block:: docker + + # Build stage with Spack pre-installed and ready to be used + FROM spack/centos7:0.15.4 as builder + + # What we want to install and how we want to install it + # is specified in a manifest file (spack.yaml) + RUN mkdir /opt/spack-environment \ + && (echo "spack:" \ + && echo " specs:" \ + && echo " - gromacs+mpi" \ + && echo " - mpich" \ + && echo " concretization: together" \ + && echo " config:" \ + && echo " install_tree: /opt/software" \ + && echo " view: /opt/view") > /opt/spack-environment/spack.yaml + [ ... ] + # Bare OS image to run the installed executables + FROM centos:7 + + COPY --from=builder /opt/spack-environment /opt/spack-environment + COPY --from=builder /opt/software /opt/software + COPY --from=builder /opt/view /opt/view + COPY --from=builder /etc/profile.d/z10_spack_environment.sh /etc/profile.d/z10_spack_environment.sh + + ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l"] + +This method of selecting base images is the simplest of the two, and we advise +to use it whenever possible. There are cases though where using Spack official +images is not enough to fit production needs. In these situations users can manually +select which base image to start from in the recipe, as we'll see next. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Use Custom Images Provided by Users +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Consider, as an example, building a production grade image for a CUDA +application. The best strategy would probably be to build on top of +images provided by the vendor and regard CUDA as an external package. + +Spack doesn't currently provide an official image with CUDA configured +this way, but users can build it on their own and then configure the +environment to explicitly pull it. This requires users to: + +1. Specify the image used to build the software under ``images:build`` +2. Specify the image used to install the built software under ``images:final`` + +A ``spack.yaml`` like the following: + +.. code-block:: yaml + + spack: + specs: + - gromacs@2019.4+cuda build_type=Release + - mpich + - fftw precision=float + packages: + cuda: + buildable: False + externals: + - spec: cuda%gcc + prefix: /usr/local/cuda + + container: + images: + build: custom/cuda-10.1-ubuntu18.04:latest + final: nvidia/cuda:10.1-base-ubuntu18.04 + +produces, for instance, the following ``Dockerfile``: + +.. code-block:: docker + + # Build stage with Spack pre-installed and ready to be used + FROM custom/cuda-10.1-ubuntu18.04:latest as builder + + # What we want to install and how we want to install it + # is specified in a manifest file (spack.yaml) + RUN mkdir /opt/spack-environment \ + && (echo "spack:" \ + && echo " specs:" \ + && echo " - gromacs@2019.4+cuda build_type=Release" \ + && echo " - mpich" \ + && echo " - fftw precision=float" \ + && echo " packages:" \ + && echo " cuda:" \ + && echo " buildable: false" \ + && echo " externals:" \ + && echo " - spec: cuda%gcc" \ + && echo " prefix: /usr/local/cuda" \ + && echo " concretization: together" \ + && echo " config:" \ + && echo " install_tree: /opt/software" \ + && echo " view: /opt/view") > /opt/spack-environment/spack.yaml + + # Install the software, remove unnecessary deps + RUN cd /opt/spack-environment && spack env activate . && spack install --fail-fast && spack gc -y + + # Strip all the binaries + RUN find -L /opt/view/* -type f -exec readlink -f '{}' \; | \ + xargs file -i | \ + grep 'charset=binary' | \ + grep 'x-executable\|x-archive\|x-sharedlib' | \ + awk -F: '{print $1}' | xargs strip -s + + # Modifications to the environment that are necessary to run + RUN cd /opt/spack-environment && \ + spack env activate --sh -d . >> /etc/profile.d/z10_spack_environment.sh + + # Bare OS image to run the installed executables + FROM nvidia/cuda:10.1-base-ubuntu18.04 + + COPY --from=builder /opt/spack-environment /opt/spack-environment + COPY --from=builder /opt/software /opt/software + COPY --from=builder /opt/view /opt/view + COPY --from=builder /etc/profile.d/z10_spack_environment.sh /etc/profile.d/z10_spack_environment.sh + + ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l"] + +where the base images for both stages are completely custom. + +This second mode of selection for base images is more flexible than just +choosing an operating system and a Spack version, but is also more demanding. +Users may need to generate by themselves their base images and it's also their +responsibility to ensure that: + +1. Spack is available in the ``build`` stage and set up correctly to install the required software +2. The artifacts produced in the ``build`` stage can be executed in the ``final`` stage + +Therefore we don't recommend its use in cases that can be otherwise +covered by the simplified mode shown first. + +---------------------------- +Singularity Definition Files +---------------------------- + +In addition to producing recipes in ``Dockerfile`` format Spack can produce +Singularity Definition Files by just changing the value of the ``format`` +attribute: + +.. code-block:: console + + $ cat spack.yaml + spack: + specs: + - hdf5~mpi + container: + format: singularity + + $ spack containerize > hdf5.def + $ sudo singularity build hdf5.sif hdf5.def + +The minimum version of Singularity required to build a SIF (Singularity Image Format) +image from the recipes generated by Spack is ``3.5.3``. + +.. _container_config_options: + +----------------------- +Configuration Reference +----------------------- + +The tables below describe all the configuration options that are currently supported +to customize the generation of container recipes: .. list-table:: General configuration options for the ``container`` section of ``spack.yaml`` :header-rows: 1 @@ -192,21 +407,41 @@ The tables below describe the configuration options that are currently supported - The format of the recipe - ``docker`` or ``singularity`` - Yes - * - ``base:image`` - - Base image for ``final`` stage + * - ``images:os`` + - Operating system used as a base for the image - See :ref:`containers-supported-os` - - Yes - * - ``base:spack`` - - Version of Spack + - Yes, if using constrained selection of base images + * - ``images:spack`` + - Version of Spack use in the ``build`` stage - Valid tags for ``base:image`` - - Yes + - Yes, if using constrained selection of base images + * - ``images:build`` + - Image to be used in the ``build`` stage + - Any valid container image + - Yes, if using custom selection of base images + * - ``images:final`` + - Image to be used in the ``build`` stage + - Any valid container image + - Yes, if using custom selection of base images * - ``strip`` - Whether to strip binaries - ``true`` (default) or ``false`` - No - * - ``os_packages`` - - System packages to be installed - - Valid packages for the ``final`` OS + * - ``os_packages:command`` + - Tool used to manage system packages + - ``apt``, ``yum`` + - Only with custom base images + * - ``os_packages:update`` + - Whether or not to update the list of available packages + - True or False (default: True) + - No + * - ``os_packages:build`` + - System packages needed at build-time + - Valid packages for the current OS + - No + * - ``os_packages:final`` + - System packages needed at run-time + - Valid packages for the current OS - No * - ``extra_instructions:build`` - Extra instructions (e.g. `RUN`, `COPY`, etc.) at the end of the ``build`` stage @@ -245,74 +480,6 @@ The tables below describe the configuration options that are currently supported - Description string - No -Once the Environment is properly configured a recipe for a container -image can be printed to standard output by issuing the following -command from the directory where the ``spack.yaml`` resides: - -.. code-block:: console - - $ spack containerize - -The example ``spack.yaml`` above would produce for instance the -following ``Dockerfile``: - -.. code-block:: docker - - # Build stage with Spack pre-installed and ready to be used - FROM spack/centos7:latest as builder - - # What we want to install and how we want to install it - # is specified in a manifest file (spack.yaml) - RUN mkdir /opt/spack-environment \ - && (echo "spack:" \ - && echo " specs:" \ - && echo " - gromacs+mpi" \ - && echo " - mpich" \ - && echo " concretization: together" \ - && echo " config:" \ - && echo " install_tree: /opt/software" \ - && echo " view: /opt/view") > /opt/spack-environment/spack.yaml - - # Install the software, remove unnecessary deps - RUN cd /opt/spack-environment && spack env activate . && spack install && spack gc -y - - # Strip all the binaries - RUN find -L /opt/view/* -type f -exec readlink -f '{}' \; | \ - xargs file -i | \ - grep 'charset=binary' | \ - grep 'x-executable\|x-archive\|x-sharedlib' | \ - awk -F: '{print $1}' | xargs strip -s - - # Modifications to the environment that are necessary to run - RUN cd /opt/spack-environment && \ - spack env activate --sh -d . >> /etc/profile.d/z10_spack_environment.sh - - - # Bare OS image to run the installed executables - FROM centos:7 - - COPY --from=builder /opt/spack-environment /opt/spack-environment - COPY --from=builder /opt/software /opt/software - COPY --from=builder /opt/view /opt/view - COPY --from=builder /etc/profile.d/z10_spack_environment.sh /etc/profile.d/z10_spack_environment.sh - - RUN yum update -y && yum install -y epel-release && yum update -y \ - && yum install -y libgomp \ - && rm -rf /var/cache/yum && yum clean all - - RUN echo 'export PS1="\[$(tput bold)\]\[$(tput setaf 1)\][gromacs]\[$(tput setaf 2)\]\u\[$(tput sgr0)\]:\w $ "' >> ~/.bashrc - - - LABEL "app"="gromacs" - LABEL "mpi"="mpich" - - ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l"] - -.. note:: - Spack can also produce Singularity definition files to build the image. The - minimum version of Singularity required to build a SIF (Singularity Image Format) - from them is ``3.5.3``. - -------------- Best Practices -------------- |