Compare commits
13 Commits
011b2036d6
...
9a4c7c9440
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a4c7c9440 | ||
|
|
f99fbc0483 | ||
|
|
c35c3f73a0 | ||
|
|
9787fbf0db | ||
|
|
79b8e4fa27 | ||
|
|
1596b2bfc5 | ||
|
|
2fae11dd33 | ||
|
|
d32706bae6 | ||
|
|
195210346b | ||
|
|
3f5b6c0558 | ||
|
|
4b7a359663 | ||
|
|
4d9edf1532 | ||
|
|
8812459beb |
@@ -8,6 +8,6 @@ readme: README.md
|
||||
repository: https://git.uumas.fi/uumas/ansible-docker
|
||||
license_file: LICENSE
|
||||
dependencies:
|
||||
uumas.general: '>=0.5.8'
|
||||
uumas.general: '>=0.5.9'
|
||||
authors:
|
||||
- uumas
|
||||
|
||||
@@ -36,4 +36,6 @@ argument_specs:
|
||||
docker_entrypoint:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
|
||||
dockerfile:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
|
||||
1
roles/authentik/README.md
Normal file
1
roles/authentik/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Sets up an authentik docker container.
|
||||
5
roles/authentik/defaults/main.yml
Normal file
5
roles/authentik/defaults/main.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
|
||||
authentik_env: {}
|
||||
docker_networks:
|
||||
- name: authentik
|
||||
49
roles/authentik/meta/argument_specs.yml
Normal file
49
roles/authentik/meta/argument_specs.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
|
||||
argument_specs:
|
||||
main:
|
||||
short_description: Authentik container
|
||||
description: "Sets up an authentik docker container."
|
||||
options:
|
||||
authentik_env:
|
||||
description: "dict of custom environment variables for authentik container"
|
||||
type: dict
|
||||
required: false
|
||||
default: {}
|
||||
|
||||
# All options after this will be passed directly to the container role
|
||||
docker_service_suffix:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
docker_host_user:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
|
||||
database_passwords:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
docker_additional_services:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
|
||||
docker_volume_type:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
reverse_proxy_type:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
ports:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
docker_vhost_domains:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
docker_entrypoint:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
dockerfile:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
docker_networks:
|
||||
description: "Passed to container role"
|
||||
required: false
|
||||
26
roles/authentik/tasks/main.yml
Normal file
26
roles/authentik/tasks/main.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
|
||||
- name: Authentik container
|
||||
ansible.builtin.import_role:
|
||||
name: container
|
||||
vars:
|
||||
docker_service: authentik
|
||||
docker_image: beryju/authentik:latest
|
||||
docker_command:
|
||||
- server
|
||||
docker_image_http_port: 9000
|
||||
docker_database: postgres
|
||||
docker_additional_services:
|
||||
- redis
|
||||
docker_env: "{{ authentik_common_env | combine(authentik_env) }}"
|
||||
|
||||
- name: Authentik worker container
|
||||
ansible.builtin.import_role:
|
||||
name: container
|
||||
vars:
|
||||
docker_service: authentik_worker
|
||||
docker_image: beryju/authentik:latest
|
||||
docker_command:
|
||||
- worker
|
||||
reverse_proxy_type: none
|
||||
docker_env: "{{ authentik_common_env | combine(authentik_env) }}"
|
||||
15
roles/authentik/vars/main.yml
Normal file
15
roles/authentik/vars/main.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
|
||||
authentik_common_env:
|
||||
AUTHENTIK_REDIS__HOST: authentik_redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: authentik_db
|
||||
AUTHENTIK_POSTGRESQL__USER: authentik
|
||||
AUTHENTIK_POSTGRESQL__NAME: authentik
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: "{{ database_passwords.authentik }}"
|
||||
AUTHENTIK_SECRET_KEY: "{{ authentik_secret_key }}"
|
||||
AUTHENTIK_EMAIL__HOST: "{{ smtp_server }}"
|
||||
AUTHENTIK_EMAIL__PORT: '587'
|
||||
AUTHENTIK_EMAIL__USE_TLS: 'true'
|
||||
AUTHENTIK_EMAIL__USERNAME: "{{ smtp_user | default(omit) }}"
|
||||
AUTHENTIK_EMAIL__PASSWORD: "{{ smtp_pw | default(omit) }}"
|
||||
AUTHENTIK_EMAIL__FROM: "{{ smtp_from }}"
|
||||
@@ -3,6 +3,8 @@
|
||||
docker_host_user: false
|
||||
docker_volume_type: named
|
||||
docker_mariadb_config: {}
|
||||
docker_redis_persistence: false
|
||||
dockerfile: []
|
||||
|
||||
docker_phpmyadmin_basicauth: true
|
||||
docker_phpmyadmin_basicauth_users: {}
|
||||
|
||||
@@ -17,6 +17,12 @@ argument_specs:
|
||||
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
|
||||
@@ -57,7 +63,13 @@ argument_specs:
|
||||
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
|
||||
|
||||
18
roles/container/molecule/default/converge.yml
Normal file
18
roles/container/molecule/default/converge.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: Nginx container
|
||||
import_role:
|
||||
name: container
|
||||
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/container/molecule/default/molecule.yml
Normal file
15
roles/container/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/container/molecule/default/verify.yml
Normal file
83
roles/container/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.Containers }}
|
||||
- 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 }}
|
||||
@@ -6,6 +6,49 @@
|
||||
image: memcached:alpine
|
||||
pull: true
|
||||
restart_policy: always
|
||||
networks: "{{ container_networks | default(omit) }}"
|
||||
networks:
|
||||
- "{{ container_networks[0] }}"
|
||||
log_driver: local
|
||||
when: "'memcached' in docker_additional_services"
|
||||
|
||||
- name: Redis
|
||||
when: "'redis' in docker_additional_services"
|
||||
block:
|
||||
- name: Reset redis container mount definition var
|
||||
set_fact:
|
||||
redis_container_mount_definition: []
|
||||
|
||||
- name: Set up redis container data bind mount
|
||||
when: docker_volume_type == 'bind'
|
||||
block:
|
||||
- name: Create redis data bind mount directory for {{ docker_service_name }}
|
||||
file:
|
||||
path: "{{ docker_mounts_dir }}/redis"
|
||||
state: directory
|
||||
|
||||
- name: Set redis_container_mount_definition for redis data bind mount
|
||||
set_fact:
|
||||
redis_container_mount_definition:
|
||||
- source: "{{ docker_mounts_dir + '/redis' }}"
|
||||
target: /data
|
||||
type: bind
|
||||
|
||||
- name: Set redis_container_mount_definition for redis data named volume
|
||||
set_fact:
|
||||
redis_container_mount_definition:
|
||||
source: "{{ docker_service_name + '_redis' }}"
|
||||
target: /data
|
||||
type: volume
|
||||
when: docker_volume_type == 'named'
|
||||
|
||||
- name: "Redis container for {{ docker_service_name }}"
|
||||
docker_container:
|
||||
name: "{{ docker_service_name }}_redis"
|
||||
image: redis:alpine
|
||||
pull: true
|
||||
restart_policy: always
|
||||
mounts: "{{ redis_container_mount_definition }}"
|
||||
command: "{{ '--save 60 1' if docker_redis_persistence else omit }}"
|
||||
networks:
|
||||
- "{{ container_networks[0] }}"
|
||||
log_driver: local
|
||||
|
||||
@@ -75,7 +75,8 @@
|
||||
published_ports: "{{ db_published_ports | default(omit) }}"
|
||||
restart_policy: always
|
||||
mounts: "{{ db_container_mount_definition }}"
|
||||
networks: "{{ container_networks | default(omit) }}"
|
||||
networks:
|
||||
- "{{ container_networks[0] }}"
|
||||
log_driver: local
|
||||
|
||||
- name: phpMyAdmin container for {{ docker_service_name }}
|
||||
@@ -89,6 +90,7 @@
|
||||
published_ports:
|
||||
- "127.0.0.1:{{ ports[docker_service_name]['phpmyadmin'] }}:80"
|
||||
restart_policy: always
|
||||
networks: "{{ container_networks | default(omit) }}"
|
||||
networks:
|
||||
- "{{ container_networks[0] }}"
|
||||
log_driver: local
|
||||
when: docker_database == 'mariadb' and ports[docker_service_name]['phpmyadmin'] is defined
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
docker_volumes_new: []
|
||||
final_docker_volumes: "{{ docker_volumes }}"
|
||||
container_image: ''
|
||||
container_networks: []
|
||||
|
||||
- name: Warn about docker_volumes legacy format
|
||||
debug:
|
||||
@@ -39,7 +40,7 @@
|
||||
set_fact:
|
||||
template_mounts_needed: "{{ docker_mounts | selectattr('template', 'defined') | list | length > 0 }}"
|
||||
volumes_needed: "{{ docker_mounts | selectattr('name', 'defined') | list | length > 0 or docker_database != 'none' }}"
|
||||
dockerfile_needed: "{{ dockerfile is defined and dockerfile | length > 0 }}"
|
||||
dockerfile_needed: "{{ dockerfile | length > 0 }}"
|
||||
db_config_mounts_needed: "{{ docker_mariadb_config | length > 0 }}"
|
||||
- name: Set more assistive variables
|
||||
set_fact:
|
||||
|
||||
@@ -24,10 +24,6 @@
|
||||
include_tasks: proxy.yml
|
||||
when: reverse_proxy_type != 'none'
|
||||
|
||||
- name: Additional services
|
||||
include_tasks: additional.yml
|
||||
when: docker_additional_services is defined
|
||||
|
||||
- name: Create directory /opt/{{ docker_service }}
|
||||
file:
|
||||
path: "/opt/{{ docker_service }}"
|
||||
@@ -80,6 +76,10 @@
|
||||
include_tasks: database.yml
|
||||
when: docker_database != 'none'
|
||||
|
||||
- name: Additional services
|
||||
include_tasks: additional.yml
|
||||
when: docker_additional_services is defined
|
||||
|
||||
- name: Container volumes
|
||||
import_tasks: volumes.yml
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
command: "{{ docker_command | default(omit) }}"
|
||||
restart_policy: always
|
||||
network_mode: "{{ docker_network_mode | default(omit) }}"
|
||||
networks: "{{ container_networks | default(omit) }}"
|
||||
networks: "{{ container_networks }}"
|
||||
log_driver: local
|
||||
register: container_out
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# {{ ansible_managed }}
|
||||
|
||||
FROM {{ docker_image }}
|
||||
{% if dockerfile.run is iterable %}
|
||||
{% for cmd in dockerfile.run %}
|
||||
RUN {{ cmd }}
|
||||
{% for item in dockerfile %}
|
||||
{{ item }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
|
||||
- name: restart docker
|
||||
systemd:
|
||||
- name: Restart docker
|
||||
ansible.builtin.systemd:
|
||||
name: docker.service
|
||||
state: restarted
|
||||
|
||||
5
roles/docker/molecule/default/converge.yml
Normal file
5
roles/docker/molecule/default/converge.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: all
|
||||
roles:
|
||||
- docker
|
||||
15
roles/docker/molecule/default/molecule.yml
Normal file
15
roles/docker/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
|
||||
command: /lib/systemd/systemd
|
||||
pre_build_image: true
|
||||
privileged: true
|
||||
provisioner:
|
||||
name: ansible
|
||||
verifier:
|
||||
name: ansible
|
||||
12
roles/docker/molecule/default/verify.yml
Normal file
12
roles/docker/molecule/default/verify.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Verify
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Docker hello world container
|
||||
community.docker.docker_container:
|
||||
name: hello-world
|
||||
image: hello-world
|
||||
detach: false
|
||||
cleanup: true
|
||||
register: docker_hello_world
|
||||
@@ -1,38 +1,27 @@
|
||||
---
|
||||
|
||||
- name: Install dependencies
|
||||
apt:
|
||||
name:
|
||||
- apt-transport-https
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
update_cache: true
|
||||
|
||||
- name: Set dpkg arch (amd64)
|
||||
set_fact:
|
||||
dpkg_arch: amd64
|
||||
when: ansible_architecture == 'x86_64'
|
||||
- name: Set dpkg arch (arm64)
|
||||
set_fact:
|
||||
dpkg_arch: arm64
|
||||
when: ansible_architecture == 'aarch64'
|
||||
|
||||
- name: Add docker repo signing key
|
||||
apt_key:
|
||||
id: '9DC858229FC7DD38854AE2D88D81803C0EBFCD88'
|
||||
url: 'https://download.docker.com/linux/debian/gpg'
|
||||
- name: Add docker repo
|
||||
apt_repository:
|
||||
repo: "deb [arch={{ dpkg_arch }}] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
|
||||
filename: 'docker'
|
||||
mode: '644'
|
||||
- name: Add docker apt repository
|
||||
ansible.builtin.import_role:
|
||||
name: uumas.general.apt_repository
|
||||
vars:
|
||||
repo_name: docker
|
||||
repo_url: https://download.docker.com/linux/{{ ansible_distribution | lower }}
|
||||
repo_key_url: https://download.docker.com/linux/debian/gpg
|
||||
repo_arch: "{{ apt_arch }}"
|
||||
repo_components:
|
||||
- stable
|
||||
|
||||
- name: Install docker
|
||||
apt:
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-buildx-plugin
|
||||
- python3-docker
|
||||
|
||||
- name: Ensure docker is started and enabled
|
||||
ansible.builtin.systemd:
|
||||
name: docker.service
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
argument_specs:
|
||||
main:
|
||||
short_description: Alpine container
|
||||
description: "Sets up an alpine docker container. This role can be used as a template for other roles using the container role."
|
||||
short_description: Grafana
|
||||
description: "Sets up a grafana docker container"
|
||||
options:
|
||||
database_passwords:
|
||||
description: "Passed to container role"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- name: Reset dockerfile variable
|
||||
set_fact:
|
||||
dockerfile: {}
|
||||
dockerfile: []
|
||||
|
||||
- name: Set docker service full name (required because docker_env uses it)
|
||||
set_fact:
|
||||
@@ -11,14 +11,16 @@
|
||||
|
||||
- name: Add memcached php extension to container
|
||||
set_fact:
|
||||
dockerfile: "{{ dockerfile | combine({'run': \
|
||||
['apt-get update && apt-get install -y libmemcached-dev libssl-dev zlib1g-dev && \
|
||||
pecl install memcached-3.2.0 && docker-php-ext-enable memcached']}, list_merge='append') }}"
|
||||
dockerfile: >
|
||||
"{{ dockerfile +
|
||||
['RUN apt-get update && \
|
||||
apt-get install -y libmemcached-dev libssl-dev zlib1g-dev && \
|
||||
pecl install memcached-3.2.0 && docker-php-ext-enable memcached'] }}"
|
||||
when: "'memcached' in docker_additional_services"
|
||||
|
||||
- name: Add pdo_mysql php extension to container
|
||||
set_fact:
|
||||
dockerfile: "{{ dockerfile | combine({'run': ['docker-php-ext-install -j$(nproc) pdo_mysql']}, list_merge='append') }}"
|
||||
dockerfile: "{{ dockerfile + ['RUN docker-php-ext-install -j$(nproc) pdo_mysql'] }}"
|
||||
when: "'pdo_mysql' in wordpress_php_extensions"
|
||||
|
||||
- name: Include additional volume vars
|
||||
|
||||
Reference in New Issue
Block a user