https://github.com/djuuu/ansible-role-docker-project
Base role for Docker Compose projects
https://github.com/djuuu/ansible-role-docker-project
ansible ansible-role docker docker-compose
Last synced: 2 months ago
JSON representation
Base role for Docker Compose projects
- Host: GitHub
- URL: https://github.com/djuuu/ansible-role-docker-project
- Owner: Djuuu
- License: other
- Created: 2024-11-03T15:54:46.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-01-11T22:57:44.000Z (over 1 year ago)
- Last Synced: 2025-02-24T03:57:02.346Z (over 1 year ago)
- Topics: ansible, ansible-role, docker, docker-compose
- Homepage:
- Size: 36.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Ansible Role: Docker-project
============================
Base role for Docker Compose projects.
Requirements
------------
- Docker CLI with Docker compose plugin 2.18.0 or later
- Ansible >=2.11.0
Role Variables
--------------
Common Docker projects variables:
### Project name
```yaml
docker_project_name: # example-project
```
Project name should be set in concrete roles using this role as a base.
This variable is derived into the following 2 variables:
- `docker_project_slug` _(slugified project name, with `-` separators)_
Determines:
- directory where project will be installed
- default service subdomain
- misc. Traefik keys (service & router, middleware prefix)
- `docker_project_prefix` _(slugified project name, with `_` separators)_
Used as [dynamic variables](#dynamic-variables) prefix
Implementation example:
* `example-role/defaults/main.yml`
```yaml
example_role_project_name: example
```
* `example-role/vars/main.yml`
```yaml
docker_project_name: "{{ example_role_project_name }}"
```
### Base directory for Docker projects
```yaml
docker_projects_path: # /var/apps
```
### Base domain suffixes
```yaml
# Local machine domain
local_base_domain: internal
# Exposed service domain
exposed_base_domain: # example.net
```
These domains suffixes are used to build Traefik default rule in
[djuuu.traefik_docker](https://github.com/Djuuu/ansible-role-traefik-docker),
along with optional `{{ docker_project_prefix }}_traefik_subdomain` [dynamic variable](#dynamic-variables).
See:
- https://github.com/Djuuu/ansible-role-traefik-docker/blob/main/templates/docker-compose.yml.j2#L48-L52
- https://doc.traefik.io/traefik/providers/docker/#defaultrule
### Additional allowed origins
```yaml
docker_project_allowed_origins: []
# - https://dashboard.example.net
```
Used in `csp-add-frame-ancestors@file` and `{{ docker_project_slug }}-cors@docker` middlewares from
[djuuu.traefik_docker](https://github.com/Djuuu/ansible-role-traefik-docker) role.
### Dynamic variables
Variables constructed from `docker_project_name` value can be used to configure:
- _`{{ docker_project_prefix }}`_**`_restart`**
Container restart policy (default: `"unless-stopped"`)
* Traefik integration (see [djuuu.traefik_docker](https://github.com/Djuuu/ansible-role-traefik-docker) role)
- _`{{ docker_project_prefix }}`_**`_traefik_enable`**
Should Traefik expose service? (default: `false`)
- _`{{ docker_project_prefix }}`_**`_traefik_domain`**
Domain used to expose service (note: takes precedence over `_traefik_subdomain`)
- _`{{ docker_project_prefix }}`_**`_traefik_subdomain`**
Subdomain used to expose service (concatenated with `local_base_domain` / `exposed_base_domain`).
- _`{{ docker_project_prefix }}`_**`_traefik_router_service`**
Service name targeted by Traefik router
- _`{{ docker_project_prefix }}`_**`_traefik_loadbalancer_server_port`**
Port targeted by Traefik router
- _`{{ docker_project_prefix }}`_**`_traefik_loadbalancer_server_scheme`** (default: `"http"`)
Scheme targeted by Traefik router
- _`{{ docker_project_prefix }}`_**`_traefik_entrypoints`** (default: `"https"`)
Traefik router entrypoints
- _`{{ docker_project_prefix }}`_**`_traefik_middlewares`**
Traefik router middlewares
- _`{{ docker_project_prefix }}`_**`_traefik_define_internal_route`** (default: `false`)
Should an internal route be defined (restricted to `traefik_internal_networks`)
- _`{{ docker_project_prefix }}`_**`_traefik_middlewares_internal`**
Traefik router middlewares applied on internal route
- _`{{ docker_project_prefix }}`_**`_access_control_max_age`** (default: `100`)
- _`{{ docker_project_prefix }}`_**`_access_control_allow_methods`** (default: `"*"`)
- _`{{ docker_project_prefix }}`_**`_access_control_allow_headers`** (default: `"*"`)
CORS settings when `{{ docker_project_slug }}-cors@docker` middleware is enabled
- _`{{ docker_project_prefix }}`_**`_traefik_custom_labels`**
Additional Traefik labels
* Network
- _`{{ docker_project_prefix }}`_**`_network_mode`** (default: `bridge`)
Network mode (ex: `host`)
- _`{{ docker_project_prefix }}`_**`_network_ipv4_subnet`**
- _`{{ docker_project_prefix }}`_**`_network_ipv6_subnet`**
Optional default network IP subnets
* Additional docker compose options
- _`{{ docker_project_prefix }}`_**`_service_additional_options`**
Main service additional docker-compose options (ex: cpu_shares, deploy, ...)
- _`{{ docker_project_prefix }}`_**`_service_additional_labels`**
Main service additional docker-compose labels (ex: wud.tag.include, ...)
- _`{{ docker_project_prefix }}`_**`_compose_additional_options`**
Top-level additional docker-compose options
When set, dynamic variables are set into equivalent variables prefixed with `docker_project_`
(ex: `docker_project_traefik_domain`, `docker_project_compose_additional_options`, etc.)
### Generated variables
These variables are computed from other variables and can be used in roles:
- `docker_project_path`=`"{{ docker_projects_path }}/{{ docker_project_slug }}"`
Target directory of current project installation.
Should be used in depending role.
- `traefik_domains`
list of fully qualified domains used to expose service (internal use)
ex: `['hello-world.example.net', 'hello-world.local']`
- `traefik_domain_label`
Traefik routing rule label when using domain configuration (internal use)
ex: ``traefik.http.routers.hello-world.rule: Host(`hello-world.example.net`)``
- `traefik_subdomain_label`
Traefik routing rule label when using subdomain configuration (internal use)
ex: `net.example.subdomain: hello-world`
- **`traefik_project_base_host_rules`**
Host rules used in Traefik routing rules.
Can be useful when adding custom routing rules (`{{ docker_project_prefix }}_traefik_custom_labels`)
ex: ``(Host(`hello-world.example.net`) || Host(`hello-world.local`))``
- **`traefik_project_base_labels`**
Generated Traefik labels.
Should be added to the `labels` section of your service Docker Compose configuration.
ex:
```yaml
traefik.enable: true
net.example.subdomain: hello-world
# ...
```
- **`docker_project_service_network_options`**
Service `network_mode` or `networks` attributes.
ex:
```yaml
network_mode: host # from `docker_project_network_mode` dynamic var
```
or:
```yaml
networks:
- default
- other # from `docker_project_additional_networks` dynamic var
```
- **`docker_project_default_network`**
Generated default network configuration.
Should be added to the `networks` section of your Docker Compose configuration.
ex:
```yaml
default:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.18.0.0/16
- subnet: 2001:db8:0001:0001::/64
enable_ipv6: true
```
### Other variables
```yaml
# Path to the Docker CLI (Community.Docker modules argument)
# https://docs.ansible.com/ansible/latest/collections/community/docker/index.html
docker_cli:
# Path to the Docker Compose CLI (when using legacy docker-compose plugin)
docker_compose_cli:
```
The following computed variables are available for convenience:
- `docker_cmd`:
uses `docker_cli` if set, or defaults to 'docker'
- `docker_compose_cmd`:
uses `docker_compose_cli` if set, or defaults to `{{ docker_cmd }} compose`
```yaml
pull: false
```
Pulls image before starting container in `compose-up` task (intended as extra var).
Example role implementation
---------------------------
Role example:
* `hello_world/meta/main.yml`
```yaml
galaxy_info:
role_name: hello_world
dependencies:
- name: djuuu.docker_project
src: https://github.com/Djuuu/ansible-role-docker-project
version: main
```
* `hello_world/defaults/main.yml`
```yaml
hello_world_project_name: hello-world
```
* `my-example/vars/main.yml`
```yaml
docker_project_name: "{{ hello_world_project_name }}"
```
* `hello_world/tasks/main.yml`
```yaml
## Init
- name: Ensure project directory exists
ansible.builtin.file:
path: "{{ docker_project_path }}"
state: directory
mode: '0755'
tags: ["init"]
## Configure
- name: Template docker-compose.yml
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ docker_project_path }}/docker-compose.yml"
mode: '0644'
validate: "{{ docker_compose_cmd }} -f %s config"
backup: true
## Run
- name: Start app
ansible.builtin.include_role: { name: djuuu.docker_project, tasks_from: compose-up }
```
* `hello_world/templates/docker-compose.yml.j2`
```yaml
name: {{ docker_project_slug }}
services:
hello_world:
image: hello-world
container_name: {{ docker_project_slug }}
restart: {{ docker_project_restart }}
{{ docker_project_service_network_options | indent(4) }}
{{ docker_project_service_additional_options | indent(4) }}
labels:
{{ traefik_project_base_labels | indent(6) }}
{{ docker_project_service_additional_labels | indent(6) }}
{{ docker_project_networks }}
{{ docker_project_compose_additional_options }}
```
Configuration example with dynamic vars:
* `host_vars/example/hello.yml`
```yaml
hello_world_project_name: "hey-there"
# Dynamic variables
hey_there_traefik_enable: true
hey_there_traefik_domain: example.net
hey_there_traefik_subdomain: hey
hey_there_traefik_router_service: hello
hey_there_traefik_loadbalancer_server_port: 1234
hey_there_traefik_entrypoints: http,https
hey_there_traefik_middlewares:
- "internal-access@file" # see djuuu.traefik_docker templates/dynamic-conf/middlewares/internal-access.yml.j2
- "csp-add-frame-ancestors@file" # see djuuu.traefik_docker templates/dynamic-conf/middlewares/csp-add-frame-ancestors.yml.j2
- "{{ docker_project_slug }}-cors@docker" # see tasks/_init_traefik_vars.yml
hey_there_access_control_max_age: 60
hey_there_access_control_allow_methods: "OPTIONS, HEAD, GET"
hey_there_access_control_allow_headers: "X-Custom-Header, Upgrade-Insecure-Requests"
hey_there_traefik_custom_labels: |-
hello-label: hey there
other-label: example
hey_there_network_mode: bridge
hey_there_additional_networks:
- example_net
hey_there_network_ipv4_subnet: 172.18.0.0/16
hey_there_network_ipv6_subnet: 2001:db8:0001:0001::/64
hey_there_service_additional_options: |
cpu_shares: 10
deploy:
resources:
limits:
memory: 128M
ports:
- "1234:1234"
hey_there_compose_additional_options: |
x-example:
title: This is an example
```
Dependencies
------------
None.
Some variables allow integration with:
- [djuuu.traefik_docker](https://github.com/Djuuu/ansible-role-traefik-docker)
Example Playbooks
-----------------
Role is not intended to be run as-is, but as a dependency in other roles.
However, there are some available tasks that can be used independently:
**`compose-ps`**
```yaml
- name: List Docker Compose projects status
hosts: all
gather_facts: false
vars:
docker_projects:
- my-project
- other-project
tasks:
- name: Docker compose ps
ansible.builtin.include_role:
name: djuuu.docker_project
tasks_from: compose-ps
vars:
docker_project_name: "{{ item.name | default(item) }}"
project_restart: "{{ item.restart | default(true) }}"
loop: "{{ docker_projects | default([]) }}"
```
**`compose-update`**
```yaml
- name: Update Docker Compose projects
hosts: all
gather_facts: false
vars:
docker_projects:
- "my-project"
- { name: "other-project", restart: false } # on-demand service without running container
tasks:
- name: Docker compose update
ansible.builtin.include_role:
name: djuuu.docker_project
tasks_from: compose-update
vars:
docker_project_name: "{{ item.name | default(item) }}"
docker_project_restart: "{{ item.restart | default(true) }}"
loop: "{{ docker_projects | default([]) }}"
- name: Docker system prune
ansible.builtin.include_role:
name: djuuu.docker_project
tasks_from: system-prune
```
**`compose-up`**
```yaml
- name: Start Docker Compose project
hosts: example
gather_facts: false
vars:
docker_project_name: my-project
tasks:
- name: Start app
ansible.builtin.include_role:
name: djuuu.docker_project
tasks_from: compose-up
```
**`compose-restart`**
```yaml
- name: Restart Docker Compose project
hosts: example
gather_facts: false
vars:
docker_project_name: my-project
tasks:
- name: Restart app
ansible.builtin.include_role:
name: djuuu.docker_project
tasks_from: compose-restart
```
**`system-prune`**
```yaml
- name: Docker system prune
hosts: all
gather_facts: false
tasks:
- name: Docker system prune
ansible.builtin.include_role:
name: djuuu.docker_project
tasks_from: system-prune
```
License
-------
Beerware License