├── .ansible-lint ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ ├── release.yml │ └── stale.yml ├── .gitignore ├── .yamllint ├── LICENSE ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── molecule └── default │ ├── converge.yml │ ├── molecule.yml │ └── verify.yml ├── tasks ├── docker-compose.yml ├── docker-users.yml ├── main.yml ├── setup-Debian.yml └── setup-RedHat.yml └── vars ├── Alpine.yml ├── Archlinux.yml ├── Debian.yml ├── RedHat.yml └── main.yml /.ansible-lint: -------------------------------------------------------------------------------- 1 | skip_list: 2 | - 'yaml' 3 | - 'risky-shell-pipe' 4 | - 'role-name' 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | --- 3 | github: geerlingguy 4 | patreon: geerlingguy 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 'on': 4 | pull_request: 5 | push: 6 | branches: 7 | - master 8 | schedule: 9 | - cron: "0 7 * * 0" 10 | 11 | defaults: 12 | run: 13 | working-directory: 'geerlingguy.docker' 14 | 15 | jobs: 16 | 17 | lint: 18 | name: Lint 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Check out the codebase. 22 | uses: actions/checkout@v4 23 | with: 24 | path: 'geerlingguy.docker' 25 | 26 | - name: Set up Python 3. 27 | uses: actions/setup-python@v5 28 | with: 29 | python-version: '3.x' 30 | 31 | - name: Install test dependencies. 32 | run: pip3 install yamllint 33 | 34 | - name: Lint code. 35 | run: | 36 | yamllint . 37 | 38 | molecule: 39 | name: Molecule 40 | runs-on: ubuntu-latest 41 | strategy: 42 | matrix: 43 | distro: 44 | - rockylinux9 45 | - ubuntu2404 46 | - ubuntu2204 47 | - debian12 48 | - debian11 49 | - fedora40 50 | 51 | steps: 52 | - name: Check out the codebase. 53 | uses: actions/checkout@v4 54 | with: 55 | path: 'geerlingguy.docker' 56 | 57 | - name: Set up Python 3. 58 | uses: actions/setup-python@v5 59 | with: 60 | python-version: '3.x' 61 | 62 | - name: Install test dependencies. 63 | run: pip3 install ansible molecule molecule-plugins[docker] docker 64 | 65 | - name: Run Molecule tests. 66 | run: molecule test 67 | env: 68 | PY_COLORS: '1' 69 | ANSIBLE_FORCE_COLOR: '1' 70 | MOLECULE_DISTRO: ${{ matrix.distro }} 71 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This workflow requires a GALAXY_API_KEY secret present in the GitHub 3 | # repository or organization. 4 | # 5 | # See: https://github.com/marketplace/actions/publish-ansible-role-to-galaxy 6 | # See: https://github.com/ansible/galaxy/issues/46 7 | 8 | name: Release 9 | 'on': 10 | push: 11 | tags: 12 | - '*' 13 | 14 | defaults: 15 | run: 16 | working-directory: 'geerlingguy.docker' 17 | 18 | jobs: 19 | 20 | release: 21 | name: Release 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Check out the codebase. 25 | uses: actions/checkout@v4 26 | with: 27 | path: 'geerlingguy.docker' 28 | 29 | - name: Set up Python 3. 30 | uses: actions/setup-python@v5 31 | with: 32 | python-version: '3.x' 33 | 34 | - name: Install Ansible. 35 | run: pip3 install ansible-core 36 | 37 | - name: Trigger a new import on Galaxy. 38 | run: >- 39 | ansible-galaxy role import --api-key ${{ secrets.GALAXY_API_KEY }} 40 | $(echo ${{ github.repository }} | cut -d/ -f1) $(echo ${{ github.repository }} | cut -d/ -f2) 41 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Close inactive issues 3 | 'on': 4 | schedule: 5 | - cron: "55 6 * * 1" # semi-random time 6 | 7 | jobs: 8 | close-issues: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - uses: actions/stale@v8 15 | with: 16 | days-before-stale: 120 17 | days-before-close: 60 18 | exempt-issue-labels: bug,pinned,security,planned 19 | exempt-pr-labels: bug,pinned,security,planned 20 | stale-issue-label: "stale" 21 | stale-pr-label: "stale" 22 | stale-issue-message: | 23 | This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 24 | 25 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 26 | close-issue-message: | 27 | This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 28 | stale-pr-message: | 29 | This pr has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 30 | 31 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 32 | close-pr-message: | 33 | This pr has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 34 | repo-token: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | */__pycache__ 3 | *.pyc 4 | .cache 5 | 6 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | line-length: 6 | max: 200 7 | level: warning 8 | 9 | ignore: | 10 | .github/workflows/stale.yml 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Jeff Geerling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Role: Docker 2 | 3 | [![CI](https://github.com/geerlingguy/ansible-role-docker/actions/workflows/ci.yml/badge.svg)](https://github.com/geerlingguy/ansible-role-docker/actions/workflows/ci.yml) 4 | 5 | An Ansible Role that installs [Docker](https://www.docker.com) on Linux. 6 | 7 | ## Requirements 8 | 9 | None. 10 | 11 | ## Role Variables 12 | 13 | Available variables are listed below, along with default values (see `defaults/main.yml`): 14 | 15 | ```yaml 16 | # Edition can be one of: 'ce' (Community Edition) or 'ee' (Enterprise Edition). 17 | docker_edition: 'ce' 18 | docker_packages: 19 | - "docker-{{ docker_edition }}" 20 | - "docker-{{ docker_edition }}-cli" 21 | - "docker-{{ docker_edition }}-rootless-extras" 22 | docker_packages_state: present 23 | ``` 24 | 25 | The `docker_edition` should be either `ce` (Community Edition) or `ee` (Enterprise Edition). 26 | You can also specify a specific version of Docker to install using the distribution-specific format: 27 | Red Hat/CentOS: `docker-{{ docker_edition }}-` (Note: you have to add this to all packages); 28 | Debian/Ubuntu: `docker-{{ docker_edition }}=` (Note: you have to add this to all packages). 29 | 30 | You can control whether the package is installed, uninstalled, or at the latest version by setting `docker_packages_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). 31 | 32 | ```yaml 33 | docker_obsolete_packages: 34 | - docker 35 | - docker.io 36 | - docker-engine 37 | - docker-doc 38 | - docker-compose 39 | - docker-compose-v2 40 | - podman-docker 41 | - containerd 42 | - runc 43 | ``` 44 | 45 | `docker_obsolete_packages` for different os-family: 46 | 47 | - [`RedHat.yaml`](./vars/RedHat.yml) 48 | - [`Debian.yaml`](./vars/Debian.yml) 49 | 50 | A list of packages to be uninstalled prior to running this role. See [Docker's installation instructions](https://docs.docker.com/engine/install/debian/#uninstall-old-versions) for an up-to-date list of old packages that should be removed. 51 | 52 | ```yaml 53 | docker_service_manage: true 54 | docker_service_state: started 55 | docker_service_enabled: true 56 | docker_restart_handler_state: restarted 57 | ``` 58 | 59 | 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`. 60 | 61 | ```yaml 62 | docker_install_compose_plugin: true 63 | docker_compose_package: docker-compose-plugin 64 | docker_compose_package_state: present 65 | ``` 66 | 67 | 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. 68 | 69 | ```yaml 70 | docker_install_compose: false 71 | docker_compose_version: "v2.32.1" 72 | docker_compose_arch: "{{ ansible_architecture }}" 73 | docker_compose_url: "https://github.com/docker/compose/releases/download/{{ docker_compose_version }}/docker-compose-linux-{{ docker_compose_arch }}" 74 | docker_compose_path: /usr/local/bin/docker-compose 75 | ``` 76 | 77 | Docker Compose installation options. 78 | 79 | ```yaml 80 | docker_add_repo: true 81 | ``` 82 | 83 | 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. 84 | 85 | ```yaml 86 | docker_repo_url: https://download.docker.com/linux 87 | ``` 88 | 89 | The main Docker repo URL, common between Debian and RHEL systems. 90 | 91 | ```yaml 92 | docker_apt_release_channel: stable 93 | docker_apt_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}" 94 | docker_apt_repository: "deb [arch={{ docker_apt_arch }}{{' signed-by=/etc/apt/keyrings/docker.asc' if add_repository_key is not failed}}] {{ docker_repo_url }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" 95 | docker_apt_ignore_key_error: True 96 | docker_apt_gpg_key: "{{ docker_repo_url }}/{{ ansible_distribution | lower }}/gpg" 97 | docker_apt_filename: "docker" 98 | ``` 99 | 100 | (Used only for Debian/Ubuntu.) You can switch the channel to `nightly` if you want to use the Nightly release. 101 | 102 | You can change `docker_apt_gpg_key` to a different url if you are behind a firewall or provide a trustworthy mirror. 103 | Usually in combination with changing `docker_apt_repository` as well. `docker_apt_filename` controls the name of the source list file created in `sources.list.d`. If you are upgrading from an older (<7.0.0) version of this role, you should change this to the name of the existing file (e.g. `download_docker_com_linux_debian` on Debian) to avoid conflicting lists. 104 | 105 | ```yaml 106 | docker_yum_repo_url: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora','centos') }}/docker-{{ docker_edition }}.repo" 107 | docker_yum_repo_enable_nightly: '0' 108 | docker_yum_repo_enable_test: '0' 109 | docker_yum_gpg_key: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora', 'centos') }}/gpg" 110 | ``` 111 | 112 | (Used only for RedHat/CentOS.) You can enable the Nightly or Test repo by setting the respective vars to `1`. 113 | 114 | You can change `docker_yum_gpg_key` to a different url if you are behind a firewall or provide a trustworthy mirror. 115 | Usually in combination with changing `docker_yum_repository` as well. 116 | 117 | ```yaml 118 | docker_users: 119 | - user1 120 | - user2 121 | ``` 122 | 123 | A list of system users to be added to the `docker` group (so they can use Docker on the server). 124 | 125 | ```yaml 126 | docker_daemon_options: 127 | storage-driver: "overlay2" 128 | log-opts: 129 | max-size: "100m" 130 | ``` 131 | 132 | Custom `dockerd` options can be configured through this dictionary representing the json file `/etc/docker/daemon.json`. 133 | 134 | ## Use with Ansible (and `docker` Python library) 135 | 136 | 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: 137 | 138 | ```yaml 139 | - hosts: all 140 | 141 | vars: 142 | pip_install_packages: 143 | - name: docker 144 | 145 | roles: 146 | - geerlingguy.pip 147 | - geerlingguy.docker 148 | ``` 149 | 150 | ## Dependencies 151 | 152 | None. 153 | 154 | ## Example Playbook 155 | 156 | ```yaml 157 | - hosts: all 158 | roles: 159 | - geerlingguy.docker 160 | ``` 161 | 162 | ## License 163 | 164 | MIT / BSD 165 | 166 | ## Sponsors 167 | 168 | * [We Manage](https://we-manage.de): Helping start-ups and grown-ups scaling their infrastructure in a sustainable way. 169 | 170 | 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! 171 | 172 | ## Author Information 173 | 174 | This role was created in 2017 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). 175 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Edition can be one of: 'ce' (Community Edition) or 'ee' (Enterprise Edition). 3 | docker_edition: 'ce' 4 | docker_packages: 5 | - "docker-{{ docker_edition }}" 6 | - "docker-{{ docker_edition }}-cli" 7 | - "docker-{{ docker_edition }}-rootless-extras" 8 | - "containerd.io" 9 | - docker-buildx-plugin 10 | docker_packages_state: present 11 | docker_obsolete_packages: 12 | - docker 13 | - docker.io 14 | - docker-engine 15 | - docker-doc 16 | - docker-compose 17 | - docker-compose-v2 18 | - podman-docker 19 | - containerd 20 | - runc 21 | 22 | # Service options. 23 | docker_service_manage: true 24 | docker_service_state: started 25 | docker_service_enabled: true 26 | docker_restart_handler_state: restarted 27 | 28 | # Docker Compose Plugin options. 29 | docker_install_compose_plugin: true 30 | docker_compose_package: docker-compose-plugin 31 | docker_compose_package_state: present 32 | 33 | # Docker Compose options. 34 | docker_install_compose: false 35 | docker_compose_version: "v2.32.1" 36 | docker_compose_arch: "{{ ansible_architecture }}" 37 | docker_compose_url: "https://github.com/docker/compose/releases/download/{{ docker_compose_version }}/docker-compose-linux-{{ docker_compose_arch }}" 38 | docker_compose_path: /usr/local/bin/docker-compose 39 | 40 | # Enable repo setup 41 | docker_add_repo: true 42 | 43 | # Docker repo URL. 44 | docker_repo_url: https://download.docker.com/linux 45 | 46 | # Used only for Debian/Ubuntu/Pop!_OS/Linux Mint. Switch 'stable' to 'nightly' if needed. 47 | docker_apt_release_channel: stable 48 | # docker_apt_ansible_distribution is a workaround for Ubuntu variants which can't be identified as such by Ansible, 49 | # and is only necessary until Docker officially supports them. 50 | docker_apt_ansible_distribution: "{{ 'ubuntu' if ansible_distribution in ['Pop!_OS', 'Linux Mint'] else ansible_distribution }}" 51 | docker_apt_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'armhf' if ansible_architecture == 'armv7l' else 'amd64' }}" 52 | docker_apt_repository: "deb [arch={{ docker_apt_arch }} signed-by=/etc/apt/keyrings/docker.asc] {{ docker_repo_url }}/{{ docker_apt_ansible_distribution | lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" 53 | docker_apt_ignore_key_error: true 54 | docker_apt_gpg_key: "{{ docker_repo_url }}/{{ docker_apt_ansible_distribution | lower }}/gpg" 55 | docker_apt_gpg_key_checksum: "sha256:1500c1f56fa9e26b9b8f42452a553675796ade0807cdce11975eb98170b3a570" 56 | docker_apt_filename: "docker" 57 | 58 | # Used only for RedHat/CentOS/Fedora. 59 | docker_yum_repo_url: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora','centos') }}/docker-{{ docker_edition }}.repo" 60 | docker_yum_repo_enable_nightly: '0' 61 | docker_yum_repo_enable_test: '0' 62 | docker_yum_gpg_key: "{{ docker_repo_url }}/{{ (ansible_distribution == 'Fedora') | ternary('fedora', 'centos') }}/gpg" 63 | 64 | # A list of users who will be added to the docker group. 65 | docker_users: [] 66 | 67 | # Docker daemon options as a dict 68 | docker_daemon_options: {} 69 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart docker 3 | service: 4 | name: docker 5 | state: "{{ docker_restart_handler_state }}" 6 | ignore_errors: "{{ ansible_check_mode }}" 7 | when: docker_service_manage | bool 8 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: [] 3 | 4 | galaxy_info: 5 | role_name: docker 6 | author: geerlingguy 7 | description: Docker for Linux. 8 | company: "Midwestern Mac, LLC" 9 | license: "license (BSD, MIT)" 10 | min_ansible_version: 2.10 11 | platforms: 12 | - name: Fedora 13 | versions: 14 | - all 15 | - name: Debian 16 | versions: 17 | - buster 18 | - bullseye 19 | - bookworm 20 | - name: Ubuntu 21 | versions: 22 | - bionic 23 | - focal 24 | - jammy 25 | - noble 26 | - name: Alpine 27 | version: 28 | - all 29 | - name: ArchLinux 30 | versions: 31 | - all 32 | galaxy_tags: 33 | - web 34 | - system 35 | - containers 36 | - docker 37 | - orchestration 38 | - compose 39 | - server 40 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | # become: true 5 | 6 | pre_tasks: 7 | - name: Update apt cache. 8 | apt: update_cache=yes cache_valid_time=600 9 | when: ansible_os_family == 'Debian' 10 | 11 | - name: Wait for systemd to complete initialization. # noqa 303 12 | command: systemctl is-system-running 13 | register: systemctl_status 14 | until: > 15 | 'running' in systemctl_status.stdout or 16 | 'degraded' in systemctl_status.stdout 17 | retries: 30 18 | delay: 5 19 | when: ansible_service_mgr == 'systemd' 20 | changed_when: false 21 | failed_when: systemctl_status.rc > 1 22 | 23 | roles: 24 | - role: geerlingguy.docker 25 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | role_name_check: 1 3 | dependency: 4 | name: galaxy 5 | options: 6 | ignore-errors: true 7 | driver: 8 | name: docker 9 | platforms: 10 | - name: instance 11 | image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux9}-ansible:latest" 12 | command: ${MOLECULE_DOCKER_COMMAND:-""} 13 | volumes: 14 | - /sys/fs/cgroup:/sys/fs/cgroup:rw 15 | cgroupns_mode: host 16 | privileged: true 17 | pre_build_image: true 18 | provisioner: 19 | name: ansible 20 | playbooks: 21 | converge: ${MOLECULE_PLAYBOOK:-converge.yml} 22 | -------------------------------------------------------------------------------- /molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify Docker Role 3 | hosts: all 4 | tasks: 5 | - name: Verify Docker binary is available 6 | command: docker version 7 | register: docker_version_result 8 | changed_when: false 9 | failed_when: docker_version_result.rc != 0 10 | 11 | - name: Show Docker version details 12 | debug: 13 | msg: > 14 | Docker Version Output: 15 | {{ docker_version_result.stdout_lines | join('\n') }} 16 | 17 | - name: Verify Docker service is running 18 | command: systemctl is-active docker 19 | register: docker_service_status 20 | when: ansible_service_mgr == 'systemd' 21 | changed_when: false 22 | failed_when: docker_service_status.stdout.strip() != "active" 23 | 24 | - name: Display Docker service status 25 | debug: 26 | msg: "Docker service is {{ docker_service_status.stdout.strip() }}" 27 | when: ansible_service_mgr == 'systemd' 28 | 29 | - name: Pull the 'hello-world' image 30 | command: docker pull hello-world 31 | register: docker_pull_result 32 | changed_when: true 33 | failed_when: docker_pull_result.rc != 0 34 | 35 | - name: Show result of pulling the 'hello-world' image 36 | debug: 37 | msg: > 38 | Pulling 'hello-world' completed with output: 39 | {{ docker_pull_result.stdout_lines | join('\n') }} 40 | 41 | - name: Run a test container (hello-world) 42 | command: docker run --rm hello-world 43 | register: docker_run_result 44 | changed_when: true 45 | failed_when: docker_run_result.rc != 0 46 | 47 | - name: Display test container output 48 | debug: 49 | msg: > 50 | Running 'hello-world' container completed with output: 51 | {{ docker_run_result.stdout_lines | join('\n') }} 52 | -------------------------------------------------------------------------------- /tasks/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check current docker-compose version. 3 | command: "{{ docker_compose_path }} --version" 4 | register: docker_compose_vsn 5 | check_mode: false 6 | changed_when: false 7 | failed_when: false 8 | 9 | - set_fact: 10 | docker_compose_current_version: "{{ docker_compose_vsn.stdout | regex_search('(\\d+(\\.\\d+)+)') }}" 11 | when: > 12 | docker_compose_vsn.stdout is defined 13 | and (docker_compose_vsn.stdout | length > 0) 14 | 15 | - name: Delete existing docker-compose version if it's different. 16 | file: 17 | path: "{{ docker_compose_path }}" 18 | state: absent 19 | when: > 20 | docker_compose_current_version is defined 21 | and (docker_compose_version | regex_replace('v', '')) not in docker_compose_current_version 22 | 23 | - name: Install Docker Compose (if configured). 24 | get_url: 25 | url: "{{ docker_compose_url }}" 26 | dest: "{{ docker_compose_path }}" 27 | mode: 0755 28 | when: > 29 | (docker_compose_current_version is not defined) 30 | or (docker_compose_current_version | length == 0) 31 | or (docker_compose_current_version is version((docker_compose_version | regex_replace('v', '')), '<')) 32 | -------------------------------------------------------------------------------- /tasks/docker-users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure docker users are added to the docker group. 3 | user: 4 | name: "{{ item }}" 5 | groups: docker 6 | append: true 7 | with_items: "{{ docker_users }}" 8 | 9 | - name: Reset ssh connection to apply user changes. 10 | meta: reset_connection 11 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Load OS-specific vars. 3 | include_vars: "{{ lookup('first_found', params) }}" 4 | vars: 5 | params: 6 | files: 7 | - '{{ansible_distribution}}.yml' 8 | - '{{ansible_os_family}}.yml' 9 | - main.yml 10 | paths: 11 | - 'vars' 12 | 13 | - include_tasks: setup-RedHat.yml 14 | when: ansible_os_family == 'RedHat' 15 | 16 | - include_tasks: setup-Debian.yml 17 | when: ansible_os_family == 'Debian' 18 | 19 | - name: Install Docker packages. 20 | package: 21 | name: "{{ docker_packages }}" 22 | state: "{{ docker_packages_state }}" 23 | notify: restart docker 24 | ignore_errors: "{{ ansible_check_mode }}" 25 | when: "ansible_version.full is version_compare('2.12', '<') or ansible_os_family not in ['RedHat', 'Debian']" 26 | 27 | - name: Install Docker packages (with downgrade option). 28 | package: 29 | name: "{{ docker_packages }}" 30 | state: "{{ docker_packages_state }}" 31 | allow_downgrade: true 32 | notify: restart docker 33 | ignore_errors: "{{ ansible_check_mode }}" 34 | when: "ansible_version.full is version_compare('2.12', '>=') and ansible_os_family in ['RedHat', 'Debian']" 35 | 36 | - name: Install docker-compose plugin. 37 | package: 38 | name: "{{ docker_compose_package }}" 39 | state: "{{ docker_compose_package_state }}" 40 | notify: restart docker 41 | ignore_errors: "{{ ansible_check_mode }}" 42 | when: "docker_install_compose_plugin | bool == true and (ansible_version.full is version_compare('2.12', '<') or ansible_os_family not in ['RedHat', 'Debian'])" 43 | 44 | - name: Install docker-compose-plugin (with downgrade option). 45 | package: 46 | name: "{{ docker_compose_package }}" 47 | state: "{{ docker_compose_package_state }}" 48 | allow_downgrade: true 49 | notify: restart docker 50 | ignore_errors: "{{ ansible_check_mode }}" 51 | when: "docker_install_compose_plugin | bool == true and ansible_version.full is version_compare('2.12', '>=') and ansible_os_family in ['RedHat', 'Debian']" 52 | 53 | - name: Ensure /etc/docker/ directory exists. 54 | file: 55 | path: /etc/docker 56 | state: directory 57 | mode: 0755 58 | when: docker_daemon_options.keys() | length > 0 59 | 60 | - name: Configure Docker daemon options. 61 | copy: 62 | content: "{{ docker_daemon_options | to_nice_json }}" 63 | dest: /etc/docker/daemon.json 64 | mode: 0644 65 | when: docker_daemon_options.keys() | length > 0 66 | notify: restart docker 67 | 68 | - name: Ensure Docker is started and enabled at boot. 69 | service: 70 | name: docker 71 | state: "{{ docker_service_state }}" 72 | enabled: "{{ docker_service_enabled }}" 73 | ignore_errors: "{{ ansible_check_mode }}" 74 | when: docker_service_manage | bool 75 | 76 | - name: Ensure handlers are notified now to avoid firewall conflicts. 77 | meta: flush_handlers 78 | 79 | - include_tasks: docker-compose.yml 80 | when: docker_install_compose | bool 81 | 82 | - name: Get docker group info using getent. 83 | getent: 84 | database: group 85 | key: docker 86 | split: ':' 87 | when: docker_users | length > 0 88 | 89 | - name: Check if there are any users to add to the docker group. 90 | set_fact: 91 | at_least_one_user_to_modify: true 92 | when: 93 | - docker_users | length > 0 94 | - item not in ansible_facts.getent_group["docker"][2] 95 | with_items: "{{ docker_users }}" 96 | 97 | - include_tasks: docker-users.yml 98 | when: at_least_one_user_to_modify is defined 99 | -------------------------------------------------------------------------------- /tasks/setup-Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apt key is not present in trusted.gpg.d 3 | ansible.builtin.file: 4 | path: /etc/apt/trusted.gpg.d/docker.asc 5 | state: absent 6 | 7 | - name: Ensure old apt source list is not present in /etc/apt/sources.list.d 8 | ansible.builtin.file: 9 | path: "/etc/apt/sources.list.d/download_docker_com_linux_{{ docker_apt_ansible_distribution | lower }}.list" 10 | state: absent 11 | 12 | - name: Ensure the repo referencing the previous trusted.gpg.d key is not present 13 | apt_repository: 14 | repo: "deb [arch={{ docker_apt_arch }} signed-by=/etc/apt/trusted.gpg.d/docker.asc] {{ docker_repo_url }}/{{ docker_apt_ansible_distribution | lower }} {{ ansible_distribution_release }} {{ docker_apt_release_channel }}" 15 | state: absent 16 | filename: "{{ docker_apt_filename }}" 17 | update_cache: true 18 | when: docker_add_repo | bool 19 | 20 | - # See https://docs.docker.com/engine/install/debian/#uninstall-old-versions 21 | name: Ensure old versions of Docker are not installed. 22 | package: 23 | name: "{{ docker_obsolete_packages }}" 24 | state: absent 25 | 26 | - name: Ensure dependencies are installed. 27 | apt: 28 | name: 29 | - apt-transport-https 30 | - ca-certificates 31 | state: present 32 | when: docker_add_repo | bool 33 | 34 | - name: Ensure directory exists for /etc/apt/keyrings 35 | file: 36 | path: /etc/apt/keyrings 37 | state: directory 38 | mode: "0755" 39 | 40 | - name: Add Docker apt key. 41 | ansible.builtin.get_url: 42 | url: "{{ docker_apt_gpg_key }}" 43 | dest: /etc/apt/keyrings/docker.asc 44 | mode: "0644" 45 | force: false 46 | checksum: "{{ docker_apt_gpg_key_checksum | default(omit) }}" 47 | register: add_repository_key 48 | ignore_errors: "{{ docker_apt_ignore_key_error }}" 49 | when: docker_add_repo | bool 50 | 51 | - name: Ensure curl is present (on older systems without SNI). 52 | package: name=curl state=present 53 | when: add_repository_key is failed and docker_add_repo | bool 54 | 55 | - name: Add Docker apt key (alternative for older systems without SNI). 56 | shell: > 57 | curl -sSL {{ docker_apt_gpg_key }} | apt-key add - 58 | when: add_repository_key is failed and docker_add_repo | bool 59 | 60 | - name: Add Docker repository. 61 | apt_repository: 62 | repo: "{{ docker_apt_repository }}" 63 | state: present 64 | filename: "{{ docker_apt_filename }}" 65 | update_cache: true 66 | when: docker_add_repo | bool 67 | -------------------------------------------------------------------------------- /tasks/setup-RedHat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure old versions of Docker are not installed. 3 | package: 4 | name: "{{ docker_obsolete_packages }}" 5 | state: absent 6 | 7 | - name: Add Docker GPG key. 8 | rpm_key: 9 | key: "{{ docker_yum_gpg_key }}" 10 | state: present 11 | when: docker_add_repo | bool 12 | 13 | - name: Add Docker repository. 14 | get_url: 15 | url: "{{ docker_yum_repo_url }}" 16 | dest: '/etc/yum.repos.d/docker-{{ docker_edition }}.repo' 17 | owner: root 18 | group: root 19 | mode: 0644 20 | when: docker_add_repo | bool 21 | 22 | - name: Configure Docker Nightly repo. 23 | ini_file: 24 | dest: '/etc/yum.repos.d/docker-{{ docker_edition }}.repo' 25 | section: 'docker-{{ docker_edition }}-nightly' 26 | option: enabled 27 | value: '{{ docker_yum_repo_enable_nightly }}' 28 | mode: 0644 29 | no_extra_spaces: true 30 | when: docker_add_repo | bool 31 | 32 | - name: Configure Docker Test repo. 33 | ini_file: 34 | dest: '/etc/yum.repos.d/docker-{{ docker_edition }}.repo' 35 | section: 'docker-{{ docker_edition }}-test' 36 | option: enabled 37 | value: '{{ docker_yum_repo_enable_test }}' 38 | mode: 0644 39 | no_extra_spaces: true 40 | when: docker_add_repo | bool 41 | 42 | - name: Configure containerd on RHEL 8. 43 | block: 44 | - name: Ensure runc is not installed. 45 | package: 46 | name: runc 47 | state: absent 48 | 49 | - name: Ensure container-selinux is installed. 50 | package: 51 | name: container-selinux 52 | state: present 53 | 54 | - name: Ensure containerd.io is installed. 55 | package: 56 | name: containerd.io 57 | state: present 58 | when: ansible_distribution_major_version | int == 8 59 | -------------------------------------------------------------------------------- /vars/Alpine.yml: -------------------------------------------------------------------------------- 1 | --- 2 | docker_packages: "docker" 3 | docker_compose_package: docker-cli-compose 4 | -------------------------------------------------------------------------------- /vars/Archlinux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | docker_packages: "docker" 3 | docker_compose_package: docker-compose 4 | -------------------------------------------------------------------------------- /vars/Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Used only for Debian/Ubuntu (Debian OS-Family) 3 | # https://docs.docker.com/engine/install/debian/#uninstall-old-versions 4 | 5 | docker_obsolete_packages: 6 | - docker 7 | - docker.io 8 | - docker-engine 9 | - docker-doc 10 | - docker-compose 11 | - docker-compose-v2 12 | - podman-docker 13 | - containerd 14 | - runc 15 | -------------------------------------------------------------------------------- /vars/RedHat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Used only for Fedora/Rocky (RedHat OS-Family) 3 | # https://docs.docker.com/engine/install/fedora/#uninstall-old-versions 4 | # https://docs.docker.com/engine/install/centos/#uninstall-old-versions 5 | 6 | docker_obsolete_packages: 7 | - docker 8 | - docker-client 9 | - docker-client-latest 10 | - docker-common 11 | - docker-latest 12 | - docker-latest-logrotate 13 | - docker-logrotate 14 | - docker-engine 15 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Empty file 3 | --------------------------------------------------------------------------------