Add service role
This commit is contained in:
@@ -1,5 +1,20 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
- name: Deprecation warning
|
||||||
|
debug:
|
||||||
|
msg: >
|
||||||
|
The role uumas.docker.container has been deprecated. You should switch to
|
||||||
|
uumas.docker.service instead. It has the following syntax changes:\n
|
||||||
|
* container name suffixes are separated by - instead of _\n
|
||||||
|
* May require updating hostnames in configs or database\n
|
||||||
|
* May require fixing any ports, database_passwords or
|
||||||
|
docker_vhost_domains variables to new syntax\n
|
||||||
|
* May require renaming database user and database for existing database
|
||||||
|
* docker_volume_type defaults to bind. Set it to named if you want to
|
||||||
|
continue using named volumes.\n
|
||||||
|
uumas.docker.container doesn't receive any updates and may be removed
|
||||||
|
after May 2024
|
||||||
|
|
||||||
- name: Container role initialization
|
- name: Container role initialization
|
||||||
import_tasks: init.yml
|
import_tasks: init.yml
|
||||||
|
|
||||||
|
|||||||
1
roles/service/README.md
Normal file
1
roles/service/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Sets up a docker service
|
||||||
28
roles/service/defaults/main.yml
Normal file
28
roles/service/defaults/main.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
docker_namespace: "{{ docker_service }}"
|
||||||
|
docker_service_suffix: ""
|
||||||
|
docker_volume_type: bind
|
||||||
|
docker_restart_policy: always
|
||||||
|
|
||||||
|
reverse_proxy_type: caddy
|
||||||
|
docker_proxy_target_protocol: http
|
||||||
|
|
||||||
|
docker_additional_env: {}
|
||||||
|
docker_additional_services: []
|
||||||
|
docker_database: none
|
||||||
|
docker_mounts: []
|
||||||
|
docker_network_mode: ""
|
||||||
|
docker_networks: []
|
||||||
|
docker_env: {}
|
||||||
|
|
||||||
|
docker_published_ports: []
|
||||||
|
docker_host_user: false
|
||||||
|
dockerfile: []
|
||||||
|
|
||||||
|
docker_mariadb_config: {}
|
||||||
|
docker_redis_persistence: false
|
||||||
|
docker_phpmyadmin_basicauth: true
|
||||||
|
docker_phpmyadmin_basicauth_users: {}
|
||||||
|
|
||||||
|
timezone: Etc/UTC
|
||||||
13
roles/service/handlers/main.yml
Normal file
13
roles/service/handlers/main.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Restart container
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ docker_service_name }}"
|
||||||
|
restart: true
|
||||||
|
when: not container_out.changed
|
||||||
|
|
||||||
|
- name: Ensure container running
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ docker_service_name }}"
|
||||||
|
state: started
|
||||||
|
when: not ansible_check_mode
|
||||||
216
roles/service/meta/argument_specs.yml
Normal file
216
roles/service/meta/argument_specs.yml
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
argument_specs:
|
||||||
|
main:
|
||||||
|
short_description: Docker service
|
||||||
|
description: "Sets up a docker service. Supports defining networks, building a custom image, setting up memcached, databases and a reverse proxy, creating a user on the host to run the container as, named volumes, bind mounts (either auto-created or existing)."
|
||||||
|
options:
|
||||||
|
docker_service:
|
||||||
|
description: "The name of the docker service (example: gitea)"
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
docker_namespace:
|
||||||
|
description: The namespace of the service. This can be used when multiple containers should be part of the service. Used as the default network, the name of the directory where bind mounts are created and the prefix for volume names.
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
default: "{{ docker_service }}"
|
||||||
|
docker_service_suffix:
|
||||||
|
description: "A suffix used to allow running multiple instances of the same service on a host. If docker_service is gitea and docker_service_suffix production, the service will be gitea-production"
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
docker_image:
|
||||||
|
description: "Docker image to use for the container. If dockerfile is defined, it will be used as base for locally built image (example: gitea/gitea:latest)"
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
dockerfile:
|
||||||
|
description: "A list of dockerfile instructions to add to the base image"
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
required: false
|
||||||
|
default: []
|
||||||
|
docker_host_user:
|
||||||
|
description: "If true, creates a user on the host for this service. The container will run as this user's uid/gid. Bind mount volumes will be owned by this user."
|
||||||
|
type: bool
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
|
||||||
|
docker_database:
|
||||||
|
description: "Database type to set up. It will be run in a docker container accessible to the service at host <service name (with -suffix if suffix is defined)>-db on default port."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
choices:
|
||||||
|
- postgres
|
||||||
|
- mariadb
|
||||||
|
- mongo
|
||||||
|
- none
|
||||||
|
default: none
|
||||||
|
database_passwords:
|
||||||
|
description: >
|
||||||
|
database_passwords[docker_service] is a string with the password used
|
||||||
|
for communication between the service and database. Required if
|
||||||
|
docker_database is postgres or mariadb. For mariadb, you can also
|
||||||
|
define database_passwords[docker_service + '_root'] if you want to
|
||||||
|
set a password for the mariadb root user
|
||||||
|
type: dict
|
||||||
|
required: false
|
||||||
|
docker_mariadb_config:
|
||||||
|
description: |
|
||||||
|
A dict specifying config for mariadb. For example
|
||||||
|
mysqld:
|
||||||
|
innodb_buffer_pool_size: '4G'
|
||||||
|
aria_pagecache_buffer_size': '4G'
|
||||||
|
would set
|
||||||
|
[mysqld]
|
||||||
|
innodb_buffer_pool_size = 4G
|
||||||
|
aria_pagecache_buffer_size = 4G
|
||||||
|
type: dict
|
||||||
|
required: false
|
||||||
|
default: {}
|
||||||
|
docker_additional_services:
|
||||||
|
description: "List of additional services to configure (in separate containers). These will be accessible with hostname <docker_service_name>[_suffix]_<additional_service>"
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
elements: str
|
||||||
|
choices:
|
||||||
|
- memcached
|
||||||
|
- redis
|
||||||
|
default: []
|
||||||
|
docker_redis_persistence:
|
||||||
|
description: Whether to save redis data to persistent storage
|
||||||
|
type: bool
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
docker_phpmyadmin_basicauth:
|
||||||
|
description: Whether to enable basicauth for phpmyadmin
|
||||||
|
type: bool
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
docker_phpmyadmin_basicauth_users:
|
||||||
|
description: Dict of users and their password hashes for phpmyadmin basic auth. Required if docker_phpmyadmin_basicauth is true and phpmyadmin is used.
|
||||||
|
type: dict
|
||||||
|
required: false
|
||||||
|
default: {}
|
||||||
|
|
||||||
|
docker_volume_type:
|
||||||
|
description: "Defines whether to use named volumes or bind mounts for mounts with name"
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
choices:
|
||||||
|
- named
|
||||||
|
- bind
|
||||||
|
default: named
|
||||||
|
docker_mounts:
|
||||||
|
description: "List of bind mounts or volumes to be mounted inside the container. Each element is a dict with path and exactly one of name, src or template"
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
default: []
|
||||||
|
elements: dict
|
||||||
|
options:
|
||||||
|
path:
|
||||||
|
description: "The path inside the container to mount at"
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
readonly:
|
||||||
|
description: "If true, volume will be mounted as read only inside the container. Only applies for named and src mounts."
|
||||||
|
type: bool
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
mode:
|
||||||
|
description: "Permissions for the created/templated directory. Defaults to '0644' for files, '0755' for directories. Doesn't apply for named volumes."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
name:
|
||||||
|
description: "If docker_volume_type is named, the name of the named volume to be mounted at path. If docker_volume_type is bind, the name of the folder to create under /opt/<service>[/suffix]/mounts/ and mount at path."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
src:
|
||||||
|
description: "Host path to bind mount inside the container."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
template:
|
||||||
|
description: "Name of template without .j2 extension. Will be templated at /opt/<service>[/suffix]/mounts/<template> and mounted read only inside the container."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
copypath:
|
||||||
|
description: "Name of file or directory to copy. Will be deployed from files/<copypath> to /opt/<service>[/suffix]/mounts/<copypath> and mounted read only inside the container."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
reverse_proxy_type:
|
||||||
|
description: "Defines which kind of reverse proxy to configure for the container. Traefik support is experimental."
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
choices:
|
||||||
|
- caddy
|
||||||
|
- traefik
|
||||||
|
- none
|
||||||
|
default: caddy
|
||||||
|
docker_image_http_port:
|
||||||
|
description: "The port for http listener inside the container. Will be mapped to the host port defined in ports. Required if reverse_proxy_type is not none."
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
docker_proxy_target_protocol:
|
||||||
|
description: "Protocol to use for proxy connection"
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
choices:
|
||||||
|
- http
|
||||||
|
- https
|
||||||
|
default: http
|
||||||
|
ports:
|
||||||
|
description: "ports[docker_service]['http'] or ports[docker_service]['https'] defines the port on which the container will listen on for reverse proxy connections. Required if reverse_proxy_type is caddy. If ports[docker_service]['phpmyadmin'] is defined and docker_database is mariadb, phpmyadmin will is installed."
|
||||||
|
type: dict
|
||||||
|
docker_vhost_domains:
|
||||||
|
description: "docker_vhost_domains[docker_service] is a list which defines which domains should be proxied to the container. Required if reverse_proxy_type is not none. docker_vhost_domains[docker_service + '-phpmyadmin'] is used for phpmyadmin"
|
||||||
|
type: dict
|
||||||
|
docker_published_ports:
|
||||||
|
description: "A list of published ports in docker format (<host listen address>:<host port>:<container port>)"
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
default: []
|
||||||
|
docker_networks:
|
||||||
|
description: A list of docker networks for docker service. Defaults to docker name
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
default:
|
||||||
|
- name: "{{ docker_namespace }}"
|
||||||
|
elements: dict
|
||||||
|
options:
|
||||||
|
name:
|
||||||
|
description: Name of the docker network
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
docker_env:
|
||||||
|
description: "A dict of environment variables for the container"
|
||||||
|
type: dict
|
||||||
|
required: false
|
||||||
|
default: {}
|
||||||
|
docker_entrypoint:
|
||||||
|
description: "Docker entrypoint as list of command and arguments"
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
elements: str
|
||||||
|
docker_command:
|
||||||
|
description: "Docker command as list of arguments or command and arguments"
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
elements: str
|
||||||
|
docker_memory:
|
||||||
|
description: Memory limit for the container
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
docker_restart_policy:
|
||||||
|
description: Restart policy of the service
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
default: always
|
||||||
|
docker_network_mode:
|
||||||
|
description: "Docker container network mode"
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
timezone:
|
||||||
|
description: "Timezone set in the TZ env var"
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
default: Etc/UTC
|
||||||
4
roles/service/meta/main.yml
Normal file
4
roles/service/meta/main.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- role: docker
|
||||||
18
roles/service/molecule/default/converge.yml
Normal file
18
roles/service/molecule/default/converge.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
- name: Converge
|
||||||
|
hosts: all
|
||||||
|
tasks:
|
||||||
|
- name: Nginx
|
||||||
|
include_role:
|
||||||
|
name: service
|
||||||
|
vars:
|
||||||
|
docker_service: nginx
|
||||||
|
docker_image: nginx
|
||||||
|
docker_image_http_port: 80
|
||||||
|
admin_email: test@example.com
|
||||||
|
ports:
|
||||||
|
nginx:
|
||||||
|
http: 28001
|
||||||
|
docker_vhost_domains:
|
||||||
|
nginx:
|
||||||
|
- localhost
|
||||||
15
roles/service/molecule/default/molecule.yml
Normal file
15
roles/service/molecule/default/molecule.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
driver:
|
||||||
|
name: podman
|
||||||
|
platforms:
|
||||||
|
- name: bullseye
|
||||||
|
image: git.uumas.fi/uumas/molecule-testbed:bullseye-docker
|
||||||
|
command: /lib/systemd/systemd
|
||||||
|
pre_build_image: true
|
||||||
|
privileged: true
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
83
roles/service/molecule/default/verify.yml
Normal file
83
roles/service/molecule/default/verify.yml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
---
|
||||||
|
- name: Verify
|
||||||
|
hosts: all
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: Ensure https://localhost returns 200
|
||||||
|
ansible.builtin.uri:
|
||||||
|
url: https://localhost
|
||||||
|
validate_certs: false
|
||||||
|
return_content: true
|
||||||
|
register: get_localhost
|
||||||
|
|
||||||
|
- name: Assert caddy responded on https://localhost
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: "(get_localhost.server | split(', '))[0] == 'Caddy'"
|
||||||
|
- name: Assert nginx responded on https://localhost
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: "(get_localhost.server | split(', '))[1].startswith('nginx')"
|
||||||
|
|
||||||
|
- name: Get /opt/nginx directory info
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: /opt/nginx
|
||||||
|
register: opt_nginx_stat
|
||||||
|
- name: Assert /opt/nginx doesn't exist
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: not opt_nginx_stat.stat.exists
|
||||||
|
msg: /opt/nginx should not have been created but it was
|
||||||
|
|
||||||
|
- name: Get host passwd nginx user
|
||||||
|
ansible.builtin.getent:
|
||||||
|
database: passwd
|
||||||
|
key: nginx
|
||||||
|
fail_key: false
|
||||||
|
- name: Assert nginx user does not exist
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: getent_passwd.nginx == None
|
||||||
|
msg: "nginx user should not exist but it does ({{ getent_passwd }})"
|
||||||
|
|
||||||
|
- name: Get nginx container info
|
||||||
|
community.docker.docker_container_info:
|
||||||
|
name: nginx
|
||||||
|
register: container_out
|
||||||
|
|
||||||
|
- name: Assert container port 80 forwarded to host 28001
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- "container_out.container.HostConfig.PortBindings['80/tcp'] is defined"
|
||||||
|
- "container_out.container.HostConfig.PortBindings['80/tcp'][0].HostPort == '28001'"
|
||||||
|
msg: "Container port 80 not correctly forwarded to host port. Port bindings output was {{ container_out.container.HostConfig.PortBindings }}"
|
||||||
|
|
||||||
|
- name: Assert container user not set
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: container_out.container.Config.User == ""
|
||||||
|
|
||||||
|
- name: Get container image info
|
||||||
|
community.docker.docker_image_info:
|
||||||
|
name: "{{ container_out.container.Image }}"
|
||||||
|
register: container_image_out
|
||||||
|
- name: Assert nginx image not built locally
|
||||||
|
assert:
|
||||||
|
that: container_image_out.images[0].RepoTags[0] == 'nginx:latest'
|
||||||
|
msg: "Nginx image tag incorrect. It should have been nginx:latest but it was {{ container_image_out.images[0].RepoTags }}"
|
||||||
|
|
||||||
|
- name: Get docker host info
|
||||||
|
community.docker.docker_host_info:
|
||||||
|
volumes: true
|
||||||
|
register: docker_host_out
|
||||||
|
- name: Assert all containers are running
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: docker_host_out.host_info.Containers == docker_host_out.host_info.ContainersRunning
|
||||||
|
msg: There should have been {{ docker_host_out.host_info.Containers }} containers running but there were {{ docker_host_out.host_info.ContainersRunning }}
|
||||||
|
- name: Assert no extra containers were created
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: docker_host_out.host_info.Containers == 1
|
||||||
|
msg: There should have been 1 container created but there were {{ docker_host_out.host_info.Containers }}
|
||||||
|
- name: Assert no extra images were pulled
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: docker_host_out.host_info.Images == 1
|
||||||
|
msg: There should have been 1 image present but there were {{ docker_host_out.host_info.Images }}
|
||||||
|
- name: Assert no volumes were created
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: docker_host_out.volumes | length == 0
|
||||||
|
msg: There should have been no volumes present but there were {{ docker_host_out.volumes | length }}
|
||||||
51
roles/service/tasks/additional.yml
Normal file
51
roles/service/tasks/additional.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Store docker additional services so it doesn't get reset
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_docker_additional_services: "{{ docker_additional_services }}"
|
||||||
|
|
||||||
|
- name: "Memcached container for {{ docker_service_name }}"
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: service
|
||||||
|
vars:
|
||||||
|
docker_namespace: "{{ _docker_namespace }}"
|
||||||
|
docker_service: memcached
|
||||||
|
docker_image: memcached:alpine
|
||||||
|
reverse_proxy_type: none
|
||||||
|
docker_mounts: []
|
||||||
|
docker_published_ports: []
|
||||||
|
docker_env: {}
|
||||||
|
docker_additional_env: {}
|
||||||
|
docker_networks: []
|
||||||
|
docker_database: none
|
||||||
|
docker_additional_services: []
|
||||||
|
docker_host_user: false
|
||||||
|
dockerfile: []
|
||||||
|
docker_command: "{{ omit }}"
|
||||||
|
docker_entrypoint: "{{ omit }}"
|
||||||
|
docker_memory: "{{ omit }}"
|
||||||
|
when: "'memcached' in _docker_additional_services"
|
||||||
|
|
||||||
|
- name: "Redis container for {{ docker_service_name }}"
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: service
|
||||||
|
vars:
|
||||||
|
docker_namespace: "{{ _docker_namespace }}"
|
||||||
|
docker_service: redis
|
||||||
|
docker_image: redis:alpine
|
||||||
|
reverse_proxy_type: none
|
||||||
|
docker_mounts:
|
||||||
|
- name: redis
|
||||||
|
path: /data
|
||||||
|
docker_command: "{{ '--save 60 1' if docker_redis_persistence else omit }}"
|
||||||
|
docker_published_ports: []
|
||||||
|
docker_env: {}
|
||||||
|
docker_additional_env: {}
|
||||||
|
docker_networks: []
|
||||||
|
docker_database: none
|
||||||
|
docker_additional_services: []
|
||||||
|
docker_host_user: false
|
||||||
|
dockerfile: []
|
||||||
|
docker_entrypoint: "{{ omit }}"
|
||||||
|
docker_memory: "{{ omit }}"
|
||||||
|
when: "'redis' in _docker_additional_services"
|
||||||
94
roles/service/tasks/database.yml
Normal file
94
roles/service/tasks/database.yml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Set postgres container vars
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
db_container_image: 'postgres:14-alpine'
|
||||||
|
db_container_env:
|
||||||
|
POSTGRES_USER: "{{ docker_service_underscore_name }}"
|
||||||
|
POSTGRES_PASSWORD: "{{ database_passwords[docker_service_name] }}"
|
||||||
|
db_container_data: /var/lib/postgresql/data
|
||||||
|
when: docker_database == 'postgres'
|
||||||
|
|
||||||
|
- name: Set mariadb container vars
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
db_container_image: mariadb:10
|
||||||
|
db_container_env:
|
||||||
|
MARIADB_USER: "{{ docker_service_underscore_name }}"
|
||||||
|
MARIADB_DATABASE: "{{ docker_service_underscore_name }}"
|
||||||
|
MARIADB_PASSWORD: "{{ database_passwords[docker_service_name] }}"
|
||||||
|
MARIADB_RANDOM_ROOT_PASSWORD: "{{ database_passwords[docker_service_name + '_root'] is not defined | string }}"
|
||||||
|
MARIADB_ROOT_PASSOWRD: "{{ database_passwords[docker_service_name + '_root'] | default(omit) }}"
|
||||||
|
db_container_data: /var/lib/mysql
|
||||||
|
db_image_port: 3306
|
||||||
|
when: docker_database == 'mariadb'
|
||||||
|
|
||||||
|
- name: Set mongo container vars
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
db_container_image: 'mongo:latest'
|
||||||
|
db_container_data: /data/db
|
||||||
|
when: docker_database == 'mongo'
|
||||||
|
|
||||||
|
- name: Define db container data mount
|
||||||
|
set_fact:
|
||||||
|
db_container_mounts:
|
||||||
|
- name: db
|
||||||
|
path: "{{ db_container_data }}"
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Define db container config mount
|
||||||
|
set_fact:
|
||||||
|
db_container_mounts: "{{ db_container_mounts + [{'template': 'mariadb.cnf', 'path': '/etc/mysql/conf.d/custom.cnf'}] }}"
|
||||||
|
when: db_config_mounts_needed
|
||||||
|
|
||||||
|
- name: Set db published ports var
|
||||||
|
set_fact:
|
||||||
|
db_published_ports: ["127.0.0.1:{{ ports[docker_service_name].db }}:{{ db_image_port }}"]
|
||||||
|
when: ports[docker_service_name].db is defined
|
||||||
|
|
||||||
|
- name: Database container for {{ docker_service_name }}
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: service
|
||||||
|
vars:
|
||||||
|
docker_namespace: "{{ _docker_namespace }}"
|
||||||
|
docker_service: db
|
||||||
|
docker_image: "{{ db_container_image }}"
|
||||||
|
reverse_proxy_type: none
|
||||||
|
docker_mounts: "{{ db_container_mounts }}"
|
||||||
|
docker_published_ports: "{{ db_published_ports | default([]) }}"
|
||||||
|
docker_env: "{{ db_container_env | default({}) }}"
|
||||||
|
docker_additional_env: {}
|
||||||
|
docker_networks: []
|
||||||
|
docker_database: none
|
||||||
|
docker_additional_services: []
|
||||||
|
docker_host_user: false
|
||||||
|
dockerfile: []
|
||||||
|
docker_command: "{{ omit }}"
|
||||||
|
docker_entrypoint: "{{ omit }}"
|
||||||
|
docker_memory: "{{ omit }}"
|
||||||
|
|
||||||
|
- name: phpMyAdmin container for {{ docker_service_name }}
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: service
|
||||||
|
vars:
|
||||||
|
docker_namespace: "{{ _docker_namespace }}"
|
||||||
|
docker_service: phpmyadmin
|
||||||
|
docker_image: phpmyadmin
|
||||||
|
docker_mounts: []
|
||||||
|
docker_published_ports:
|
||||||
|
- "127.0.0.1:{{ ports[docker_service_name]['phpmyadmin'] }}:80"
|
||||||
|
docker_env:
|
||||||
|
PMA_ABSOLUTE_URI: "https://{{ docker_vhost_domains[docker_service_name + '_phpmyadmin'][0] }}"
|
||||||
|
PMA_HOST: "{{ docker_service_name }}-db"
|
||||||
|
docker_additional_env: {}
|
||||||
|
docker_networks: []
|
||||||
|
docker_database: none
|
||||||
|
docker_additional_services: []
|
||||||
|
docker_host_user: false
|
||||||
|
dockerfile: []
|
||||||
|
docker_command: "{{ omit }}"
|
||||||
|
docker_entrypoint: "{{ omit }}"
|
||||||
|
docker_memory: "{{ omit }}"
|
||||||
|
docker_proxy_target_protocol: http
|
||||||
|
vhost_basicauth: "{{ docker_phpmyadmin_basicauth }}"
|
||||||
|
vhost_basicauth_users: "{{ docker_phpmyadmin_basicauth_users }}"
|
||||||
|
when: docker_database == 'mariadb' and ports[docker_service_name]['phpmyadmin'] is defined
|
||||||
14
roles/service/tasks/host_user.yml
Normal file
14
roles/service/tasks/host_user.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: "Create user for {{ docker_service_name }}"
|
||||||
|
user:
|
||||||
|
name: "{{ docker_service_underscore_name }}"
|
||||||
|
home: "/opt/{{ docker_namespace }}/{{ docker_service_suffix }}"
|
||||||
|
create_home: false
|
||||||
|
system: true
|
||||||
|
shell: /bin/bash
|
||||||
|
register: user
|
||||||
|
|
||||||
|
- name: Set docker container user
|
||||||
|
set_fact:
|
||||||
|
docker_user: "{{ user.uid }}:{{ user.group }}"
|
||||||
71
roles/service/tasks/image.yml
Normal file
71
roles/service/tasks/image.yml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Image build
|
||||||
|
when: dockerfile_needed
|
||||||
|
block:
|
||||||
|
- name: Set docker_build_directory variable
|
||||||
|
set_fact:
|
||||||
|
docker_build_directory: /opt/{{ docker_namespace }}/build
|
||||||
|
|
||||||
|
- name: Create container build directory
|
||||||
|
file:
|
||||||
|
path: "{{ docker_build_directory }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Put dockerfile in place
|
||||||
|
template:
|
||||||
|
src: Dockerfile.j2
|
||||||
|
dest: "{{ docker_build_directory }}/Dockerfile"
|
||||||
|
mode: 0644
|
||||||
|
|
||||||
|
- name: Build docker image for {{ docker_service }}
|
||||||
|
docker_image:
|
||||||
|
name: "local_{{ docker_service }}"
|
||||||
|
source: build
|
||||||
|
force_source: true
|
||||||
|
build:
|
||||||
|
pull: true
|
||||||
|
path: "{{ docker_build_directory }}"
|
||||||
|
register: built_image
|
||||||
|
changed_when:
|
||||||
|
- not ansible_check_mode
|
||||||
|
- built_image.changed
|
||||||
|
|
||||||
|
- name: Pull container image for {{ docker_service_name }}
|
||||||
|
docker_image:
|
||||||
|
name: "{{ docker_image }}"
|
||||||
|
source: pull
|
||||||
|
force_source: true
|
||||||
|
register: pulled_image
|
||||||
|
when: not dockerfile_needed
|
||||||
|
changed_when:
|
||||||
|
- not ansible_check_mode
|
||||||
|
- pulled_image.changed
|
||||||
|
|
||||||
|
- name: Set container_image variable
|
||||||
|
set_fact:
|
||||||
|
container_image: "{{ item.image }}"
|
||||||
|
when: item.skipped is not defined or not item.skipped
|
||||||
|
loop:
|
||||||
|
- "{{ built_image }}"
|
||||||
|
- "{{ pulled_image }}"
|
||||||
|
|
||||||
|
- name: Check mode image info
|
||||||
|
when: ansible_check_mode
|
||||||
|
block:
|
||||||
|
- name: Get docker image info for check mode
|
||||||
|
docker_image_info:
|
||||||
|
name: "{{ ('local_' + docker_service) if dockerfile | length > 0 else docker_image }}"
|
||||||
|
register: existing_image
|
||||||
|
|
||||||
|
- name: Set check mode container_image variable
|
||||||
|
set_fact:
|
||||||
|
container_image: "{{ existing_image.images[0] }}"
|
||||||
|
when: existing_image.images | length > 0
|
||||||
|
|
||||||
|
- name: Set image user variable
|
||||||
|
set_fact:
|
||||||
|
image_user: "{{ container_image.Config.User }}"
|
||||||
|
when:
|
||||||
|
- not ansible_check_mode
|
||||||
|
- container_image.Config.User | int
|
||||||
63
roles/service/tasks/init.yml
Normal file
63
roles/service/tasks/init.yml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Fail if docker_volumes defined
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "docker_volumes is not supported anymore. Use docker_mounts instead!"
|
||||||
|
when: docker_volumes is defined
|
||||||
|
|
||||||
|
- name: Store variables to be reset in the end
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_docker_service_name: "{{ docker_service_name }}"
|
||||||
|
_docker_mount_definition: "{{ docker_mount_definition }}"
|
||||||
|
_container_published_ports: "{{ container_published_ports }}"
|
||||||
|
_container_image: "{{ container_image }}"
|
||||||
|
_container_networks: "{{ container_networks }}"
|
||||||
|
_template_mounts_needed: "{{ template_mounts_needed }}"
|
||||||
|
_copypath_mounts_needed: "{{ copypath_mounts_needed }}"
|
||||||
|
_volumes_needed: "{{ volumes_needed }}"
|
||||||
|
_dockerfile_needed: "{{ dockerfile_needed }}"
|
||||||
|
_db_config_mounts_needed: "{{ db_config_mounts_needed }}"
|
||||||
|
_bind_volumes_needed: "{{ bind_volumes_needed }}"
|
||||||
|
_named_volumes_needed: "{{ named_volumes_needed }}"
|
||||||
|
_create_opt_directory: "{{ create_opt_directory }}"
|
||||||
|
_create_mounts_directory: "{{ create_mounts_directory }}"
|
||||||
|
_docker_service_underscore_name: "{{ docker_service_underscore_name }}"
|
||||||
|
_image_user: "{{ image_user }}"
|
||||||
|
when: create_mounts_directory is defined
|
||||||
|
|
||||||
|
- name: Initialize variables
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
_docker_namespace: "{{ docker_namespace }}"
|
||||||
|
docker_service_name: "{{ docker_namespace }}"
|
||||||
|
docker_mount_definition: []
|
||||||
|
container_published_ports: []
|
||||||
|
container_image: ''
|
||||||
|
image_user: ''
|
||||||
|
container_networks: []
|
||||||
|
|
||||||
|
- name: Add suffix to docker_service_name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
docker_service_name: "{{ docker_service_name }}-{{ docker_service_suffix }}"
|
||||||
|
when: docker_service_suffix | length > 0
|
||||||
|
|
||||||
|
- name: Add docker_service to docker_service_name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
docker_service_name: "{{ docker_service_name }}-{{ docker_service }}"
|
||||||
|
when: docker_namespace != docker_service
|
||||||
|
|
||||||
|
- name: Set assistive variables
|
||||||
|
set_fact:
|
||||||
|
docker_service_underscore_name: "{{ docker_service_name | replace('-', '_') }}"
|
||||||
|
template_mounts_needed: "{{ docker_mounts | selectattr('template', 'defined') | list | length > 0 }}"
|
||||||
|
copypath_mounts_needed: "{{ docker_mounts | selectattr('copypath', 'defined') | list | length > 0 }}"
|
||||||
|
volumes_needed: "{{ docker_mounts | selectattr('name', 'defined') | list | length > 0 or docker_database != 'none' }}"
|
||||||
|
dockerfile_needed: "{{ dockerfile | length > 0 }}"
|
||||||
|
db_config_mounts_needed: "{{ docker_mariadb_config | length > 0 }}"
|
||||||
|
- name: Set more assistive variables
|
||||||
|
set_fact:
|
||||||
|
bind_volumes_needed: "{{ volumes_needed and docker_volume_type == 'bind' }}"
|
||||||
|
named_volumes_needed: "{{ volumes_needed and docker_volume_type == 'named' }}"
|
||||||
|
- name: Set even more assistive variables
|
||||||
|
set_fact:
|
||||||
|
create_opt_directory: "{{ dockerfile_needed or docker_host_user or bind_volumes_needed or template_mounts_needed or copypath_mounts_needed or db_config_mounts_needed }}"
|
||||||
|
create_mounts_directory: "{{ bind_volumes_needed or template_mounts_needed or copypath_mounts_needed or db_config_mounts_needed }}"
|
||||||
139
roles/service/tasks/main.yml
Normal file
139
roles/service/tasks/main.yml
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Container role initialization
|
||||||
|
import_tasks: init.yml
|
||||||
|
|
||||||
|
- name: Docker network
|
||||||
|
when: docker_network_mode != 'host' or docker_networks | length > 0
|
||||||
|
block:
|
||||||
|
- name: Set networks variable to {{ docker_namespace + ('-' + docker_service_suffix if docker_service_suffix | length > 0 else '') }}
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
container_networks:
|
||||||
|
- name: "{{ docker_namespace + ('-' + docker_service_suffix if docker_service_suffix | length > 0 else '') }}"
|
||||||
|
when: docker_networks | length == 0
|
||||||
|
- name: Set networks variable to {{ docker_networks }}
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
container_networks: "{{ docker_networks }}"
|
||||||
|
when: docker_networks | length > 0
|
||||||
|
- name: Create docker networks
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
loop: "{{ container_networks }}"
|
||||||
|
|
||||||
|
- name: Reverse proxy for container
|
||||||
|
include_tasks: proxy.yml
|
||||||
|
when: reverse_proxy_type != 'none'
|
||||||
|
|
||||||
|
- name: Create directory /opt/{{ docker_namespace }}
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/opt/{{ docker_namespace }}"
|
||||||
|
state: directory
|
||||||
|
mode: 0755
|
||||||
|
when: create_opt_directory
|
||||||
|
|
||||||
|
- name: Container image
|
||||||
|
import_tasks: image.yml
|
||||||
|
|
||||||
|
- name: Container user
|
||||||
|
include_tasks: host_user.yml
|
||||||
|
when: docker_host_user
|
||||||
|
|
||||||
|
- name: Create suffix directory
|
||||||
|
when: create_opt_directory and docker_service_suffix | length > 0
|
||||||
|
block:
|
||||||
|
- name: Create directory /opt/{{ docker_namespace + '/' + docker_service_suffix }}
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/opt/{{ docker_namespace }}/{{ docker_service_suffix }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ user.uid | default(omit) }}"
|
||||||
|
group: "{{ user.group | default(omit) }}"
|
||||||
|
mode: 0755
|
||||||
|
- name: Set container_workdir variable
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
container_workdir: /opt/{{ docker_namespace }}/{{ docker_service_suffix }}
|
||||||
|
|
||||||
|
- name: Set container_workdir variable
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
container_workdir: /opt/{{ docker_namespace }}
|
||||||
|
when: docker_service_suffix | length == 0
|
||||||
|
|
||||||
|
- name: Create mounts directory
|
||||||
|
when: create_mounts_directory
|
||||||
|
block:
|
||||||
|
- name: Set docker_mounts_dir
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
docker_mounts_dir: "{{ container_workdir }}/mounts"
|
||||||
|
|
||||||
|
- name: Create directory {{ docker_mounts_dir }}
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ docker_mounts_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ user.uid | default(omit) }}"
|
||||||
|
group: "{{ user.group | default(omit) }}"
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: Database container
|
||||||
|
include_tasks: database.yml
|
||||||
|
when: docker_database != 'none'
|
||||||
|
|
||||||
|
- name: Additional services
|
||||||
|
include_tasks: additional.yml
|
||||||
|
when: docker_additional_services | length > 0
|
||||||
|
|
||||||
|
- name: Container mounts
|
||||||
|
import_tasks: mounts.yml
|
||||||
|
|
||||||
|
- name: "Ensure container with legacy name doesn't exist for {{ docker_service_underscore_name }}"
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ docker_service_underscore_name }}"
|
||||||
|
state: absent
|
||||||
|
when: docker_service_underscore_name != docker_service_name
|
||||||
|
|
||||||
|
- name: Ensure network with legacy name doesn't exist
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: "{{ docker_service_underscore_name }}"
|
||||||
|
state: absent
|
||||||
|
when: docker_service_underscore_name != docker_service_name
|
||||||
|
|
||||||
|
- name: "Container for {{ docker_service_name }}"
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ docker_service_name }}"
|
||||||
|
image: "{{ container_image.Id if (not ansible_check_mode) or (container_image | length > 0) else docker_image }}"
|
||||||
|
user: "{{ docker_user if docker_host_user else omit }}"
|
||||||
|
mounts: "{{ docker_mount_definition }}"
|
||||||
|
published_ports: "{{ container_published_ports + docker_published_ports }}"
|
||||||
|
labels: "{{ traefik_labels | default(omit) }}"
|
||||||
|
env: "{{ docker_env | combine(docker_additional_env) | combine({'TZ': timezone}) }}"
|
||||||
|
entrypoint: "{{ docker_entrypoint | default(omit) }}"
|
||||||
|
command: "{{ docker_command | default(omit) }}"
|
||||||
|
memory: "{{ docker_memory | default(omit) }}"
|
||||||
|
restart_policy: "{{ docker_restart_policy }}"
|
||||||
|
network_mode: "{{ docker_network_mode if docker_network_mode | length > 0 else omit }}"
|
||||||
|
networks: "{{ container_networks }}"
|
||||||
|
log_driver: local
|
||||||
|
state: "{{ 'started' if docker_restart_policy == 'always' else 'present' }}"
|
||||||
|
register: container_out
|
||||||
|
notify: Ensure container running
|
||||||
|
|
||||||
|
- name: Flush handlers to trigger container restart
|
||||||
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Reset variables to their original values
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
docker_service_name: "{{ _docker_service_name }}"
|
||||||
|
docker_mount_definition: "{{ _docker_mount_definition }}"
|
||||||
|
container_published_ports: "{{ _container_published_ports }}"
|
||||||
|
container_image: "{{ _container_image }}"
|
||||||
|
container_networks: "{{ _container_networks }}"
|
||||||
|
template_mounts_needed: "{{ _template_mounts_needed }}"
|
||||||
|
copypath_mounts_needed: "{{ _copypath_mounts_needed }}"
|
||||||
|
volumes_needed: "{{ _volumes_needed }}"
|
||||||
|
dockerfile_needed: "{{ _dockerfile_needed }}"
|
||||||
|
db_config_mounts_needed: "{{ _db_config_mounts_needed }}"
|
||||||
|
bind_volumes_needed: "{{ _bind_volumes_needed }}"
|
||||||
|
named_volumes_needed: "{{ _named_volumes_needed }}"
|
||||||
|
create_opt_directory: "{{ _create_opt_directory }}"
|
||||||
|
create_mounts_directory: "{{ _create_mounts_directory }}"
|
||||||
|
docker_service_underscore_name: "{{ _docker_service_underscore_name }}"
|
||||||
|
image_user: "{{ _image_user }}"
|
||||||
|
when: _docker_service_name is defined
|
||||||
64
roles/service/tasks/mounts.yml
Normal file
64
roles/service/tasks/mounts.yml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: Create directories and put files in them
|
||||||
|
when: create_mounts_directory
|
||||||
|
block:
|
||||||
|
- name: Define mount directory owner
|
||||||
|
set_fact:
|
||||||
|
mount_owner: "{{ user.uid if docker_host_user else image_user }}"
|
||||||
|
mount_group: "{{ user.group if docker_host_user else '' }}"
|
||||||
|
|
||||||
|
- name: "Create docker bind mount directories for {{ docker_service_name }}"
|
||||||
|
file:
|
||||||
|
path: "{{ docker_mounts_dir }}/{{ item.name }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ mount_owner if (item.set_owner is not defined or item.set_owner) and mount_owner | length > 0 else omit }}"
|
||||||
|
group: "{{ mount_group if (item.set_group is not defined or item.set_group) and mount_group | length > 0 else omit }}"
|
||||||
|
mode: "{{ item.mode | default('0755') }}"
|
||||||
|
when: item.name is defined and docker_volume_type == 'bind'
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
- name: Set docker_mount_definition for named binds
|
||||||
|
set_fact:
|
||||||
|
docker_mount_definition: "{{ docker_mount_definition + [{'source': docker_mounts_dir + '/' + item.name, 'target': item.path, 'type': 'bind', 'read_only': item.readonly | default(false)}] }}"
|
||||||
|
when: item.name is defined and docker_volume_type == 'bind'
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
|
||||||
|
- name: Template docker template mounts for {{ docker_service_name }}
|
||||||
|
template:
|
||||||
|
src: "{{ item.template }}.j2"
|
||||||
|
dest: "{{ docker_mounts_dir }}/{{ item.template }}"
|
||||||
|
mode: "{{ item.mode | default('0644') }}"
|
||||||
|
when: item.template is defined
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
notify: Restart container
|
||||||
|
- name: Set docker_mount_definition for template mounts
|
||||||
|
set_fact:
|
||||||
|
docker_mount_definition: "{{ docker_mount_definition + [{'source': docker_mounts_dir + '/' + item.template, 'target': item.path, 'type': 'bind', 'read_only': true}] }}"
|
||||||
|
when: item.template is defined
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
|
||||||
|
- name: Copy docker copypath mounts for {{ docker_service_name }}
|
||||||
|
copy:
|
||||||
|
src: "files/{{ item.copypath }}"
|
||||||
|
dest: "{{ docker_mounts_dir }}/"
|
||||||
|
mode: "{{ item.mode | default('0755') }}"
|
||||||
|
when: item.copypath is defined
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
notify: Restart container
|
||||||
|
- name: Set docker_mount_definition for copypath mounts
|
||||||
|
set_fact:
|
||||||
|
docker_mount_definition: "{{ docker_mount_definition + [{'source': docker_mounts_dir + '/' + item.copypath, 'target': item.path, 'type': 'bind', 'read_only': true}] }}"
|
||||||
|
when: item.copypath is defined
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
|
||||||
|
- name: Set docker_mount_definition for named volumes
|
||||||
|
set_fact:
|
||||||
|
docker_mount_definition: "{{ docker_mount_definition + [{'source': docker_namespace + ('-' + docker_service_suffix if docker_service_suffix | length > 0 else '') + '-' + item.name, 'target': item.path, 'type': 'volume', 'read_only': item.readonly | default(false)}] }}"
|
||||||
|
when: docker_volume_type == 'named' and item.name is defined
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
|
|
||||||
|
- name: Set docker_mount_definition for src binds
|
||||||
|
set_fact:
|
||||||
|
docker_mount_definition: "{{ docker_mount_definition + [{'source': item.src, 'target': item.path, 'type': 'bind', 'read_only': item.readonly | default(false)}] }}"
|
||||||
|
when: item.src is defined
|
||||||
|
loop: "{{ docker_mounts }}"
|
||||||
31
roles/service/tasks/proxy.yml
Normal file
31
roles/service/tasks/proxy.yml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
- name: "Ensure reverse proxy with legacy name doesn't exist"
|
||||||
|
include_role:
|
||||||
|
name: uumas.general.vhost
|
||||||
|
vars:
|
||||||
|
vhost_id: "{{ docker_service_underscore_name }}"
|
||||||
|
vhost_state: absent
|
||||||
|
when: docker_service_underscore_name != docker_service_name
|
||||||
|
|
||||||
|
- name: Reverse proxy
|
||||||
|
include_role:
|
||||||
|
name: uumas.general.vhost
|
||||||
|
vars:
|
||||||
|
vhost_type: reverse_proxy
|
||||||
|
vhost_id: "{{ docker_service_name }}"
|
||||||
|
proxy_target_protocol: "{{ docker_proxy_target_protocol }}"
|
||||||
|
vhost_domains: "{{ docker_vhost_domains[docker_service_name] }}"
|
||||||
|
proxy_target_port: "{{ ports[docker_service_name][proxy_target_protocol] }}"
|
||||||
|
when: reverse_proxy_type != 'traefik'
|
||||||
|
|
||||||
|
- name: Set published ports variable to http port
|
||||||
|
set_fact:
|
||||||
|
container_published_ports: ["127.0.0.1:{{ ports[docker_service_name][docker_proxy_target_protocol] }}:{{ docker_image_http_port }}"]
|
||||||
|
when:
|
||||||
|
- docker_network_mode != 'host'
|
||||||
|
- reverse_proxy_type != 'traefik'
|
||||||
|
|
||||||
|
- name: Include traefik vars
|
||||||
|
include_vars: traefik.yml
|
||||||
|
when: reverse_proxy_type == 'traefik'
|
||||||
6
roles/service/templates/Dockerfile.j2
Normal file
6
roles/service/templates/Dockerfile.j2
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# {{ ansible_managed }}
|
||||||
|
|
||||||
|
FROM {{ docker_image }}
|
||||||
|
{% for item in dockerfile %}
|
||||||
|
{{ item }}
|
||||||
|
{% endfor %}
|
||||||
8
roles/service/templates/mariadb.cnf.j2
Normal file
8
roles/service/templates/mariadb.cnf.j2
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# {{ ansible_managed }}
|
||||||
|
|
||||||
|
{% for section in docker_mariadb_config | dict2items %}
|
||||||
|
[{{ section.key }}]
|
||||||
|
{% for item in section.value | dict2items %}
|
||||||
|
{{ item.key }} = {{ item.value }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
3
roles/service/todo
Normal file
3
roles/service/todo
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Reverse proxy for phpmyadmin
|
||||||
|
|
||||||
|
Make docker_additional_services a loop of include_tasks
|
||||||
Reference in New Issue
Block a user