From 17219f6e1fa511213b77ac06f305b820ffa74f08 Mon Sep 17 00:00:00 2001 From: Carlo Mion Date: Thu, 2 Mar 2023 15:37:30 +0100 Subject: [PATCH] docs(DEV.rst): add documentation explaining the Docker build process Explain the usage of `pip-compile` in the Docker build --- docs/DEV.rst | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ docs/conf.py | 4 +++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/docs/DEV.rst b/docs/DEV.rst index e93b4480c..3808d4680 100644 --- a/docs/DEV.rst +++ b/docs/DEV.rst @@ -111,6 +111,56 @@ tests conf configuration directory, containing some sample files +Dependencies management +^^^^^^^^^^^^^^^^^^^^^^^ + +This project is published as a Python package, and following the `PEP 631 `_ convention +the dependencies are declared as part of the ``pyproject.toml`` file. +However since this project is run as an application, it is good practice to clearly specify the version of dependencies the application has been built and tested with, +to ensure a consistent deployment environment across multiple systems. + +For this reason, a ``requirements.txt`` file is used to **pin** all the dependencies (both direct and indirect ones), specifying their exact version. +This file is auto-generated using ``pip-compile``, provided by the `pip-tools `_ package. +It uses the ``pyproject.toml`` as the source for the dependencies, and should not be manually changed. It is generated using + +.. code:: console + + $ pip-compile --resolver=backtracking pyproject.toml + + +This ``requirements.txt`` file is fundamental for efficiently building the ``Docker`` images: thanks to the Docker build cache, +the dependencies are only installed the first time in the built process, and are re-used from the Docker cache in subsequent builds. +This improves dramatically the build times, especially when there is the need to compile native dependencies. +See :ref:`Docker build` for more information. + +Docker build +^^^^^^^^^^^^ + +To locally build the container, it is required to have installed at least *Docker Engine 23.0*, since it enables `Docker BuildKit `_ by default, +with all its useful features used in this build process. + +- First it is necessary to build the AppDaemon Python package in the project directory (it will then be used as part of the Docker build stage). + +.. code:: console + + $ python -m build + +- Then invoke the usual the docker build command: + +.. code:: console + + $ docker build -t appdaemon . + + +The Docker build makes use of the `multi-stage build `_ capabilities of Docker. +This is necessary since the *arm/v6* and *arm/v7* architectures do not provide Python *wheels* for this architectures of the **orjson** and **uvloop** packages, required by this project. + +For this reason the build is divided in multiple *stages*: a *builder* stage and a *runtime* stage: + +- The **builder** stage is used to install compile-time dependencies such as ``gcc`` and ``rust`` (to compile C extensions of Python dependencies), in addition to all the dependencies defined in the ``requirements.txt``. + + By copying only the ``requirements.txt``, **only the dependencies** of AppDameon are installed, so if there is no change in them between two subsequent Docker builds, Docker caches this layer and skip this step. +- The **runtime stage** copies the built Python packages from the previous stage and install the AppDaemon package in the container, along with its startup scripts and files. Pull Requests ------------- diff --git a/docs/conf.py b/docs/conf.py index 54a6d439d..7a007673d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,9 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon"] +# - sphinx.ext.autosectionlabel: link to sections of the document ny their name +# https://sublime-and-sphinx-guide.readthedocs.io/en/latest/references.html#links-to-sections-in-the-same-document +extensions = ["sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx.ext.autosectionlabel"] autodoc_member_order = "bysource"