diff --git a/roles/geerlingguy.docker/.ansible-lint b/roles/geerlingguy.docker/.ansible-lint index affe64fa..2cd8c9f2 100644 --- a/roles/geerlingguy.docker/.ansible-lint +++ b/roles/geerlingguy.docker/.ansible-lint @@ -1,3 +1,4 @@ skip_list: - - '306' - - '106' + - 'yaml' + - 'risky-shell-pipe' + - 'role-name' diff --git a/roles/geerlingguy.docker/.github/stale.yml b/roles/geerlingguy.docker/.github/stale.yml index 3ac21f9a..3e8d9310 100644 --- a/roles/geerlingguy.docker/.github/stale.yml +++ b/roles/geerlingguy.docker/.github/stale.yml @@ -12,6 +12,7 @@ onlyLabels: [] # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable exemptLabels: + - bug - pinned - security - planned diff --git a/roles/geerlingguy.docker/.github/workflows/ci.yml b/roles/geerlingguy.docker/.github/workflows/ci.yml index 6a2fe4a8..1a22d236 100644 --- a/roles/geerlingguy.docker/.github/workflows/ci.yml +++ b/roles/geerlingguy.docker/.github/workflows/ci.yml @@ -29,12 +29,11 @@ jobs: python-version: '3.x' - name: Install test dependencies. - run: pip3 install yamllint ansible-lint + run: pip3 install yamllint - name: Lint code. run: | yamllint . - ansible-lint molecule: name: Molecule @@ -42,13 +41,13 @@ jobs: strategy: matrix: distro: - - centos8 - - centos7 + - rockylinux8 + - ubuntu2204 - ubuntu2004 - ubuntu1804 + - debian11 - debian10 - - debian9 - - fedora33 + - fedora34 steps: - name: Check out the codebase. diff --git a/roles/geerlingguy.docker/.github/workflows/release.yml b/roles/geerlingguy.docker/.github/workflows/release.yml index 5d02a3e6..0b04d243 100644 --- a/roles/geerlingguy.docker/.github/workflows/release.yml +++ b/roles/geerlingguy.docker/.github/workflows/release.yml @@ -32,7 +32,9 @@ jobs: python-version: '3.x' - name: Install Ansible. - run: pip3 install ansible-base + run: pip3 install ansible-core - name: Trigger a new import on Galaxy. - run: ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) + run: >- + ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} + $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) diff --git a/roles/geerlingguy.docker/.gitignore b/roles/geerlingguy.docker/.gitignore index f56f5b57..8840c8f0 100644 --- a/roles/geerlingguy.docker/.gitignore +++ b/roles/geerlingguy.docker/.gitignore @@ -1,3 +1,5 @@ *.retry */__pycache__ *.pyc +.cache + diff --git a/roles/geerlingguy.docker/README.md b/roles/geerlingguy.docker/README.md index 3090374f..953b7dd9 100644 --- a/roles/geerlingguy.docker/README.md +++ b/roles/geerlingguy.docker/README.md @@ -14,40 +14,62 @@ Available variables are listed below, along with default values (see `defaults/m # Edition can be one of: 'ce' (Community Edition) or 'ee' (Enterprise Edition). docker_edition: 'ce' - docker_package: "docker-{{ docker_edition }}" - docker_package_state: present + docker_packages: + - "docker-{{ docker_edition }}" + - "docker-{{ docker_edition }}-cli" + - "docker-{{ docker_edition }}-rootless-extras" + docker_packages_state: present -The `docker_edition` should be either `ce` (Community Edition) or `ee` (Enterprise Edition). You can also specify a specific version of Docker to install using the distribution-specific format: Red Hat/CentOS: `docker-{{ docker_edition }}-`; Debian/Ubuntu: `docker-{{ docker_edition }}=`. +The `docker_edition` should be either `ce` (Community Edition) or `ee` (Enterprise Edition). +You can also specify a specific version of Docker to install using the distribution-specific format: +Red Hat/CentOS: `docker-{{ docker_edition }}-` (Note: you have to add this to all packages); +Debian/Ubuntu: `docker-{{ docker_edition }}=` (Note: you have to add this to all packages). 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_manage: true 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`. +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 `docker_service_manage` to `false`. + + docker_install_compose_plugin: false + docker_compose_package: docker-compose-plugin + docker_compose_package_state: present + +Docker Compose Plugin installation options. These differ from the below in that docker-compose is installed as a docker plugin (and used with `docker compose`) instead of a standalone binary. docker_install_compose: true docker_compose_version: "1.26.0" + docker_compose_arch: "{{ ansible_architecture }}" docker_compose_path: /usr/local/bin/docker-compose Docker Compose installation options. + docker_add_repo: true + +Controls whether this role will add the official Docker repository. Set to `false` if you want to use the default docker packages for your system or manage the package repository on your own. + + docker_repo_url: https://download.docker.com/linux + +The main Docker repo URL, common between Debian and RHEL systems. + 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 }}" + docker_apt_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}" + docker_apt_repository: "deb [arch={{ docker_apt_arch }}] {{ docker_repo_url }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" docker_apt_ignore_key_error: True - docker_apt_gpg_key: https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg + docker_apt_gpg_key: "{{ docker_repo_url }}/{{ ansible_distribution | lower }}/gpg" (Used only for Debian/Ubuntu.) You can switch the channel to `nightly` if you want to use the Nightly release. You can change `docker_apt_gpg_key` to a different url if you are behind a firewall or provide a trustworthy mirror. Usually in combination with changing `docker_apt_repository` as well. - docker_yum_repo_url: https://download.docker.com/linux/centos/docker-{{ docker_edition }}.repo + docker_yum_repo_url: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora','centos') }}/docker-{{ docker_edition }}.repo"docker_edition }}.repo docker_yum_repo_enable_nightly: '0' docker_yum_repo_enable_test: '0' - docker_yum_gpg_key: https://download.docker.com/linux/centos/gpg + docker_yum_gpg_key: "{{ docker_repo_url }}/centos/gpg" (Used only for RedHat/CentOS.) You can enable the Nightly or Test repo by setting the respective vars to `1`. @@ -60,6 +82,13 @@ Usually in combination with changing `docker_yum_repository` as well. A list of system users to be added to the `docker` group (so they can use Docker on the server). + docker_daemon_options: + storage-driver: "devicemapper" + log-opts: + max-size: "100m" + +Custom `dockerd` options can be configured through this dictionary representing the json file `/etc/docker/daemon.json`. + ## Use with Ansible (and `docker` Python library) Many users of this role wish to also use Ansible to then _build_ Docker images and manage Docker containers on the server where Docker is installed. In this case, you can easily add in the `docker` Python library using the `geerlingguy.pip` role: @@ -92,6 +121,12 @@ None. MIT / BSD +## Sponsors + +* [We Manage](https://we-manage.de): Helping start-ups and grown-ups scaling their infrastructure in a sustainable way. + +The above sponsor(s) are supporting Jeff Geerling on [GitHub Sponsors](https://github.com/sponsors/geerlingguy). You can sponsor Jeff's work too, to help him continue improving these Ansible open source projects! + ## Author Information This role was created in 2017 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). diff --git a/roles/geerlingguy.docker/defaults/main.yml b/roles/geerlingguy.docker/defaults/main.yml index 8d660479..870a94c1 100644 --- a/roles/geerlingguy.docker/defaults/main.yml +++ b/roles/geerlingguy.docker/defaults/main.yml @@ -1,31 +1,52 @@ --- # Edition can be one of: 'ce' (Community Edition) or 'ee' (Enterprise Edition). docker_edition: 'ce' -docker_package: "docker-{{ docker_edition }}" -docker_package_state: present +docker_packages: + - "docker-{{ docker_edition }}" + - "docker-{{ docker_edition }}-cli" + - "docker-{{ docker_edition }}-rootless-extras" + - "containerd.io" +docker_packages_state: present # Service options. +docker_service_manage: true docker_service_state: started docker_service_enabled: true docker_restart_handler_state: restarted +# Docker Compose Plugin options. +docker_install_compose_plugin: false +docker_compose_package: docker-compose-plugin +docker_compose_package_state: present + # Docker Compose options. docker_install_compose: true -docker_compose_version: "1.26.0" +docker_compose_version: "v2.11.1" +docker_compose_arch: "{{ ansible_architecture }}" +docker_compose_url: "https://github.com/docker/compose/releases/download/{{ docker_compose_version }}/docker-compose-linux-{{ docker_compose_arch }}" docker_compose_path: /usr/local/bin/docker-compose +# Enable repo setup +docker_add_repo: true + +# Docker repo URL. +docker_repo_url: https://download.docker.com/linux + # Used only for Debian/Ubuntu. Switch 'stable' to 'nightly' if needed. 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 }}" +docker_apt_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}" +docker_apt_repository: "deb [arch={{ docker_apt_arch }}] {{ docker_repo_url }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" docker_apt_ignore_key_error: true -docker_apt_gpg_key: https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg +docker_apt_gpg_key: "{{ docker_repo_url }}/{{ ansible_distribution | lower }}/gpg" # Used only for RedHat/CentOS/Fedora. -docker_yum_repo_url: https://download.docker.com/linux/{{ (ansible_distribution == "Fedora") | ternary("fedora","centos") }}/docker-{{ docker_edition }}.repo +docker_yum_repo_url: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora','centos') }}/docker-{{ docker_edition }}.repo" docker_yum_repo_enable_nightly: '0' docker_yum_repo_enable_test: '0' -docker_yum_gpg_key: https://download.docker.com/linux/centos/gpg +docker_yum_gpg_key: "{{ docker_repo_url }}/centos/gpg" # A list of users who will be added to the docker group. docker_users: [] + +# Docker daemon options as a dict +docker_daemon_options: {} diff --git a/roles/geerlingguy.docker/handlers/main.yml b/roles/geerlingguy.docker/handlers/main.yml index 7847bc1c..72594c8c 100644 --- a/roles/geerlingguy.docker/handlers/main.yml +++ b/roles/geerlingguy.docker/handlers/main.yml @@ -1,3 +1,7 @@ --- - name: restart docker - service: "name=docker state={{ docker_restart_handler_state }}" + service: + name: docker + state: "{{ docker_restart_handler_state }}" + ignore_errors: "{{ ansible_check_mode }}" + when: docker_service_manage | bool diff --git a/roles/geerlingguy.docker/meta/main.yml b/roles/geerlingguy.docker/meta/main.yml index fc017275..edc5f8ed 100644 --- a/roles/geerlingguy.docker/meta/main.yml +++ b/roles/geerlingguy.docker/meta/main.yml @@ -18,13 +18,19 @@ galaxy_info: - all - name: Debian versions: - - stretch - buster + - bullseye - name: Ubuntu versions: - - xenial - bionic - focal + - jammy + - name: Alpine + version: + - all + - name: ArchLinux + versions: + - all galaxy_tags: - web - system diff --git a/roles/geerlingguy.docker/molecule/default/molecule.yml b/roles/geerlingguy.docker/molecule/default/molecule.yml index 74907107..d291e5b6 100644 --- a/roles/geerlingguy.docker/molecule/default/molecule.yml +++ b/roles/geerlingguy.docker/molecule/default/molecule.yml @@ -1,4 +1,5 @@ --- +role_name_check: 1 dependency: name: galaxy driver: @@ -8,7 +9,8 @@ platforms: image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest" command: ${MOLECULE_DOCKER_COMMAND:-""} volumes: - - /sys/fs/cgroup:/sys/fs/cgroup:ro + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host privileged: true pre_build_image: true provisioner: diff --git a/roles/geerlingguy.docker/tasks/docker-compose.yml b/roles/geerlingguy.docker/tasks/docker-compose.yml index 92cf4f27..53a44822 100644 --- a/roles/geerlingguy.docker/tasks/docker-compose.yml +++ b/roles/geerlingguy.docker/tasks/docker-compose.yml @@ -1,20 +1,31 @@ --- - name: Check current docker-compose version. - command: docker-compose --version - register: docker_compose_current_version + command: "{{ docker_compose_path }} --version" + register: docker_compose_vsn + check_mode: false changed_when: false failed_when: false +- set_fact: + docker_compose_current_version: "{{ docker_compose_vsn.stdout | regex_search('(\\d+(\\.\\d+)+)') }}" + when: > + docker_compose_vsn.stdout is defined + and (docker_compose_vsn.stdout | length > 0) + - name: Delete existing docker-compose version if it's different. file: path: "{{ docker_compose_path }}" state: absent when: > - docker_compose_current_version.stdout is defined - and docker_compose_version not in docker_compose_current_version.stdout + docker_compose_current_version is defined + and (docker_compose_version | regex_replace('v', '')) not in docker_compose_current_version - name: Install Docker Compose (if configured). get_url: - url: https://github.com/docker/compose/releases/download/{{ docker_compose_version }}/docker-compose-Linux-x86_64 + url: "{{ docker_compose_url }}" dest: "{{ docker_compose_path }}" mode: 0755 + when: > + (docker_compose_current_version is not defined) + or (docker_compose_current_version | length == 0) + or (docker_compose_current_version is version((docker_compose_version | regex_replace('v', '')), '<')) diff --git a/roles/geerlingguy.docker/tasks/docker-users.yml b/roles/geerlingguy.docker/tasks/docker-users.yml index b3b6e0f1..6e387e66 100644 --- a/roles/geerlingguy.docker/tasks/docker-users.yml +++ b/roles/geerlingguy.docker/tasks/docker-users.yml @@ -5,3 +5,6 @@ groups: docker append: true with_items: "{{ docker_users }}" + +- name: Reset ssh connection to apply user changes. + meta: reset_connection diff --git a/roles/geerlingguy.docker/tasks/main.yml b/roles/geerlingguy.docker/tasks/main.yml index 56449ef7..dcd47dec 100644 --- a/roles/geerlingguy.docker/tasks/main.yml +++ b/roles/geerlingguy.docker/tasks/main.yml @@ -1,14 +1,68 @@ --- +- name: Load OS-specific vars. + include_vars: "{{ lookup('first_found', params) }}" + vars: + params: + files: + - '{{ansible_distribution}}.yml' + - '{{ansible_os_family}}.yml' + - main.yml + paths: + - 'vars' + - include_tasks: setup-RedHat.yml when: ansible_os_family == 'RedHat' - include_tasks: setup-Debian.yml when: ansible_os_family == 'Debian' -- name: Install Docker. +- name: Install Docker packages. package: - name: "{{ docker_package }}" - state: "{{ docker_package_state }}" + name: "{{ docker_packages }}" + state: "{{ docker_packages_state }}" + notify: restart docker + ignore_errors: "{{ ansible_check_mode }}" + when: "ansible_version.full is version_compare('2.12', '<') or ansible_os_family not in ['RedHat', 'Debian']" + +- name: Install Docker packages (with downgrade option). + package: + name: "{{ docker_packages }}" + state: "{{ docker_packages_state }}" + allow_downgrade: true + notify: restart docker + ignore_errors: "{{ ansible_check_mode }}" + when: "ansible_version.full is version_compare('2.12', '>=') and ansible_os_family in ['RedHat', 'Debian']" + +- name: Install docker-compose plugin. + package: + name: "{{ docker_compose_package }}" + state: "{{ docker_compose_package_state }}" + notify: restart docker + ignore_errors: "{{ ansible_check_mode }}" + when: "docker_install_compose_plugin | bool == true and (ansible_version.full is version_compare('2.12', '<') or ansible_os_family not in ['RedHat', 'Debian'])" + +- name: Install docker-compose-plugin (with downgrade option). + package: + name: "{{ docker_compose_package }}" + state: "{{ docker_compose_package_state }}" + allow_downgrade: true + notify: restart docker + ignore_errors: "{{ ansible_check_mode }}" + when: "docker_install_compose_plugin | bool == true and ansible_version.full is version_compare('2.12', '>=') and ansible_os_family in ['RedHat', 'Debian']" + +- name: Ensure /etc/docker/ directory exists. + file: + path: /etc/docker + state: directory + mode: 0755 + when: docker_daemon_options.keys() | length > 0 + +- name: Configure Docker daemon options. + copy: + content: "{{ docker_daemon_options | to_nice_json }}" + dest: /etc/docker/daemon.json + mode: 0644 + when: docker_daemon_options.keys() | length > 0 notify: restart docker - name: Ensure Docker is started and enabled at boot. @@ -16,6 +70,8 @@ name: docker state: "{{ docker_service_state }}" enabled: "{{ docker_service_enabled }}" + ignore_errors: "{{ ansible_check_mode }}" + when: docker_service_manage | bool - name: Ensure handlers are notified now to avoid firewall conflicts. meta: flush_handlers @@ -23,5 +79,20 @@ - include_tasks: docker-compose.yml when: docker_install_compose | bool -- include_tasks: docker-users.yml +- name: Get docker group info using getent. + getent: + database: group + key: docker + split: ':' when: docker_users | length > 0 + +- name: Check if there are any users to add to the docker group. + set_fact: + at_least_one_user_to_modify: true + when: + - docker_users | length > 0 + - item not in ansible_facts.getent_group["docker"][2] + with_items: "{{ docker_users }}" + +- include_tasks: docker-users.yml + when: at_least_one_user_to_modify is defined diff --git a/roles/geerlingguy.docker/tasks/setup-Debian.yml b/roles/geerlingguy.docker/tasks/setup-Debian.yml index d701135b..0abcd173 100644 --- a/roles/geerlingguy.docker/tasks/setup-Debian.yml +++ b/roles/geerlingguy.docker/tasks/setup-Debian.yml @@ -11,30 +11,43 @@ name: - apt-transport-https - ca-certificates - - gnupg2 state: present + when: docker_add_repo | bool + +- name: Ensure additional dependencies are installed (on Ubuntu < 20.04 and any other systems). + apt: + name: gnupg2 + state: present + when: ansible_distribution != 'Ubuntu' or ansible_distribution_version is version('20.04', '<') + +- name: Ensure additional dependencies are installed (on Ubuntu >= 20.04). + apt: + name: gnupg + state: present + when: ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('20.04', '>=') - name: Add Docker apt key. - apt_key: + ansible.builtin.get_url: url: "{{ docker_apt_gpg_key }}" - id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88 - state: present + dest: /etc/apt/trusted.gpg.d/docker.asc + mode: '0644' + force: true register: add_repository_key ignore_errors: "{{ docker_apt_ignore_key_error }}" + when: docker_add_repo | bool - name: Ensure curl is present (on older systems without SNI). package: name=curl state=present - when: add_repository_key is failed + when: add_repository_key is failed and docker_add_repo | bool - name: Add Docker apt key (alternative for older systems without SNI). shell: > - curl -sSL {{ docker_apt_gpg_key }} | sudo apt-key add - - args: - warn: false - when: add_repository_key is failed + curl -sSL {{ docker_apt_gpg_key }} | apt-key add - + when: add_repository_key is failed and docker_add_repo | bool - name: Add Docker repository. apt_repository: repo: "{{ docker_apt_repository }}" state: present update_cache: true + when: docker_add_repo | bool diff --git a/roles/geerlingguy.docker/tasks/setup-RedHat.yml b/roles/geerlingguy.docker/tasks/setup-RedHat.yml index 96072385..ad337c40 100644 --- a/roles/geerlingguy.docker/tasks/setup-RedHat.yml +++ b/roles/geerlingguy.docker/tasks/setup-RedHat.yml @@ -11,6 +11,7 @@ rpm_key: key: "{{ docker_yum_gpg_key }}" state: present + when: docker_add_repo | bool - name: Add Docker repository. get_url: @@ -19,6 +20,7 @@ owner: root group: root mode: 0644 + when: docker_add_repo | bool - name: Configure Docker Nightly repo. ini_file: @@ -27,6 +29,8 @@ option: enabled value: '{{ docker_yum_repo_enable_nightly }}' mode: 0644 + no_extra_spaces: true + when: docker_add_repo | bool - name: Configure Docker Test repo. ini_file: @@ -35,6 +39,8 @@ option: enabled value: '{{ docker_yum_repo_enable_test }}' mode: 0644 + no_extra_spaces: true + when: docker_add_repo | bool - name: Configure containerd on RHEL 8. block: diff --git a/roles/geerlingguy.docker/vars/Alpine.yml b/roles/geerlingguy.docker/vars/Alpine.yml new file mode 100644 index 00000000..b81917a4 --- /dev/null +++ b/roles/geerlingguy.docker/vars/Alpine.yml @@ -0,0 +1,2 @@ +--- +docker_packages: "docker" diff --git a/roles/geerlingguy.docker/vars/Archlinux.yml b/roles/geerlingguy.docker/vars/Archlinux.yml new file mode 100644 index 00000000..b81917a4 --- /dev/null +++ b/roles/geerlingguy.docker/vars/Archlinux.yml @@ -0,0 +1,2 @@ +--- +docker_packages: "docker" diff --git a/roles/geerlingguy.docker/vars/main.yml b/roles/geerlingguy.docker/vars/main.yml new file mode 100644 index 00000000..805232bf --- /dev/null +++ b/roles/geerlingguy.docker/vars/main.yml @@ -0,0 +1,2 @@ +--- +# Empty file