A Dagger module for managing and deploying Docker Compose manifests through SSH connection.
- Initiate a dagger project.
- Create
manifests
directory under root fo the project directory and puts all docker compose and all related files there. You can create as many subfolder as needed. - Create
.ssh
folder that at minimum contains ssh private key namedid_rsa
. - Import and unify the
#DDCompose.plan
withdagger.#Plan
- Fill
#DDCompose.manifests
with information related to all manifests inmanifests
directory. See #Manifest for all avaialable fields. - Execute
dagger do deploy
to deploy all defined manifests.
Suppose there is an awesome-service
with the following docker compose related files:
$ find manifests
manifests
manifests/host1.example.test/awesome-service
manifests/host1.example.test/awesome-service/settings.conf
manifests/host1.example.test/awesome-service/docker-compose.yml
To deploy this manifest to host1.example.test
and put all the manifest files inside /opt/docker/awesome-service
, the cue file should look like this
package main
import (
"dagger.io/dagger"
"github.com/telkomindonesia/ddcompose"
)
dagger.#Plan & (ddcompose.#DDCompose & { manifests: [
{
name: "awesome-service"
path: "host1.example.test/awesome-service"
remoteHost: "host1.example.test"
remotePath: "/opt/docker/awesome-service"
},
]}).plan
Checkout examples for more sample on how to use this module.
The deploy
actions is composed with sub-actions structured in the following manner:
deploy
:<manifest name>
:<manifest remoteHost>
:<manifest remotePath>
:<manifest>
This allow for controlling which manifest(s) to be deployed. For example:
dagger do deploy awesome-service
will deploy all manifest namedawesome-service
.dagger do deploy awesome-service host1.example.test
will deploy all manifest namedawesome-service
only tohost1.example.test
.dagger do deploy awesome-service host1.example.test /opt/docker/awesome-service
will deploy all manifest namedawesome-service
only tohost1.example.test
and only to path/opt/docker/awesome-service
.
Since 0.8.0, synchronization is done using rsync with --delete
flag. Exclusion is possible by creating .rsync-exclude
file inside the root dir of each manifest path, which will be passed as argument to --exclude-from
flag.
Under the hood, the deploy
action wraps docker compose
command to deploy the manifest. To add additional config for the docker client (such as authentication for remote registry), set #DDCompose.docker.config
to true
and put the config inside .docker/config.json
.
It is also possible to deploy the manifest to the local host where the command is executed. To do this, do not set the remoteHost
remotePath
attribute of the manifest.
In this mode, a docker volume will be generated that will contain the modified manifest filesß. This volume can then be used in docker-compose by using DDCOMPOSE_MANIFEST_VOLUME
env variable, for example
services:
certain-service:
volumes:
- ${DDCOMPOSE_MANIFEST_VOLUME:-.}:/src
The fenvname
action is used to generate a text file containing a list of files or folders inside manifests
folders with their respective generated-variable name. This variable name can be included in docker compose file to force recreate the related container when the content of the correlated file or folder changes. See examples for more detail on how to include the fenv inside docker compose file.
The module support automatic file decryption for all files with __sops__
prefix encountered inside manifests
dir using sops and age encryption. To enable this feature, set #DDCompose.sops.age
to true
and put the private key inside .sops/age/keys.txt
file.
An optional action named build
can be enabled by setting #DDCompose.builders
to true
which allow an execution of terraform scripts inside builders
folder. During execution, the terraform scripts will have access to the manifests directory whose path can be accessed by defining a variable named manifests_dir
.
If #DDCompose.sops.config
is set to true
(which require .sops.yaml
file to be available on the root directory), then terraform.tfstate
will be encrypted as __sops__terraform.tfstate
after each execution and the original terraform.tfstate
will be deleted. See examples for more detail.