From 3715c77f3816a853cc45351684908c3d9575b158 Mon Sep 17 00:00:00 2001 From: uzurka Date: Thu, 19 Dec 2024 22:09:56 +0100 Subject: [PATCH] initial commit --- .gitignore | 1 + .gitlab-ci.yml | 14 +++++ .yamllint | 8 +++ LICENSE | 20 ++++++++ README.md | 101 ++++++++++++++++++++++++++++++++++++ defaults/main.yml | 35 +++++++++++++ handlers/main.yml | 5 ++ meta/.galaxy_install_info | 2 + meta/main.yml | 13 +++++ tasks/install.yml | 60 ++++++++++++++++++++++ tasks/main.yml | 77 ++++++++++++++++++++++++++++ tasks/swarm.yml | 105 ++++++++++++++++++++++++++++++++++++++ vars/python2.yml | 7 +++ vars/python3.yml | 5 ++ 14 files changed, 453 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .yamllint create mode 100644 LICENSE create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/.galaxy_install_info create mode 100644 meta/main.yml create mode 100644 tasks/install.yml create mode 100644 tasks/main.yml create mode 100644 tasks/swarm.yml create mode 100644 vars/python2.yml create mode 100644 vars/python3.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ceddaa3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.cache/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..86555d7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,14 @@ +--- +stages: + - validate + +.template: + interruptible: true + stage: validate + tags: + - ansible + +yamllint: + extends: .template + script: + - yamllint -c .yamllint . diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..edb5f24 --- /dev/null +++ b/.yamllint @@ -0,0 +1,8 @@ +--- +extends: default + +ignore: | + .cache/ + +rules: + line-length: disable diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94c3355 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) NoxInmortus (Alban E.G.) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc48898 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# Ansible Role: Docker + +An Ansible Role that installs [Docker](https://www.docker.com) for Debian. This role allows to add `docker` group to users, can also manage docker networks and containers. + +## Role Variables + +Available variables are listed below, along with default values (see `defaults/main.yml`): + +### Docker package +```yaml +# Edition can be one of: 'ce' (Community Edition) or 'ee' (Enterprise Edition). +docker_edition: 'ce' +docker_package: "docker-{{ docker_edition }}" +docker_package_state: present +``` + +You can control whether the package is installed, uninstalled, or at the latest version by setting `docker_package_state` to `present`, `absent`, or `latest`, respectively. Note that the Docker daemon will be automatically restarted if the Docker package is updated. This is a side effect of flushing all handlers (running any of the handlers that have been notified by this and any other role up to this point in the play). + +### Docker service state +```yaml +docker_service_state: started +docker_service_enabled: true +docker_restart_handler_state: restarted +``` + +Variables to control the state of the `docker` service, and whether it should start on boot. If you're installing Docker inside a Docker container without systemd or sysvinit, you should set these to `stopped` and set the enabled variable to `no`. + +### Docker installation +```yaml + docker_apt_release_channel: stable + docker_apt_arch: amd64 + docker_apt_repository: "deb [arch={{ docker_apt_arch }}] https://download.docker.com/linux/{{ ansible_distribution|lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" +``` + +You can switch the channel to `edge` if you want to use the Edge release. + +### Docker users +```yaml +docker_users: + - user1 + - user2 +``` + +A list of system users to be added to the `docker` group (so they can use Docker on the server). + +### Docker networks +See official documentation for `docker_network` module for more informations. + +```yaml +docker_networks: + - name: network1 + - name: network2 + state: absent +``` + +A list of docker networks to manage. + +### Docker containers +See official documentation for `docker_container` module for more informations. +```yaml +docker_containers: + - name: postgres + image: postgres:9.6 + state: started + restart_policy: unless-stopped + env: + POSTGRES_USER: foo + POSTGRES_PASSWORD: bar + POSTGRES_DB: baz + - name: memcached + image: memcached:alpine + state: started + restart_policy: unless-stopped + - name: elasticsearch + image: docker.elastic.co/elasticsearch/elasticsearch:5.6.13 + state: started + restart_policy: unless-stopped + memory: 1g + ulimits: + - memlock:-1:-1 # :: +``` + +### Tags + +| Tag | DESCRIPTION | +|-----------------------|-------------------------| +| docker | Global tag | +| docker_asserts | Asserts tasks | +| docker_install | Install docker | +| docker_users | Configure docker users | +| docker_networks | Configure docker networks | +| docker_containers | Deploy docker containers | + +## License +MIT view [LICENSE](LICENSE) + +## Sources +- https://github.com/geerlingguy/ansible-role-docker +- https://github.com/manala/ansible-roles/tree/master/manala.docker +- https://docs.ansible.com/ansible/latest/modules/docker_container_module.html +- https://github.com/atosatto/ansible-dockerswarm/ diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..5d8b357 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,35 @@ +--- +# Edition can be one of: 'ce' (Community Edition) or 'ee' (Enterprise Edition). +docker_edition: 'ce' +docker_package: "docker-{{ docker_edition }}" +docker_package_state: present + +# Packages dependencies +docker_apt_dependencies: + - ca-certificates + - curl +docker_pip_dependencies: + - docker + +# Service options. +docker_service_state: started +docker_service_enabled: true +docker_restart_handler_state: restarted + +# Switch 'stable' to 'edge' if needed. +docker_apt_release_channel: stable +docker_apt_arch: amd64 +docker_apt_repository: "deb [arch={{ docker_apt_arch }} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/{{ ansible_distribution|lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" + +# Swarm options +docker_swarm_enable: false +# Docker swarm network can be define in order to be sure that +# swarm cluster doesn't overlap with you infrastructure +# docker_swarm_network: 10.10.8.0/24 + +# You can set any interface, that is listened by docker engine. +# e.g. docker_swarm_interface: "eth1" +docker_swarm_interface: "{{ ansible_default_ipv4['interface'] }}" +docker_swarm_addr: "{{ hostvars[inventory_hostname]['ansible_' + docker_swarm_interface]['ipv4']['address'] }}" +docker_swarm_master: "{{ groups['docker_swarm_manager'][0] }}" +docker_swarm_port: 2377 diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..4d5a779 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart_docker + service: + name: docker + state: "{{ docker_restart_handler_state }}" diff --git a/meta/.galaxy_install_info b/meta/.galaxy_install_info new file mode 100644 index 0000000..d422884 --- /dev/null +++ b/meta/.galaxy_install_info @@ -0,0 +1,2 @@ +install_date: 'Sun 16 Jun 2024 04:56:38 PM ' +version: '' diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..cb5042e --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,13 @@ +--- +galaxy_info: + author: Alban E. + description: Docker for Linux. + company: Imperium + license: MIT + min_ansible_version: 2.4 + platforms: + - name: Debian + versions: + - jessie + - stretch + - buster diff --git a/tasks/install.yml b/tasks/install.yml new file mode 100644 index 0000000..bc085ef --- /dev/null +++ b/tasks/install.yml @@ -0,0 +1,60 @@ +--- +- include_vars: python2.yml + when: ansible_python_version[:1] == '2' + tags: + - docker + - docker_install + +- include_vars: python3.yml + when: ansible_python_version[:1] == '3' + tags: + - docker + - docker_install + +- name: Docker install | Add Docker apt key + get_url: + url: https://download.docker.com/linux/debian/gpg + dest: /etc/apt/keyrings/docker.asc + checksum: sha256:1500c1f56fa9e26b9b8f42452a553675796ade0807cdce11975eb98170b3a570 + tags: + - docker + - docker_install + +- name: Docker install | Add Docker repository + apt_repository: + repo: '{{ docker_apt_repository }}' + update_cache: true + tags: + - docker + - docker_install + +- name: Docker install | Install apt packages + package: + name: '{{ item }}' + state: '{{ docker_package_state }}' + with_items: + - '{{ docker_package }}' + - '{{ docker_apt_dependencies }}' + - '{{ docker_apt_python_dependencies }}' + tags: + - docker + - docker_install + +- name: Docker install | Install Docker Python library + pip: + name: '{{ docker_pip_dependencies }}' + state: '{{ docker_package_state }}' + executable: '{{ docker_pip_executable }}' + tags: + - docker + - docker_install + when: ansible_python_version[:1] == '2' + +- name: Docker install | Ensure Docker is started and enabled at boot + service: + name: docker + state: '{{ docker_service_state }}' + enabled: '{{ docker_service_enabled }}' + tags: + - docker + - docker_install diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..c8a2e41 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,77 @@ +--- +- name: Docker | Check if ansible version >= 2.4 + assert: + that: "ansible_version.full is version_compare(2.4, '>=')" + msg: "Ansible 2.4 or superior version is required." + tags: + - docker + - docker_asserts + - docker_install + - docker_users + - docker_networks + - docker_containers + +- include_tasks: install.yml + tags: + - docker + - docker_install + +- name: Docker | Ensure docker users are added to the docker group + user: + name: "{{ item }}" + groups: docker + append: true + with_items: "{{ docker_users|default([]) }}" + when: docker_users + tags: + - docker + - docker_users + +- include_tasks: swarm.yml + when: docker_swarm_enable + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Assign default labels to swarm nodes + docker_node: + debug: '{{ docker_node.debug|default(omit) }}' + hostname: '{{ docker_node.hostname|default(inventory_hostname) }}' + labels: '{{ docker_node.labels|default(omit) }}' + role: '{{ docker_node.role|default(omit) }}' + availability: '{{ docker_node.availability|default(omit) }}' + labels_state: '{{ docker_node.labels_state|default(omit) }}' + labels_to_remove: '{{ docker_node.labels_to_remove|default(omit) }}' + delegate_to: "{{ groups['docker_swarm_manager'][0] }}" + when: docker_swarm_enable + tags: + - docker + - docker_swarm + - docker_swarm_labels + +- name: Docker | Create docker networks + docker_network: + "{{ item }}" + loop: "{{ docker_networks|default([]) }}" + tags: + - docker + - docker_networks + +- name: Docker | Create docker containers + docker_container: + "{{ item }}" + loop: "{{ docker_containers|default([]) }}" + tags: + - docker + - docker_containers + +- name: Docker | Create docker swarm services + docker_swarm_service: + "{{ item }}" + loop: "{{ docker_swarm_services|default([]) }}" + when: docker_swarm_enable + tags: + - docker + - docker_swarm + - docker_swarm_services diff --git a/tasks/swarm.yml b/tasks/swarm.yml new file mode 100644 index 0000000..98c7d3e --- /dev/null +++ b/tasks/swarm.yml @@ -0,0 +1,105 @@ +--- +- name: Create a custom Swarm network. + docker_network: + name: docker_gwbridge + driver_options: + com.docker.network.bridge.enable_icc: "false" + com.docker.network.bridge.enable_ip_masquerade: "true" + com.docker.network.bridge.name: docker_gwbridge + ipam_options: + subnet: "{{ docker_swarm_network }}" + gateway: "{{ docker_swarm_network | ipaddr('net') | ipaddr('1') | ipaddr('ip') }}" + when: docker_swarm_network is defined and docker_swarm_network | ipaddr('net') + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Check if "Swarm Mode" is enabled. + shell: docker info + changed_when: false + check_mode: false + register: docker_info + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Init "Swarm Mode" on the first manager. + shell: docker swarm init + --listen-addr {{ docker_swarm_addr }}:{{ docker_swarm_port }} + --advertise-addr {{ docker_swarm_addr }} + when: "docker_info.stdout.find('Swarm: active') == -1 + and inventory_hostname == groups['docker_swarm_manager'][0]" + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Get the worker join-token. + shell: docker swarm join-token -q worker + changed_when: false + check_mode: false + register: docker_worker_token + delegate_to: "{{ groups['docker_swarm_manager'][0] }}" + delegate_facts: true + when: "'docker_swarm_worker' in group_names" + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Get the manager join-token. + shell: docker swarm join-token -q manager + changed_when: false + check_mode: false + register: docker_manager_token + delegate_to: "{{ groups['docker_swarm_manager'][0] }}" + delegate_facts: true + when: "'docker_swarm_manager' in group_names + and inventory_hostname != groups['docker_swarm_manager'][0]" + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Declare the address of the first Swarm manager as a fact. + set_fact: + docker_manager_address: "{{ groups['docker_swarm_manager'][0] }}:{{ docker_swarm_port }}" + check_mode: false + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Join the pending Swarm worker nodes. + shell: docker swarm join + --listen-addr {{ docker_swarm_addr }}:{{ docker_swarm_port }} + --advertise-addr {{ docker_swarm_addr }} + --token "{{ docker_worker_token.stdout }}" + {{ docker_manager_address }} + changed_when: false + when: "docker_info.stdout.find('Swarm: active') == -1 + and docker_info.stdout.find('Swarm: pending') == -1 + and 'docker_swarm_worker' in group_names + and 'docker_swarm_manager' not in group_names" + tags: + - docker + - docker_swarm + - docker_swarm_init + +- name: Join the pending Swarm manager nodes. + shell: docker swarm join + --listen-addr {{ docker_swarm_addr }}:{{ docker_swarm_port }} + --advertise-addr {{ docker_swarm_addr }} + --token "{{ docker_manager_token.stdout }}" + {{ docker_manager_address }} + changed_when: false + when: "docker_info.stdout.find('Swarm: active') == -1 + and docker_info.stdout.find('Swarm: pending') == -1 + and 'docker_swarm_manager' in group_names + and inventory_hostname != groups['docker_swarm_manager'][0]" + tags: + - docker + - docker_swarm + - docker_swarm_init diff --git a/vars/python2.yml b/vars/python2.yml new file mode 100644 index 0000000..7085c53 --- /dev/null +++ b/vars/python2.yml @@ -0,0 +1,7 @@ +--- +docker_apt_python_dependencies: + - python + - python-pip + - python-backports.ssl-match-hostname + +docker_pip_executable: pip2 diff --git a/vars/python3.yml b/vars/python3.yml new file mode 100644 index 0000000..d65f7bc --- /dev/null +++ b/vars/python3.yml @@ -0,0 +1,5 @@ +--- +docker_apt_python_dependencies: + - python3 + - python3-pip + - python3-docker