gw-bin 0.4.2

Watch git repositories, pull changes and run commands on the new files
Documentation
+++
title = "Docker Compose"
weight = 4
+++

# Docker Compose

`gw` plays very well with `docker`, especially `docker compose`. You can use `gw` to build the Docker image and then stop and recreate the container. It can be done with `docker`, but it is recommended to do it with `docker compose` as it will handle the whole lifecycle of build, stop and restart.

## Project configuration

Make sure to have a `docker-compose.yaml` file in the root directory. It can start existing containers or build images from the local files.

> **Note**: if you build docker images locally, you save the storage and transfer costs of the docker image repository.

Since it is also a file in your git repository, it basically doubles as an infrastructure-as-a-code. You can modify the `docker compose` setup (e.g. add another dependency, for example cache), commit and have the changes reflected in your infrastructure immediately.

## gw configuration

Just simply point to your repository and run `docker compose up`. It will restart your containers and apply any new changes.

```sh
gw /path/to/repo -s 'docker compose up -d'
```

If you are building your containers, add `--build`:

```sh
gw /path/to/repo -s 'docker compose up -d --build'
```

## Systemd unit

One neat way to use `docker-compose` is to use it together with [systemd units](/usage/systemd). They play very nicely together
because `docker-compose` is hard to be containerized, but this way it can run in the background on the host and update automatically.

To create a systemd unit, you can use the [systemd usage guide](/usage/systemd#usage), but add this to the unit file (e.g. `/etc/systemd/system/gw.service`):

```ini
# /etc/systemd/system/gw.service
[Unit]
Description = Autorestartable docker-compose for application
After = NetworkManager-wait-online.service network.target docker.service
PartOf = docker.service

[Service]
Type = simple
ExecStart = /usr/local/bin/gw /path/to/repo -v -p '/usr/bin/docker compose -f /path/to/repo/docker-compose.yml up --build'

[Install]
WantedBy = default.target
```

This will rebuild your containers in the directory, every time there is a change.

### Template systemd unit

If you have many applications that you want to autorestart with `docker-compose`, it might make sense to use a [template systemd unit](https://fedoramagazine.org/systemd-template-unit-files/).
These are units that have a pattern (`%I`) in their unit files, which you can call multiple times with multiple configurations.

For example if you have a `/path/to/repos/app1` and `/path/to/repos/app2`, you can create a generic systemd unit such as this
(make sure that the filename ends with `@`):

```ini
# /etc/systemd/system/gw@.service
[Unit]
Description = Autorestartable docker-compose for %I
After = NetworkManager-wait-online.service network.target docker.service
PartOf = docker.service

[Service]
Type = simple
WorkingDirectory = /path/to/repos/%I
ExecStart = /usr/local/bin/gw /path/to/repos/%I -vv -p '/usr/bin/docker compose -f /path/to/repos/%I/docker-compose.yml -p %I up --build'

[Install]
WantedBy = default.target
```

You can call it using the app name after a `@`, like `gw@app1` and `gw@app2`, and the `%I` will be automatically replaced with `app1` and `app2`.
So in this case `systemctl start gw@app1` will start a `docker-compose` in `/path/to/repos/app1` using the `/path/to/repos/app1/docker-compose.yml` file
with the project name `app1`.

You can extend these further by simply adding new directories and starting an automaticly deploying process with one line of code.