diff --git a/roles/container/tasks/database.yml b/roles/container/tasks/database.yml new file mode 100644 index 0000000..01e09fc --- /dev/null +++ b/roles/container/tasks/database.yml @@ -0,0 +1,44 @@ +--- + +- name: Set postgres container vars + set_fact: + db_container_image: 'postgres:14-alpine' + db_container_env: + POSTGRES_USER: "{{ docker_service_name }}" + POSTGRES_PASSWORD: "{{ database_passwords[docker_service_name] }}" + db_container_data: /var/lib/postgresql/data + when: docker_database == 'postgres' +- name: Set mariadb container vars + set_fact: + db_container_image: mariadb:10 + db_container_env: + MARIADB_USER: "{{ docker_service_name }}" + MARIADB_DATABASE: "{{ docker_service_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 + set_fact: + db_container_image: 'mongo:latest' + db_container_data: /data/db + when: docker_database == 'mongo' +- 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 + ' (' + docker_database + ')' }} + docker_container: + name: "{{ docker_service_name }}_db" + image: "{{ db_container_image }}" + pull: true + env: "{{ db_container_env | default(omit) }}" + published_ports: "{{ db_published_ports | default(omit) }}" + restart_policy: always + volumes: + - "{{ docker_service_name }}_db:{{ db_container_data }}" + networks: "{{ container_networks | default(omit) }}" + log_driver: local diff --git a/roles/container/tasks/host_user.yml b/roles/container/tasks/host_user.yml new file mode 100644 index 0000000..962de20 --- /dev/null +++ b/roles/container/tasks/host_user.yml @@ -0,0 +1,14 @@ +--- + +- name: "Create user for {{ docker_service_name }}" + user: + name: "{{ docker_service_name }}" + home: "/opt/{{ docker_service }}/{{ docker_service_suffix | default('') }}" + create_home: false + system: true + shell: /bin/bash + register: user + +- name: Set docker container user + set_fact: + docker_user: "{{ user.uid }}:{{ user.group }}" diff --git a/roles/container/tasks/image.yml b/roles/container/tasks/image.yml new file mode 100644 index 0000000..263a1ac --- /dev/null +++ b/roles/container/tasks/image.yml @@ -0,0 +1,20 @@ +--- + +- name: Image build + when: dockerfile is defined and dockerfile | length > 0 + block: + - name: Put dockerfile in place + template: + src: Dockerfile.j2 + dest: "/opt/{{ docker_service }}/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: "/opt/{{ docker_service }}" + register: docker_built_image diff --git a/roles/container/tasks/init.yml b/roles/container/tasks/init.yml new file mode 100644 index 0000000..2586934 --- /dev/null +++ b/roles/container/tasks/init.yml @@ -0,0 +1,27 @@ +--- + +- name: Set docker service full name + set_fact: + docker_service_name: "{{ docker_service }}_{{ docker_service_suffix }}" + when: docker_service_suffix is defined + +- name: Convert docker_volumes from legacy format + when: docker_volumes is defined and docker_volumes[0] is not mapping + block: + - name: Warn about docker_volumes legacy format + debug: + msg: "docker_volumes is set in a legacy, deprecated format. This support may be removed after december 2022." + + - name: Add legacy docker volumes to docker_volumes_new using the new format + set_fact: + docker_volumes_new: "{{ docker_volumes_new | default([]) + [{'name': item.split(':')[0], 'path': item.split(':')[1]}] }}" + when: "'/' not in item.split(':')[0]" + loop: "{{ docker_volumes }}" + - name: Add legacy docker src bind mounts to docker_volumes_new using the new format + set_fact: + docker_volumes_new: "{{ docker_volumes_new | default([]) + [{'src': item.split(':')[0], 'path': item.split(':')[1]}] }}" + when: "'/' in item.split(':')[0]" + loop: "{{ docker_volumes }}" + - name: Set final_docker_volumes variable + set_fact: + final_docker_volumes: "{{ docker_volumes_new }}" diff --git a/roles/container/tasks/main.yml b/roles/container/tasks/main.yml index ac38768..4398849 100644 --- a/roles/container/tasks/main.yml +++ b/roles/container/tasks/main.yml @@ -1,106 +1,25 @@ --- -- name: Set docker service full name - set_fact: - docker_service_name: "{{ docker_service }}_{{ docker_service_suffix }}" - when: docker_service_suffix is defined - -- name: Convert docker_volumes from legacy format - when: docker_volumes is defined and docker_volumes[0] is not mapping - block: - - name: Warn about docker_volumes legacy format - debug: - msg: "docker_volumes is set in a legacy, deprecated format. This support may be removed after december 2022." - - - name: Add legacy docker volumes to docker_volumes_new using the new format - set_fact: - docker_volumes_new: "{{ docker_volumes_new | default([]) + [{'name': item.split(':')[0], 'path': item.split(':')[1]}] }}" - when: "'/' not in item.split(':')[0]" - loop: "{{ docker_volumes }}" - - name: Add legacy docker src bind mounts to docker_volumes_new using the new format - set_fact: - docker_volumes_new: "{{ docker_volumes_new | default([]) + [{'src': item.split(':')[0], 'path': item.split(':')[1]}] }}" - when: "'/' in item.split(':')[0]" - loop: "{{ docker_volumes }}" - - name: Set final_docker_volumes variable - set_fact: - final_docker_volumes: "{{ docker_volumes_new }}" +- name: Container role initialization + import_tasks: init.yml - name: Docker network {{ docker_service_name }} docker_network: name: "{{ docker_service_name }}" when: docker_network_mode is not defined or docker_network_mode != 'host' - + - name: Set networks variable set_fact: container_networks: - name: "{{ docker_service_name }}" when: docker_network_mode is not defined or docker_network_mode != 'host' -- name: Reverse proxy - include_role: - name: uumas.general.reverse_proxy - vars: - 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 != 'none' and reverse_proxy_type != 'traefik' - -- name: Set published ports variable - set_fact: - container_published_ports: ["127.0.0.1:{{ ports[docker_service_name][docker_proxy_target_protocol] }}:{{ docker_image_http_port }}"] - when: reverse_proxy_type != 'traefik' and (docker_network_mode is not defined or docker_network_mode != 'host') - -- name: Include traefik vars - include_vars: traefik.yml - when: reverse_proxy_type == 'traefik' +- name: Reverse proxy for container + import_tasks: proxy.yml - name: Database container + include_tasks: database.yml when: docker_database is defined - block: - - name: Set postgres container vars - set_fact: - db_container_image: 'postgres:14-alpine' - db_container_env: - POSTGRES_USER: "{{ docker_service_name }}" - POSTGRES_PASSWORD: "{{ database_passwords[docker_service_name] }}" - db_container_data: /var/lib/postgresql/data - when: docker_database == 'postgres' - - name: Set mariadb container vars - set_fact: - db_container_image: mariadb:10 - db_container_env: - MARIADB_USER: "{{ docker_service_name }}" - MARIADB_DATABASE: "{{ docker_service_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 - set_fact: - db_container_image: 'mongo:latest' - db_container_data: /data/db - when: docker_database == 'mongo' - - 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 + ' (' + docker_database + ')' }} - docker_container: - name: "{{ docker_service_name }}_db" - image: "{{ db_container_image }}" - pull: true - env: "{{ db_container_env | default(omit) }}" - published_ports: "{{ db_published_ports | default(omit) }}" - restart_policy: always - volumes: - - "{{ docker_service_name }}_db:{{ db_container_data }}" - networks: "{{ container_networks | default(omit) }}" - log_driver: local - name: Additional services when: docker_additional_services is defined @@ -122,95 +41,15 @@ mode: 0755 when: (dockerfile is defined and dockerfile | length > 0) or docker_host_user or docker_volume_type == 'bind' -- name: Image build - when: dockerfile is defined and dockerfile | length > 0 - block: - - name: Put dockerfile in place - template: - src: Dockerfile.j2 - dest: "/opt/{{ docker_service }}/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: "/opt/{{ docker_service }}" - register: docker_built_image +- name: Container image + import_tasks: image.yml - name: Container user + include_tasks: host_user.yml when: docker_host_user - block: - - name: "Create user for {{ docker_service_name }}" - user: - name: "{{ docker_service_name }}" - home: "/opt/{{ docker_service }}/{{ docker_service_suffix | default('') }}" - create_home: false - system: true - shell: /bin/bash - register: user - - name: Set docker container user - set_fact: - docker_user: "{{ user.uid }}:{{ user.group }}" - -- name: Bind mounts - when: "docker_volume_type == 'bind'" - block: - - name: Create directory /opt/{{ docker_service + '/' + docker_service_suffix }} - file: - path: "/opt/{{ docker_service }}/{{ docker_service_suffix }}" - state: directory - owner: "{{ user.uid | default(omit) }}" - group: "{{ user.group | default(omit) }}" - mode: 0755 - when: docker_service_suffix is defined - - - name: Set docker_mounts_dir - set_fact: - docker_mounts_dir: "/opt/{{ docker_service }}/{{ docker_service_suffix }}/mounts" - when: docker_service_suffix is defined - - name: Set docker_mounts_dir - set_fact: - docker_mounts_dir: "/opt/{{ docker_service }}/mounts" - when: docker_service_suffix is not defined - - - name: Create directory {{ docker_mounts_dir }} - file: - path: "{{ docker_mounts_dir }}" - state: directory - mode: 0755 - - - name: "Create docker bind mount directories for {{ docker_service_name }}" - file: - path: "{{ docker_mounts_dir }}/{{ item.name }}" - state: directory - owner: "{{ user.uid if item.set_owner is not defined or item.set_owner else omit | default(omit) }}" - group: "{{ user.group if item.set_group is not defined or item.set_group else omit | default(omit) }}" - mode: 0750 - when: item.name is defined - loop: "{{ docker_volumes }}" - - - name: Set docker_volume_definition for named binds - set_fact: - docker_volume_definition: "{{ docker_volume_definition | default([]) + [docker_mounts_dir + '/' + item.name + ':' + item.path] }}" - when: item.name is defined - loop: "{{ docker_volumes }}" - -- name: Set docker_volume_definition for src binds - set_fact: - docker_volume_definition: "{{ docker_volume_definition | default([]) + [item.src + ':' + item.path] }}" - when: item.src is defined - loop: "{{ final_docker_volumes }}" - -- name: Set docker_volume_definition for named volumes - set_fact: - docker_volume_definition: "{{ docker_volume_definition | default([]) + [item.name + ':' + item.path] }}" - when: docker_volume_type == 'named' and item.name is defined - loop: "{{ final_docker_volumes }}" +- name: Container volumes + import_tasks: volumes.yml - name: "Container for {{ docker_service_name }}" docker_container: diff --git a/roles/container/tasks/proxy.yml b/roles/container/tasks/proxy.yml new file mode 100644 index 0000000..79963d6 --- /dev/null +++ b/roles/container/tasks/proxy.yml @@ -0,0 +1,20 @@ +--- + +- name: Reverse proxy + include_role: + name: uumas.general.reverse_proxy + vars: + 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 != 'none' and reverse_proxy_type != 'traefik' + +- name: Set published ports variable + set_fact: + container_published_ports: ["127.0.0.1:{{ ports[docker_service_name][docker_proxy_target_protocol] }}:{{ docker_image_http_port }}"] + when: reverse_proxy_type != 'traefik' and (docker_network_mode is not defined or docker_network_mode != 'host') + +- name: Include traefik vars + include_vars: traefik.yml + when: reverse_proxy_type == 'traefik' diff --git a/roles/container/tasks/volumes.yml b/roles/container/tasks/volumes.yml new file mode 100644 index 0000000..4acae37 --- /dev/null +++ b/roles/container/tasks/volumes.yml @@ -0,0 +1,55 @@ +--- + +- name: Bind mounts + when: "docker_volume_type == 'bind'" + block: + - name: Create directory /opt/{{ docker_service + '/' + docker_service_suffix }} + file: + path: "/opt/{{ docker_service }}/{{ docker_service_suffix }}" + state: directory + owner: "{{ user.uid | default(omit) }}" + group: "{{ user.group | default(omit) }}" + mode: 0755 + when: docker_service_suffix is defined + + - name: Set docker_mounts_dir + set_fact: + docker_mounts_dir: "/opt/{{ docker_service }}/{{ docker_service_suffix }}/mounts" + when: docker_service_suffix is defined + - name: Set docker_mounts_dir + set_fact: + docker_mounts_dir: "/opt/{{ docker_service }}/mounts" + when: docker_service_suffix is not defined + + - name: Create directory {{ docker_mounts_dir }} + file: + path: "{{ docker_mounts_dir }}" + state: directory + mode: 0755 + + - name: "Create docker bind mount directories for {{ docker_service_name }}" + file: + path: "{{ docker_mounts_dir }}/{{ item.name }}" + state: directory + owner: "{{ user.uid if item.set_owner is not defined or item.set_owner else omit | default(omit) }}" + group: "{{ user.group if item.set_group is not defined or item.set_group else omit | default(omit) }}" + mode: 0750 + when: item.name is defined + loop: "{{ docker_volumes }}" + - name: Set docker_volume_definition for named binds + set_fact: + docker_volume_definition: "{{ docker_volume_definition | default([]) + [docker_mounts_dir + '/' + item.name + ':' + item.path] }}" + when: item.name is defined + loop: "{{ docker_volumes }}" + +- name: Set docker_volume_definition for src binds + set_fact: + docker_volume_definition: "{{ docker_volume_definition | default([]) + [item.src + ':' + item.path] }}" + when: item.src is defined + loop: "{{ final_docker_volumes }}" + +- name: Set docker_volume_definition for named volumes + set_fact: + docker_volume_definition: "{{ docker_volume_definition | default([]) + [item.name + ':' + item.path] }}" + when: docker_volume_type == 'named' and item.name is defined + loop: "{{ final_docker_volumes }}"