more maintainer glory

This commit is contained in:
decentral1se 2022-02-03 21:17:18 +01:00
parent 3013d49fc5
commit 2cff469151
Signed by untrusted user: decentral1se
GPG Key ID: 03789458B3D0C410
2 changed files with 152 additions and 18 deletions

View File

@ -4,7 +4,7 @@ title: Packaging handbook
## Create a new recipe
You can run `abra recipe new <recipe>` to generate a new `~/.abra/recipes/<recipe>` repository. See the [maintainers tutorial](/maintainers/tutorial) for help on getting started with packaging.
You can run `abra recipe new <recipe>` to generate a new `~/.abra/recipes/<recipe>` repository. The generated repository is a copy of [`coop-cloud/example`](https://git.coopcloud.tech/coop-cloud/example).
## How are recipes are versioned?
@ -140,7 +140,7 @@ In the root of your recipe repository, run the following (if the folder doesn't
mkdir -p releases
```
And then simply create a text file which corresponds to the version release, e.g. `1.1.0+5.9.0` and write some notes. `abra` will show these when another operator runs `abra app deploy` / `abra app upgrade`.
And then create a text file which corresponds to the version release, e.g. `1.1.0+5.9.0` and write some notes. `abra` will show these when another operator runs `abra app deploy` / `abra app upgrade`.
## Generate the recipe catalogue
@ -205,41 +205,161 @@ If you write your own entrypoint, it needs to be specified in the `config` secti
I.e. `compose.smtp.yml`. These are used to provide non-essential functionality such as (registration) e-mails or single sign on. These are typically loaded by specifying `COMPOSE_FILE="compose.yml:compose.smtp.yml"` in your app `.env` configuration. Then `abra` learns to include these optional files at deploy time. `abra` uses the usual `docker-compose` configuration merging technique when merging all the `compose.**.yml` files together at deploy time.
### Docker configs
### Compose configs
If you look at a `compose.yml` file 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.`
## Enable healthchecks
TODO.
A healthcheck is an important and often overlooked part of the recipe configuration. It is part of the configuration that the runtime uses to figure out if a container is really up-and-running. You can tweak what command to run, how often and how many times to try until you assume the container is not up.
There are no real univesal configs and most maintainers just pick up what others are doing and try to adapt. There is some testing involved to see what works well. You can browse the existing recipe repositories and see from there.
You'll often find the same one used for things like caches & supporting services, such as Redis:
```yaml
healthcheck:
test: ["CMD", "redis-cli", "ping"]
```
If you're just starting off with packaging a recipe, you can use `healthcheck: disable` until you have something working. It's definitely advised to work out your healthcheck as a last step, it can be a bit tricky.
`abra app errors -w <domain>` will show what errors are being reported from a failing healtcheck setup.
## Tuning deploy configs
TODO.
A bit like healtchecks, there is no universal setup. A good default seems to be the following configuration:
```yaml
deploy:
update_config:
failure_action: rollback
order: start-first
rollback_config:
order: start-first
restart_policy:
max_attempts: 3
```
The `start-first` setting ensures that the container runtime tries to start up the new container and get it running before switching over to it.
Setting a restart policy is also good so that the runtime doesn't try to restart the container forever.
Best to [read](https://docs.docker.com/engine/reference/builder/#healthcheck) [the docs](https://docs.docker.com/compose/compose-file/compose-file-v3/#healthcheck) on this one.
## Tuning resource limits
TODO.
If you don't place resource limits on your app it will assume it can use the entire capacity of the server it is on. This can cause issues such as OOM eerors for your entire swarm.
See the [Docker documentation](https://docs.docker.com/config/containers/resource_constraints/) to get into this topic and check the other recipes to see what other maintainers are doing.
## Enable A+ SSL ratings
TODO.
If you want to get the highest rating on SSL certs, you can use the following traefik labels which use a tweaked Traefik configuration.
```yaml
- "traefik.http.routers.traefik.tls.options=default@file"
- "traefik.http.routers.traefik.middlewares=security@file"
```
See [this PR](https://git.coopcloud.tech/coop-cloud/traefik/pulls/8/files) for the technical details
## Thread environment variables
TODO.
When you define an environment variable in a `.env.sample` for a recipe, such as:
## Entrypoint hacks
```bash
FOO=123
```
TODO.
And you pass this via the `environment` stanza of a service config in the recipe like so:
```yaml
service:
app:
environment:
- FOO
```
Then your environment variable will be threaded into the running app at deploy time. If you run `abra app run <domain> app env | grep FOO` then you'll see it exposed.
You can also access it in your configs using the following syntax:
```go
{{ env "FOO" }}
```
## Entrypoints
### Custom entrypoints
They can be useful to install additional dependencies or setup configuration that upstream doesn't have or want to have.
Here's a trimmed down config, the general idea is to create a new config and insert it into the container at a specific location and then have the compose configuration tell the underlying image to run this new script as the entrypoint.
You typically don't want to completely override the upstream entrypoint of the image you're using, so in the last line of your entrypoint, you can run the upstream entrypoint.
```yaml
services:
app:
entrypoint: /docker-entrypoint.sh
configs:
- source: app_entrypoint
target: /docker-entrypoint.sh
mode: 0555
configs:
app_entrypoint:
name: ${STACK_NAME}_app_entrypoint_${APP_ENTRYPOINT_VERSION}
file: entrypoint.sh.tmpl
template_driver: golang
```
### Exposing secrets
TODO.
Sometimes apps expect to find a secret in their environment which is not possible with the default compose configuration approach. This requires a hack using an entrypoint. The hack is basically this (assume we want to expose a secret called `db_password`):
### /bin/bash is missing?
1. Setup the secret as per usual in `secrets: ...`
2. Pass a `DB_PASSWORD_FILE=/run/secrets/db_password` in via the `environment: ...`
3. Create an entrypoint and inside it, use the following boilerplate.
TODO.
```bash
#!/bin/bash
set -e
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then
val="${!var}"
elif [ "${!fileVar:-}" ]; then
val="$(< "${!fileVar}")"
fi
export "$var"="$val"
unset "$fileVar"
}
```
And then to expose your secret to the container environment use the following in a line below this function:
```bash
file_env "DB_PASSWORD"
```
### `/bin/bash` is missing?
Sometimes the containers don't even have Bash installed on them. You had better just use `/bin/sh` or, in your entrypoint script, install Bash :upside_down: The entrypoint secrets hack listed above doesn't work in this case (as it requires Bash), so instead you can just do `export FOO=$(cat /run/secrets/<secret-name>)`.
## Referening service names in configs?

View File

@ -4,16 +4,26 @@ title: New maintainers tutorial
## Package your first recipe
Packaging a recipe is basically knowing a bag of about 20 tricks. Once you learn them all, there is nothing more to learn. It can seem daunting at first but it's simple and easy to do once you know the tricks.
### Overview
Let's take as an example, [Matomo web analytics](https://matomo.org/). We'll be making a Docker "swarm-mode" `compose.yml` file. Here's an overview of the options you'd have to package Matomo:
Packaging a recipe is basically knowing a bag of about 20 tricks. Once you learn them, there is nothing more to learn. It can seem daunting at first but it's simple and easy to do once you know the tricks.
The nice thing about packaging is that only one person has to do it and then we all benefit. We've seen that over time, the core of the configuration doesn't really change. New options and versions might come but the config remains quite stable. This is good since it meand that your packaging work stays relevant and useful for other maintainers & operators as time goes on.
### Making a plan
The idea scenario is when the upstream project provides both the packaged image and a compose configuration which we can build from. If you're in luck, you'll typically find a `Dockerfile` and a `docker-compose.yml` file in the root of the upstream Git repository for the app.
- **Tired**: Write your own image and compose file from scratch
- **Wired**: Use someone else's image (& maybe compose file)
- **Inspired**: Upstream image, someone else's compose file
- **On fire**: Upstream image, Upstream compose file
- **On fire**: Upstream image, upstream compose file
Luckily, 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. That typically also means "not for production" but we can still use it as a solid base.
### Writing the `compose.yml`
Let's take a practical example, [Matomo web analytics](https://matomo.org/). We'll be making a Docker "swarm-mode" `compose.yml` file.
Luckily, 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:
@ -40,6 +50,8 @@ Open the `compose.yml` in your favourite editor and have a gander &#129442;. The
The resulting `compose.yml` is available [here](https://git.autonomic.zone/coop-cloud/matomo/src/branch/main/compose.yml).
### Test deployment
!!! 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 operators tutorial](/operators/tutorial) if you need help setting one up.
@ -64,4 +76,6 @@ abra app deploy swarm.example.com
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).
Congrats, you've packaged your first recipe! You've probably got more questions, check out the [maintainers handbook](/maintainers/handbook)!
### Finishing up
You've probably got more questions, check out the [maintainers handbook](/maintainers/handbook)!