docs.coopcloud.tech/docs/maintainers/tutorial.md

156 lines
8.6 KiB
Markdown

---
title: New maintainers tutorial
---
## Package your first recipe
Let's take as an example, [Matomo web analytics](https://matomo.org/).
We'll be making a Docker "swarm-mode" `compose.yml` file.
- Tired: Write your own image and compose file
- Wired: Use someone else's image (& maybe compose file)
- Inspired: Upstream image, someone else's compose file
- On fire: Upstream compose file
I'm feeling lazy so, luckily for me, Matomo already has an example compose file in their repository.
Like a lot of compose files, it's intended for use with `docker-compose`, instead of "swarm mode", but it should be a good start.
First, let's create a directory with the files we need:
```
abra recipe new matomo
cd ~/.abra/apps/matomo
```
Then, let's download and edit the `docker-compose.yml` file:
```
mkdir matomo && cd matomo
wget https://raw.githubusercontent.com/matomo-org/docker/master/.examples/apache/docker-compose.yml -O compose.yml
```
Open the `compose.yml` in your favourite editor and have a gander 🦢. There are a few things we're looking for -- full list to come -- but some immediate changes could be:
1. Let's bump the version to `3.8`, to make sure we can use all the latest swarm coolness
2. We load environment variables separately via [abra](/overview/#command-line-tool), so we'll strip out `env_file`.
3. The `/var/www/html` volume definition on L21 is a bit overzealous; it means a copy of Matomo will be stored separately per app instance, which is a waste of space in most cases. We'll narrow it down according to the documentation -- here, the developers have been nice enough to suggest `logs` and `config` volumes instead, which is a decent start
4. The MySQL passwords are sent as variables which is fine for basic use, but if we replace them with Docker secrets we can keep them out of our env files if we want to publish those more widely.
5. The MariaDB service doesn't need to be exposed to the internet, so we can define an `internal` network for it to communicate with Matomo.
6. Lastly, we want to use `deploy.labels` and remove the `ports:` definition, to tell Traefik to forward requests to Matomo based on hostname and generate an SSL certificate.
The resulting `compose.yml` is available [here](https://git.autonomic.zone/coop-cloud/matomo/src/branch/main/compose.yml).
!!! note "Running Co-op Cloud server required!"
The rest of this guide assumes you have a Co-op Cloud server going -- we'll use `swarm.example.com`, but replace it with your own server address.
Head over to [the deployment guide](./deploy.md) if you need help setting one up.
Now, we're ready to create a testing instance of Matomo:
```
abra app new matomo --secrets \
--domain matomo.swarm.example.com \
--server swarm.example.com \
--app-name mygreatapp
```
Depending on whether you defined any extra environment variables -- we didn't so
far, in this example -- you might want to run `abra app mygreatapp config` to
check the configuration.
Otherwise, or once you've done that, go ahead and deploy the app:
```
abra app mygreatapp deploy
```
Then, open the `DOMAIN` you configured (you might need to wait a while for Traefik to generate SSL certificates) to finish the set-up. Luckily, this container is (mostly) configurable via environment variables -- if we want to auto-generate the configuration we can use a `config` and / or a custom `entrypoint` (see [`coop-cloud/mediawiki`](https://git.autonomic.zone/coop-cloud/mediawiki) for examples of both).
## How recipes are versioned
> We are still working on stabilising this workflow
We'll use an example to work through this. Let's use [Gitea](https://hub.docker.com/r/gitea/gitea).
The Gitea project maintains a version, e.g. `1.14.3`. This version uses the [semver](https://semver.org) strategy for communicating what type of changes are included in each version, i.e., if there is a breaking change, Gitea will release a new version as `2.0.0`.
However, there are other types of changes that can happen for a recipe. Perhaps the database image gets a breaking update or the actual recipe configuration changes some environment variable. This can mean that end-users of the recipe need to do some work to make sure their updates will deploy successfully.
Therefore, we maintain an additional version part, in front of the project version. So, the first release of the Gitea recipe in the Co-op Cloud project has the version of `1.0.0+1.14.3-rootless`. This `x.y.z+` is the version part that the recipe maintainer manages. If a new available Gitea version comes out as `1.15-rootless` then the recipe maintainer will publish `1.1.0+1.15-rootless` as this is a backwards compatible update, following semantic versioning.
In all cases, we follow the semver semantics. So, if we upgrade the Gitea recipe from `1.14.3-rootless` to `1.15.3-rootless`, we still publish `1.1.0+1.15.3-rootless` as our recipe version. In this case, we skipped a few patch releases but it was all backwards compatible, so we only increment the minor version part.
The commands uses for dealing with this logic in `abra` are:
- `abra recipe upgrade`: upgrade the image tags in the compose configs of a recipe
- `abra recipe tag`: publish a git tag for the recipe repo
- `abra recipe sync`: upgrade the deploy labels to match the new recipe version
## How to publish a new recipe version
!!! warning
Due to [a limitation](https://git.coopcloud.tech/coop-cloud/organising/issues/185) in the Git library we're using in `abra`, when tagging new releases, you **must** use annotated git tags (i.e. `git tag -a`) or `abra` won't be able to parse them correctly. On the up side, it is probably better to leave a message with your new Git tag anyway. So maybe this is just "best practice" ;)
> This process is very much still a work in progress...
- `abra recipe upgrade keycloak`
- `abra recipe sync keycloak "1.0.0+13.0.1"`
- `abra recipe release -c --cm "chore: first release" -t "first release" --push`
## Style guide
- Please don't use `&image` YAML repeat anchors on the `image: ...` key because our `recipe release` logic does not handle it (see [#172](https://git.autonomic.zone/coop-cloud/abra/issues/172))
## Recipe structure
A recipe is a git repository that contains instructions for creating stacks that abra can read and interpret. You'll see a couple of files there:
- [compose.yml](#composeyml) (required!)
- [.env.sample](#envsample) (required!)
- [abra.sh](#abrash)
- [entrypoint.sh](#entrypointsh)
- [other compose files](#other-compose-files)
- [other files](#other-files)
## compose.yml
this is a [compose specification](https://compose-spec.io/) compliant file that contains a list of:
- services
- secrets
- networks
- volumes
- configs
that describe what is needed to run a stack. Whenever you deploy an app, abra reads this file to cook the stack.
## .env.sample
this file is a skeleton for environmental variables that should be adjusted by the user. Examples include: domain or php extention list. Whenever you create a new app with `abra app new` this file gets copied to the ~/.abra/servers/server-domain/app-name.env and when you run `abra app config` you're editing this file.
## abra.sh
`abra.sh` provides shell functions for running non-standard deploy, restore, rollback, backup and upgrade. This is only needed for some packages (such as nextcloud or wordpress)
## entrypoint.sh
after docker creates the filesystem and copies files into a new container it runs what's called an entrypoint. This is usually a shell script that exports some variables and runs the application. Sometimes the vendor entrypoint doesn't do everything that we need it to do. In that case you can write your own entrypoint, do whatever you need to do and then run the vendor entrypoint. For a simple example check [entrypoint.sh for croc](https://git.coopcloud.tech/coop-cloud/croc/src/commit/2f06e8aac52a3850d527434a26de0a242bea0c79/entrypoint.sh). In this case, croc needs the password to be exported as an environmental variable called `CROC_PASS`, and that is exactly what the entrypoint does before running vendor entrypoint. If you write your own entrypoint, it needs to be specified in the `config` section of compose.yml.
## other compose files
i.e. compose.smtp.yml. These are used to provide non-essential functionality such as (registration) e-mails or single sign on.
## other files
if you look at compose.yml (or compose.\*.yml) and see a `configs` section, that means this compose file is putting files in the container. This might be used for changing default (vendor) configuration, such as this [fpm-tune.ini file](https://git.coopcloud.tech/coop-cloud/nextcloud/src/commit/28425b6138603067021757de28c639ad464e9cf8/fpm-tune.ini) used to adjust php-fpm.