From 180965a27dc698bc0b3b3571ddb895c37abc83dd Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Fri, 4 Jun 2021 17:30:16 +0200 Subject: Add post on docker-compose with openrc --- ...managing-docker-compose-projects-with-openrc.md | 195 +++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 src/_posts/2021-06-04-managing-docker-compose-projects-with-openrc.md (limited to 'src/_posts') diff --git a/src/_posts/2021-06-04-managing-docker-compose-projects-with-openrc.md b/src/_posts/2021-06-04-managing-docker-compose-projects-with-openrc.md new file mode 100644 index 0000000..76fe272 --- /dev/null +++ b/src/_posts/2021-06-04-managing-docker-compose-projects-with-openrc.md @@ -0,0 +1,195 @@ +--- +layout: post +tags: Gentoo Openrc Docker DockerCompose +title: Managing Docker Compose with OpenRC +social: + email: mailto:~tyil/public-inbox@lists.sr.ht&subject=managing docker compose with openrc +description: > + A quick overview of the method I've used to manage docker-compose based + projects/services with OpenRC. +--- + +On one of my machines, I host a couple services using `docker-compose`. I +wanted to start/restart/stop these using the default init/service manager used +on the machine, `openrc`. This would allow them to start/stop automatically +with Docker (which coincides with the machine powering on or off, +respectively). + +I've set this up through a single `docker-compose` meta-service. To add new +`docker-compose` projects to be managed, all I need to do for `openrc` +configuration is creating a symlink, and configure the path to the +`docker-compose.yaml` file. + +The meta-service lives at `/etc/init.d/docker-compose`, just like all other +services managed by `openrc`. This file is quite straightforward. To start off, +a number of variables are set and exported. + +{% highlight sh %} +name="$RC_SVCNAME" +description="OpenRC script for managing the $name docker-compose project" + +# Set default values +DOCKER_COMPOSE="${DOCKER_COMPOSE:-docker-compose} $DOCKER_COMPOSE_ARGS" + +COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-$name}" + +# Export all variables used by docker-compose CLI +export COMPOSE_PROJECT_NAME +export COMPOSE_FILE +export COMPOSE_PROFILES +export COMPOSE_API_VERSION +export DOCKER_HOST +export DOCKER_TLS_VERIFY +export DOCKER_CERT_PATH +export COMPOSE_HTTP_TIMEOUT +export COMPOSE_TLS_VERSION +export COMPOSE_CONVERT_WINDOWS_PATHS +export COMPOSE_PATH_SEPARATOR +export COMPOSE_FORCE_WINDOWS_HOST +export COMPOSE_IGNORE_ORPHANS +export COMPOSE_PARALLEL_LIMIT +export COMPOSE_INTERACTIVE_NO_CLI +export COMPOSE_DOCKER_CLI_BUILD +{% endhighlight %} + +One of the services I use is also configured with its own `external` network. I +want it to be created if it doesn't exist, to ensure that the service can start +up properly. I do *not* want it to be removed, so I left that out. + +{% highlight sh %} +# Set up (external) networks +for name in "${DOCKER_NETWORKS[@]}" +do + # Create the network if needed + if ! docker network ls | awk '{ print $2 }' | grep -q "$name" + then + einfo "Creating docker network '$name'" + docker network create "$name" > /dev/null + fi + + # Expose some variables for the networks + network_id="DOCKER_NETWORK_${name}_ID" + + declare -gx DOCKER_NETWORK_${name}_ID="$(docker network ls | awk '$2 == "'"$name"'" { print $1 }')" + declare -gx DOCKER_NETWORK_${name}_GATEWAY="$(docker network inspect "${!network_id}" | jq -r '.[0].IPAM.Config[0].Gateway')" + + unset network_id +done +{% endhighlight %} + +And lastly, there's the four simple functions to declare dependencies, +configure how to `start` or `stop`, and how to get the `status` of the service. + +{% highlight sh %} +depend() { + need docker +} + +start() { + $DOCKER_COMPOSE --project-directory "$COMPOSE_PROJECT_DIRECTORY" up -d +} + +status() { + $DOCKER_COMPOSE --project-directory "$COMPOSE_PROJECT_DIRECTORY" ps +} + +stop() { + $DOCKER_COMPOSE --project-directory "$COMPOSE_PROJECT_DIRECTORY" down +} +{% endhighlight %} + +Now, to actually create a service file to manage a `docker-compose` project, a +symlink must be made. I'll take my +[`botamusique`](https://github.com/azlux/botamusique) service as an example. + +{% highlight text %} +ln -s /etc/init.d/docker-compose /etc/init.d/botamusique +{% endhighlight %} + +This service can't start just yet, as there's no `$COMPOSE_PROJECT_DIRECTORY` +configured for it yet. For this, a similarly named file should be made in +`/etc/conf.d`. In here, any variable used by the service can be configured. + +{% highlight text %} +$EDITOR /etc/conf.d/botamusique +{% endhighlight %} + +In my case, it only pertains the `$COMPOSE_PROJECT_DIRECTORY` variable. + +{% highlight sh %} +COMPOSE_PROJECT_DIRECTORY="/var/docker-compose/botamusique" +{% endhighlight %} + +And that's it. For additional `docker-compose` projects I need to make only a +symlink and a configuration file. If I discover a bug or nuisance, only a +single file needs to be altered to get the benefit on all the `docker-compose` +services. + +For reference, here's the full `/etc/init.d/docker-compose` file. + +{% highlight sh %} +#!/sbin/openrc-run +# Copyright 2021 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +name="$RC_SVCNAME" +description="OpenRC script for managing the $name docker-compose project" + +# Set default values +DOCKER_COMPOSE="${DOCKER_COMPOSE:-docker-compose} $DOCKER_COMPOSE_ARGS" + +COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-$name}" + +# Export all variables used by docker-compose CLI +export COMPOSE_PROJECT_NAME +export COMPOSE_FILE +export COMPOSE_PROFILES +export COMPOSE_API_VERSION +export DOCKER_HOST +export DOCKER_TLS_VERIFY +export DOCKER_CERT_PATH +export COMPOSE_HTTP_TIMEOUT +export COMPOSE_TLS_VERSION +export COMPOSE_CONVERT_WINDOWS_PATHS +export COMPOSE_PATH_SEPARATOR +export COMPOSE_FORCE_WINDOWS_HOST +export COMPOSE_IGNORE_ORPHANS +export COMPOSE_PARALLEL_LIMIT +export COMPOSE_INTERACTIVE_NO_CLI +export COMPOSE_DOCKER_CLI_BUILD + +# Set up (external) networks +for name in "${DOCKER_NETWORKS[@]}" +do + # Create the network if needed + if ! docker network ls | awk '{ print $2 }' | grep -q "$name" + then + einfo "Creating docker network '$name'" + docker network create "$name" > /dev/null + fi + + # Expose some variables for the networks + network_id="DOCKER_NETWORK_${name}_ID" + + declare -gx DOCKER_NETWORK_${name}_ID="$(docker network ls | awk '$2 == "'"$name"'" { print $1 }')" + declare -gx DOCKER_NETWORK_${name}_GATEWAY="$(docker network inspect "${!network_id}" | jq -r '.[0].IPAM.Config[0].Gateway')" + + unset network_id +done + +depend() { + need docker +} + +start() { + $DOCKER_COMPOSE --project-directory "$COMPOSE_PROJECT_DIRECTORY" up -d +} + +status() { + $DOCKER_COMPOSE --project-directory "$COMPOSE_PROJECT_DIRECTORY" ps +} + +stop() { + $DOCKER_COMPOSE --project-directory "$COMPOSE_PROJECT_DIRECTORY" down +} +{% endhighlight %} -- cgit v1.1