Docker Apps/Package Based

From Univention Wiki

Jump to: navigation, search

As stated in App_Center/Dev/Docker_Apps#Two_kinds_of_Docker_Apps there are two types of Docker Apps: Apps that base upon a stand-alone Docker image and Apps that install packages in a UCS based container (called ucs-appbox).

This chapter covers Apps that base upon Debian packages.

Use case

A Docker App that is based upon packages is easy to create if you already have Debian packages at hand. The image for these Docker Apps is (normally) a UCS based image. Thus, such a Docker App is good for deep integration as in the container itself runs, e.g., a Univention Directory Listener.

Life cycle

The life cycle of a package based Docker App is basically the same as that of an image based Docker App (see Docker_Apps_-_Image_based_Apps#Life_cycle). All points are valid here, too. Yet, there is one important additional feature of package based Docker Apps: Images do not necessarily have to be exchanged when a new App version is released (compare to Docker_Apps_-_Image_based_Apps#Upgrading_an_image_based_Docker_App).

Because of the way Docker Apps are uninstalled, no package uninstallation is taking place! The packages are not uninstalled, the container is removed. This means that no postrm Debian helper scripts are run. If you need that logic, you need to put it into the uinst scripts #Docker_Apps:_Scripts.

The Docker Container of a package based Docker App is more a virtual mashine that may actually run for as long as the Docker Host runs. App updates may be installed by installing new versions of the packages. There is no need to stop the container, remove it and set up a new one. It is more of a apt-get dist-upgrade.

Technically, when installing the App, a repository is included in the then started ucs-appbox container. From there packages as specified in the ini file are installed via APT.

Installation is unattended. You cannot interactively ask the user (e.g. for some kind of initial "root" password).

When upgrading the App, the old repository is removed and a new repository is added and the packages get updated. This is all done automatically by the App Center (more specifically: by scripts that live in the container and are called by the App Center).

That being said, an exchange of the image is allowed (just change DockerImage and do not include the old image in DockerAllowedImages). In this case, the section from the image based Docker Apps applies.

Docker Apps: Scripts

For every Docker App, the App Center server may hold several scripts that do not need to be packaged. Even for package based Docker Apps, it is possible to integrate it without needing to build an additional integration package (like univention-app.deb). That being said, with increasing complexity, it is advised to build such a package nonetheless. Furthermore, not everything can be achieved easily with these scripts. There are interfaces rarely used that the App Center does not support. Should your Docker App require these interfaces, it may be necessary to create a package to (also) ship the scripts mentioned below.

We need to distinguish between outer scripts and inner scripts. An outer script is called on the Docker Host, inner scripts are called inside the running Docker Container.

All scripts are called with root privileges. For inner scripts this means the local root of the Docker Container. Some scripts may get LDAP credentials. Normally, these credentials are those of the Administrator account.

The following list assumes that a package based Docker App is used as it is more important for these to have the scripts. Anyway, all of these scripts may also be used in in image based Docker Apps. Normally, image based Docker Apps do not ship these scripts in the container itself. In this case, it is possible to upload them to the App Center server along with other meta files. They will be downloaded by the App Center and copied into the container right before execution. Package based Docker Apps already have these scripts in place. But even these Apps may upload scripts to the App Center server. These files will also be downloaded and copied, thus giving you the option to further enhance the functionality provided by default. It is strongly advised to not overwrite the existing scripts (which is possible), but instead copy them to another place and call the original script as the default behaviour is very likely important. For example, if you want to enhance the store_data script of a Docker App that is based on ucs-appbox, just change DockerScriptStoreData to somewhere in, say, /opt/app/ and call /usr/share/univention-docker-container-mode/store_data before or after your own logic.

The following scripts are for installation and uninstallation. Upgrades use these scripts, too, if (and only if) the upgrade includes an image exchange (i.e. the new version with the new ini file specifies a different DockerImage). In that case the old App is uninstalled and the new App is installed.

These scripts may also be useful for image based Docker Apps. Especially inst, uinst, store_data, restore_data_after_setup.
An outer script called before the Docker Container is initialized, even before the image is downloaded. Its purpose is to check whether installation may be successful. For example, the preinst may fail if certain hardware requirements are not met. Any exit code other than 0 will result in cancellation of the installation process. If the installation of an App is the result of an image exchange (and thus more of an upgrade) the preinst is also called. This script may also be used to setup the Host environment for the App before container creation, e.g., creating an outer directory with proper permissions.
An inner script called before setup is called, right after the container is started. Its purpose is to restore those bits that may be needed to successfully run the setup script. May be useful in an upgrade process where one needs to restore the state the old container was in instead of setting up the container as if it were fresh.
An inner script and heart of the whole installation process. By default it joins the system, (a script called univention-join provided by Univention), adds the repository that was created on the App Center server and installs DefaultPackages specified in the ini file. After that it once again joins, running all scripts that may have been installed during the App installation. If the script fails (exit code != 0) the installation is aborted.
An inner script called after setup is called. Its purpose is to actually restore the data that may have been saved in store_data – now that the App is up and running but the database is still empty.
Also called join script. An outer script called after the Docker Container is configured. Think of it as a postinst of the App. See the Developer Reference for how to write a join script. If the join script runs successfully, the join script may save this information in a status file. If this does not happen, the user is constantly reminded to re-run the join script. So the join script does not need to run successfully. The installation will not be aborted at this point. But of course at some point it should run through successfully. The main purpose of the join script is to set up the domain for the new App, e.g. by adding a domain user that can be used as the LDAP binddn that your App may need to authenticate against the central user management of UCS.
An outer script called before the Docker Container is removed. Its purpose is to check whether an uninstallation may be successful. But it may be used to somehow prepare the system for the uninstallation. For example, the prerm may fail if other software still depends on it. Any exit code other than 0 will result in cancellation of the uninstallation process.
An inner script called before removing the Docker Container. In fact the App is not really uninstalled. The container is just thrown away. This also happens during image upgrades: The current image is thrown away and a new image is set up. Therefore it is important to store the data of the current App to be able to start into exactly that state when the container was removed. You may call any App specific commands like myapp-backup --full or just copy the important files. The App Center always mounts the following directory into the container, which can be used to store the data (and later restore the data from there as the very same directory will be mounted into the new container): /var/lib/univention-appcenter/apps/$APPID/data/.
Also called unjoin script. An outer script called after the Docker Container is removed. Think of it as a postrm of the App. See the Developer Reference for how to write an unjoin script. It should somehow revert most (if not all) changes done in the inst script (or join script). With the notable exception of schema registration. An LDAP schema extension should never be removed once it was registered.

The following scripts are for upgrading the software within the Docker Container. Three possible scenarios have to be covered:

  • Upgrade of system packages (security fixes, UCS calls them Errata Updates)
  • Upgrade of the operating system (a new patchlevel release or even a minor/major update of UCS (4.1-1 or 4.2-0)
  • Upgrade of App packages, i.e. a new version (with the same DockerImage) was released
These scripts are useful for a Docker Container to run indefinitely and never be replaced. As such, they are probably not important to image based Docker Apps.
An inner script called when the App Center wants to find out whether the container may install package updates or release updates. By default, this is done automatically once a day. It can be triggered manually, too, though. The script needs to echo the result: packages if mere package updates are available. These include security fixes for operating system

packages. release: RELEASE if a new version of the operating itself is available. RELEASE can be anything, it is just presented to the user. Note that the script does not search for App updates, nor does it search for a change in the DockerImage! This is done by the "outer" App Center.

An inner script called when (all) updates of existing packages shall be installed.
An inner script called when a new version of the operating system shall be installed.
An inner script called when a new version of the App packages shall be installed. This script is different from update_packages. This has technical reasons, because for normal UCS based Docker images, this requires a new repository to be registered. But it also has usability reasons: First, users may want to distinguish between necessary, stability improving package updates and (potentially) ground-shaking App updates; second, at least the UCS containers are configured to install security / stability updates


Docker Apps: Files

An App may ship additional files along with the ini file. These are not scripts as in the previous section, just plain text files.

An environment file used during the creation of the Docker Container. It contains static configuration options passed to the container via docker create ... --env ${env}. See the Docker Documentation.
This file contains (a superset of) UCR variable definitions. These definitions exist on a regular UCS to describe the specific variables in the UCR database. In this context, they are used to set UCR variables in the Docker Container. If this file is present, there will be a form before the installation of the App and after the installation on a separate page within the App Center module ("App Settings"). Further information can be found in Section 8.2.
A schema extension for LDAP. This is useful if you want to, e.g., extend the user objects of UCS by an attribute like "This user may use the App" (see Section 8.3). The file will be copied to /usr/share/univention-appcenter/apps/APPID/APPID.schema during installation. See the LDAP documentation for the syntax of a schema file. If you need an "official" OID namespace, Univention can provide one. It is important to note that shipping this file alone is not enough. You need to register it in the join script (see Section #Docker_Apps:_Scripts) via ucs_registerLDAPExtension "$@" --schema "/usr/share/univention-appcenter/apps/$APP/$APP.schema".

Docker Apps: Directories

TBD; /var/lib/univention-appcenter/...


As stated above, a package based Docker App is much like a virtual mashine. You develop Debian packages for a minimal member server. The App Center takes care of the containerization.

In this section, we will develop a Docker App based on the package dudle. Dudle is a clone of Doodle to organize polls and the like.

Actually, this section is rather short. Apart from the packages there is not very much to do with package based Docker Apps. The App Center does most of the work. And as the underlying image is a UCS, the interesting parts work out of the box.

The following ini file will be used:

Description=Schedule events and execute polls very easy
LongDescription=Dudle is a clone of the well-known solution Doodle and allows to comfortably find joint appointments with multiple participants or carry out polls very easy. It radically simplifies the process.
Categories=Collaboration, Education
Maintainer=Univention GmbH
WebInterfaceName=Dudle - Appointments & Polls

Description=Terminfindung und Abstimmungen einfach durchführen
LongDescription=Dudle ist ein Klon der bekannten Lösung Doodle und dient wie diese dazu, einfach und bequem gemeinsame Termine unter mehreren Teilnehmern zu
finden oder einfach Abstimmungen vorzunehmen. Sie verkürzt so den Abstimmungsprozess erheblich.
WebInterfaceName=Dudle - Termine & Umfragen

Notable variables:

The package dudle has been built and uploaded to the App Center server:
A custom setup script will be shipped and copied to this location. The script can be found here. Dudle is a very simple App. Linking /var/www/ in the container to the data directory will save all relevant files in the shared volume. Note that it executes the original setup script at the end.

That's about it. The crucial part (other than developing the software, of course) is saving the user data somehow in the shared volume. This is important when the container is removed. This happens during an image upgrade (which is actually not very common for UCS based images, as they can update themselves) and during an uninstallation. In the latter case, the shared volume helps to start where it ended after the user reinstalls the App.

In this section, this is done by linking the data directory to the shared volume. For more complicated szenarios, there are store_data and restore_data_after_setup in #Docker_Apps:_Scripts. If the data (partially) is in a database, see also Section 8.5.4.

Personal tools