5.4 KiB
Containers
Containers and pods (a collection of containers in the same namespace) enables easy and secure management of hosted applications. In this case podman
has been chosen to configure the pods and containers as it makes it possible to perform this task without root. Furthermore, the management of these pods which consists of automatic backups of the volumes and databases and automatically starting and updating at reboots will be performed by runsvdir
.
Podman
Install podman
with
# apk add podman
Rootless podman
needs cgroups
to operate
# rc-update add cgroups default
Set up the network namespace configuration for the user
# modprobe tun
# echo tun >> /etc/modules-load.d/tun.conf
# for i in subuid subgid; do
> echo <username>:100000:65536 >> /etc/$i
> done
Run the following container to verify if everything works
$ podman run --rm hello-world
Management of containers
To run a single container create ~/.config/sv/<container-name>/run
#!/bin/sh
command="/usr/bin/podman"
command_args="run --replace --rm --name=<container-name> --network=pasta"
env="<container-envs>"
ports="<container-ports>"
mounts="<container-mounts>"
image="<container-image>"
exec 2>&1
exec $command $command_args $env $ports $mounts $image
Make it executable and link it to the service directory
$ chmod +x ~/.config/sv/<container-name>/run
$ ln -s <home>/.config/sv/<container-name> <home>/.local/service
Management of pods
Necessary to check if a pod is running create ~/.local/bin/checkpod
#!/bin/sh
. ./conf
exec 2>&1
state=0
while [ $state == 0 ]
do
sleep 10
$command pod inspect ${name}-pod | grep -q '"State": "Running"' || state=1
done
and make it executable with
$ chmod +x ~/.local/bin/checkpod
To run a pod configured with ~/.config/pods/<pod-name>/<pod-name>.yml
, see alpine-server for examples, create ~/.config/sv/<pod-name>/conf
name="<pod-name>"
home="<home>"
pod_location="${home}/.config/pods/<pod-name>"
bin_location="${home}/.local/bin"
command="/usr/bin/podman"
command_args="--replace --network=pasta"
create ~/.config/sv/<pod-name>/run
#!/bin/sh
. ./conf
exec 2>&1
$command kube play $command_args ${pod_location}/${name}-pod.yml
exec ${bin_location}/checkpod
and create ~/.config/sv/<pod-name>/finish
#!/bin/sh
. ./conf
exec 2>&1
exec $command kube down ${pod_location}/${name}-pod.yml
Make both run
and finish
executable
$ chmod +x ~/.config/sv/<pod-name>/run
$ chmod +x ~/.config/sv/<pod-name>/finish
Finally, link the pod to the service directory
$ ln -s <home>/.config/sv/<pod-name> <home>/.local/service
Backup of volumes and databases
To back up volumes of containers and postgresql databases create ~/.local/bin/dump
#!/bin/sh
command="/usr/bin/podman"
# Dumps databases
postgres_databases="<list-of-postgres-databases>"
for database in $postgres_databases
do
exec $command exec -it ${database}-pod-postgres sh -c "pg_dumpall -U postgres | gzip > /dump/${database}.sql.gz"
done
# Exports volumes
volumes="<list-of-volumes>"
for volume in $volumes
do
exec $command volume export $volume --output <home>/.volumes/${volume}.tar
done
Make it executable
$ chmod +x ~/.local/bin/dump
Automate it with snooze
# apk add snooze
and create ~/.config/sv/dump/run
#!/bin/sh
exec 2>&1
exec snooze -H* /home/neutrino/.local/bin/dump
which executes dump every hour.
Make it executable and link it to the service directory
$ chmod +x ~/.config/sv/dump/run
$ ln -s <home>/.config/dump <home>/.local/service
Then a duplicati
container can be used to back up the .dump
and .volumes
folders to another server if necessary.
The volumes and postgresql databases can be reloaded with ~/.local/bin/load
#!/bin/sh
command="/usr/bin/podman"
# Loads dumped databases
postgres_databases="<list-of-postgres-databases>"
for database in $postgres_databases
do
exec $command exec -it ${database}-pod-postgres sh -c "gunzip -c /dump/${database}.sql.gz | psql -U postgres"
done
# Imports volumes
volumes="<list-of-volumes>"
for volume in $volumes
do
exec $command volume import $volume <home>/.volumes/${volume}.tar
done
Make it executable
$ chmod +x ~/.local/bin/load
Reverse proxy
While it would be more optimal to run a reverse proxy in a container and link the network namespaces to this container, this is unfortunately not yet possible with pasta
user network namespaces. Therefore, the reverse proxy should be run in front of the containers and thus on the system.
Install caddy with
# apk add caddy libcap
Give caddy privileges to access all ports, to be able to run caddy rootless
# setcap cap_net_bind_service=+ep /usr/sbin/caddy
Create ~/.config/caddy/caddyfile
according to your needs. Then convert it with the following to make it persistent.
$ caddy adapt -c ~/.config/caddy/caddyfile -p > ~/.config/caddy/caddy.json
Create the service ~/.config/sv/caddy/run
#!/bin/sh
command="/usr/sbin/caddy"
command_args="run"
exec ps | grep '[${command}] ${command_args}' > /dev/null
if [$? != 0]; then
exec 2>&1
exec $command $command_args
fi
Make it executable and link it to the service directory
$ chmod +x ~/.config/sv/caddy/run
$ ln -s <home>/.config/sv/caddy <home>/.local/service