<blockquote>
<p>How do i programmatically generate a docker-compose.yml file, based on which roles have been invoked?</p>
</blockquote>
<p>Reading your question, I don't think you need to do that. You're already deploying things on an explicit network; just make this external to the individual compose files. That is, perform the equivalent of:</p>
<pre><code>docker network create skyNet
</code></pre>
<p>And then modify your compose configuration to reference that as an <code>external</code> network:</p>
<pre><code>services:

  mariadb:
    image:                          mariadb/server:{{docker_mariadb_version}}
    container_name:                 mariadb
    restart:                        always        
    logging:
      driver:                       &quot;json-file&quot;
      options:
        max-size:                   &quot;10m&quot;
        max-file:                   &quot;5&quot;
    networks:
      - skyNet
    ports:
    - 127.0.0.1:3306:3306/tcp
    volumes:
      - /opt/mariadb/data:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD:        &quot;{{database_root_password}}&quot;

networks:
  skyNet:
    external: true
</code></pre>
<p>You can have each role manage it's own <code>docker-compose.yaml</code> file (and be responsible for bring up the stack). Because you're sharing a network between them, name lookups will work as expected between services, even though they're defined in different files.</p>

CC BY-SA 4.0
2024-05-31T20:23:42.370Z
Hey, recent downvoter. Consider leaving a comment; I would be happy to improve this answer.
larsks
CC BY-SA 4.0
2023-01-04T18:45:19.913Z
2023-01-04T18:45:19.913Z
larsks
<p>I am writing an Ansible playbook to deploy services to a clustered environment. There are 3 types of hosts (Application, Load balancer, database). Services are deployed via docker-compose on each host separately.</p>
<p>Example of playbook to deploy to a database host.</p>
<pre><code>- name:           Deploy database node.
  hosts:          databases
  become:         yes
  become_method:  sudo

  roles:
  - common
  - zabbix-agent
  - database
  - backup
</code></pre>
<p>The Ansible play needs to dynamically generate a docker-compose file based on which roles have been invoked on that host. So this example would need to generate a docker-compose which lists these roles.</p>
<p><strong>How do i programmatically generate a docker-compose.yml file, based on which roles have been invoked?</strong></p>
<p>I have considered:</p>
<ul>
<li>Ansible facts</li>
<li>Tags</li>
<li>global boolean variables [yuck]
but none of these seems like the right way to me.</li>
</ul>
<p>If there is a better approach to achieving my objective I'm open to any other suggestions too.</p>
<p><strong>Edit:</strong></p>
<blockquote>
<p>Can you explain what is in the container here?</p>
</blockquote>
<p>'common' role currently installs Docker and docker-compose onto the target host.
'database' starts a mariadb container.
'zabbix-agent' installs..well, zabbix agent on the host.
'backup' copies some shell scripts over.</p>
<blockquote>
<p>Is the database in the container, or is the container running next to
the database?</p>
</blockquote>
<p>the database is a mariadb Docker container. So my compose file will need to include a 'mariadb' section.</p>
<blockquote>
<p>What would a good docker-compose.yml look like for you?</p>
</blockquote>
<p>Good question. Something like this:</p>
<pre class="lang-yaml prettyprint-override"><code>version:                            '2.2'
services:

  terracotta:
    image:                          terracotta/terracotta-server-oss:5.5.1
    container_name:                 terracotta
    restart:                        always
    networks:
      - skyNet
    logging:
      driver:                       &quot;json-file&quot;
      options:
        max-size:                   &quot;10m&quot;
        max-file:                   &quot;5&quot;

  mariadb:
    image:                          mariadb/server:{{docker_mariadb_version}}
    container_name:                 mariadb
    restart:                        always        
    logging:
      driver:                       &quot;json-file&quot;
      options:
        max-size:                   &quot;10m&quot;
        max-file:                   &quot;5&quot;
    networks:
      - skyNet
    ports:
    - 127.0.0.1:3306:3306/tcp
    volumes:
      - /opt/mariadb/data:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD:        &quot;{{database_root_password}}&quot;


# Network
networks:
  skyNet:
    driver:                         bridge
</code></pre>
<p>I need to be able to need to be able to toggle which services are added to the compose file via Tags or something. Maybe I should change the phrasing of my question?</p>

CC BY-SA 4.0
2019-10-31T13:08:16.003Z
Can you explain what is in the container here? Is the database in the container, or is the container running next to the database? What would a good docker-compose.yml look like for you?
Bruce Becker
CC BY-SA 4.0
2024-05-31T16:25:06.397Z
Have you looked into fleet/helm?
James Shewey
<ansible><docker-compose><jinja>
How to programmatically generate docker-compose file?
user2818782
# How to programmatically generate docker-compose file?

(Asked by: username_0 on 2019-10-31)

I am writing an Ansible playbook to deploy services to a clustered environment. There are 3 types of hosts (Application, Load balancer, database). Services are deployed via docker-compose on each host separately.
Example of playbook to deploy to a database host.
- name:           Deploy database node.
  hosts:          databases
  become:         yes
  become_method:  sudo

  roles:
  - common
  - zabbix-agent
  - database
  - backup

The Ansible play needs to dynamically generate a docker-compose file based on which roles have been invoked on that host. So this example would need to generate a docker-compose which lists these roles.
How do i programmatically generate a docker-compose.yml file, based on which roles have been invoked?
I have considered:

Ansible facts
Tags
global boolean variables [yuck]
but none of these seems like the right way to me.

If there is a better approach to achieving my objective I'm open to any other suggestions too.
Edit:

Can you explain what is in the container here?

'common' role currently installs Docker and docker-compose onto the target host.
'database' starts a mariadb container.
'zabbix-agent' installs..well, zabbix agent on the host.
'backup' copies some shell scripts over.

Is the database in the container, or is the container running next to
the database?

the database is a mariadb Docker container. So my compose file will need to include a 'mariadb' section.

What would a good docker-compose.yml look like for you?

Good question. Something like this:
version:                            '2.2'
services:

  terracotta:
    image:                          terracotta/terracotta-server-oss:5.5.1
    container_name:                 terracotta
    restart:                        always
    networks:
      - skyNet
    logging:
      driver:                       "json-file"
      options:
        max-size:                   "10m"
        max-file:                   "5"

  mariadb:
    image:                          mariadb/server:{{docker_mariadb_version}}
    container_name:                 mariadb
    restart:                        always        
    logging:
      driver:                       "json-file"
      options:
        max-size:                   "10m"
        max-file:                   "5"
    networks:
      - skyNet
    ports:
    - 127.0.0.1:3306:3306/tcp
    volumes:
      - /opt/mariadb/data:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD:        "{{database_root_password}}"


# Network
networks:
  skyNet:
    driver:                         bridge

I need to be able to need to be able to toggle which services are added to the compose file via Tags or something. Maybe I should change the phrasing of my question?

**Tags:** ansible, docker-compose, jinja

> **Comments:**
> **username_1**: Can you explain what is in the container here? Is the database in the container, or is the container running next to the database? What would a good docker-compose.yml look like for you?  
> **username_2**: Have you looked into fleet/helm?  

---

## 1 answers

### Answer by username_3 on 2023-01-04. Score: -1

How do i programmatically generate a docker-compose.yml file, based on which roles have been invoked?

Reading your question, I don't think you need to do that. You're already deploying things on an explicit network; just make this external to the individual compose files. That is, perform the equivalent of:
docker network create skyNet

And then modify your compose configuration to reference that as an external network:
services:

  mariadb:
    image:                          mariadb/server:{{docker_mariadb_version}}
    container_name:                 mariadb
    restart:                        always        
    logging:
      driver:                       "json-file"
      options:
        max-size:                   "10m"
        max-file:                   "5"
    networks:
      - skyNet
    ports:
    - 127.0.0.1:3306:3306/tcp
    volumes:
      - /opt/mariadb/data:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD:        "{{database_root_password}}"

networks:
  skyNet:
    external: true

You can have each role manage it's own docker-compose.yaml file (and be responsible for bring up the stack). Because you're sharing a network between them, name lookups will work as expected between services, even though they're defined in different files.

> **Comments:**
> **username_3**: Hey, recent downvoter. Consider leaving a comment; I would be happy to improve this answer.  

---

