Docker Apps/Image Based
From Univention Wiki
As stated in 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.
This chapter covers Apps that base upon a stand-alone Docker image.
A Docker App that is based upon a ready-to-use Docker image is fairly easy to create. All it needs is the Docker image and the meta files. See Meta_files. (Technically, only the ini file is required)
These Apps are useful when you already have a working image.
What to do in a nutshell
To actually add such an App to Univention App Center, you need to:
- Create an ini file
- Have a logo file (better 2) in SVG
- Build a Docker Image
- Make the data persistent
- Write a join script / unjoin script (maybe minimal, only "Best practices")
- Optional: Further integration, e.g., web interface or settings
- Optional, encouraged: Write README files
Most of these things can be done using the Provider_Portal/Apps (which creates an ini file, lets you upload logos, write README files).
For the final App, your Docker image has to be hosted on Univention's Docker Registry docker.software-univention.de. This means that you have to somehow make the Docker image available for us to download and re-upload (uploading is not possible from "outside"). In the version of your App, the docker image needs to look like this: docker.software-univention.de/myapp:1.0.
For the time testing, myorganization/myapp:1.0 is enough. The image can be pulled from Docker Hub.
- Actually, whatever is in DockerImage is just used for a "docker pull" command. Docker Hub is supported like any other registry. For restricted access to your image during testing phase, you would need to do "docker login" manually on your UCS test machine.
- Univention's Docker Registry is not browsable. It needs credentials to be accessed. Before downloading the image via the Univention App Center module in UCS, each user (by default) needs to be registered by an email address. Yet, you should consider your Docker Image to be public by the time publishing the App in Univention App Center.
The life cycle of such a Docker App is straight forward. This is what happens when installing the App in simplified code:
if [ -e $app.preinst ]; then $app.preinst || exit 1; fi image=$(univention-app get $app DockerImage) docker pull $image container=$(docker create $image) # with some -p ports -v volumes -e env docker start $container || exit 1 if [ -e $app.restore_data_before_setup ]; then docker exec $container $app.restore_data_before_setup || exit 1; fi if [ -e $app.setup ]; then docker exec $container $app.setup || exit 1; fi if [ -e $app.restore_data_after_setup ]; then docker exec $container $app.restore_data_after_setup || exit 1; fi if [ -e $app.join ]; then $app.join; fi
There are a couple of scripts that the App may be bundled with (or that are already installed in the container). These scripts are explained in detail in Docker Apps/Container Scripts.
The docker image is downloaded and started. After that some scripts are run to setup the container, restore data that has been previously backed up (there will be no backup when installing, but technically the scripts run).
When the App is uninstalled, this is basically happening:
if [ -e $app.prerm ]; then $app.prerm || exit 1; fi container=$(ucr get appcenter/apps/$app/container) docker start $container || exit 1 # just in case if [ -e $app.store_data ]; then docker exec $container $app.store_data || exit 1; fi backup=$(docker commit $container) docker stop $container || exit 1 mv /var/lib/univention-appcenter/apps/$app/data /var/lib/univention-appcenter/backups/$backup/data mv /var/lib/univention-appcenter/apps/$app/conf /var/lib/univention-appcenter/backups/$backup/conf docker rm $container if [ -e $app.unjoin ]; then $app.unjoin; fi
The container is committed (as a backup), stopped and removed. A script has been run to backup any data of the App. As this is the uninstallation, this backup is moved to another directory.
- There is no easy tool to restore a backup. But the principal data is there, so it should be possible to get the App back running to the state before uninstallation. Again: This is not really supported, but present for convenience.
Upgrading an image based Docker App
When you want to release a new version of your Docker App, you need a new ini file. This ini file may be a copy of your old file. But at least the Version needs to be greater than before. You probably also want to change DockerImage, as the new version will come with a new, updated image.
This image needs to have a new name, too. Otherwise the App Center will not recognize that it needs to exchange the image.
- That's why you cannot simply name the DockerImage myapp:latest.
When this new ini file is released, the user may upgrade the Docker App. This is basically an uninstallation, followed by an installation. But the data is not moved during uninstallation, just copied, so that it is still there for the restore scripts.
Also, only the app.preinst is run, not the prerm. And no app.unjoin is run. The app.join on the other hand is run, but stops immediately unless the VERSION increased or it did not succeed yet with the previous App version. See also Integration_with_UCS/Join for the join script.
For a description of the scripts that run inside the container like app.store_data, please refer to Docker Apps/Container Scripts.
An file that is nearly functional is in: Meta_files. Note the following variables in this ini file:
- Explicitely set empty. This also holds for DockerScriptStoreData, etc. This is done because these variables have default values which are overwritten this way. Otherwise the App Center complains about missing scripts.
- Set to 8080 because the container starts Jenkins on that port. The container does not have any certificates, thus it does not provide a dedicated WebinterfacePortHTTPS. One could configure the container to do that by copying certificates and so on, but it is much easier to use 8080 for WebinterfacePortHTTPS, too.
- The Webinterface integration is described in Section 8.5.2. In a nutshell, the container's port WebinterfacePortHTTP is exposed as some port between 40000 and 41000 on the host and this port is used by Apache's mod_proxy to connect to the container. By default, it uses HTTP for HTTP requests and HTTPS for HTTPS requests in the mod_proxy configuration. Setting WebinterfaceProxy to http, Apache connects through HTTP to the container also for external HTTPS requests. Even though the Jenkins container does not speak HTTPS, we can now connect to https://docker-host/jenkins/.
- Apps are released for one minor version of UCS (e.g. 4.1). Every UCS 4.1 may install such an App regardless which exact version is installed. Besides minor and major version of UCS, we also release Errata updates (security fixes, but also usability improvements and, to a certain extent, new features). We have greatly improved the support for image based Docker Apps since the release of UCS 4.1. We strongly suggest putting at least 4.1-1 as RequiredUCSVersion for any image based Docker App. Actually, it is a good idea to check http://errata.software-univention.de/ucs/4.1/ and just put the latest errata level into the ini file (especially those errata updates concerning the App Center package), just to save users from running into subtle bugs.
The App will not work with only that ini file. First of all, the web interface can only be accessed at "/" by default. This does not work with the App Center's Apache integration. Secondly, the App does not save its data between App upgrades. Everything is wiped once the container is removed.
Therefore, we use the jenkins.env file:
These variables are passed over to the container upon creation. They are supported by the Docker image itself and fix our issues. The web interface is accessible at "/jenkins" (compare to WebInterface) and the data is stored in a special directory. It is created on the Docker Host and mounted into every Docker Container. Thus, it survives an image exchange. See Docker Apps/Files#Directories for the directories.
What the App Center does not support
Image based Docker Apps may only consist of one Docker image. Currently, the App Center does not support multiple containers linked together. It does not support docker-compose. There is only one DockerImage and this has to provide the full software stack.
Depending on DockerVolumes, the image is created with the -v option. Depending on PortsExclusive and PortsRedirection, the image is created with the -p option. Depending on the env and the univention-config-registry-variables file, the image is created with the -e option. But other than that, the actual docker create command cannot be adapted by the App provider. The App Center does not support --cap-add, nor does it support --net.
If your App needs a feature that the App Center does not (yet) provide, contact us. We will try to find a workaround or maybe we add it in a software update.