From 456c27d12bdd3bea74074b2e0151f984ac72b546 Mon Sep 17 00:00:00 2001 From: sjat Date: Sun, 14 Jun 2026 17:28:51 +0200 Subject: [PATCH] feat(docker_host): install Docker engine + compose plugin Implements the docker_host role tasks: prerequisites, /etc/apt/keyrings directory (ordered before the GPG key write), Docker APT key + repo, and docker-ce/cli/containerd.io/compose-plugin install. Daemon hardening and nftables.d integration remain deferred to Phase 2 (cluster + base firewall). Updates defaults, README, and molecule verify to assert docker --version. Co-Authored-By: Claude Opus 4.8 (1M context) --- roles/docker_host/README.md | 40 +++++++++------ roles/docker_host/defaults/main.yml | 7 +++ roles/docker_host/molecule/default/verify.yml | 14 ++++-- roles/docker_host/tasks/main.yml | 50 ++++++++++++++----- 4 files changed, 80 insertions(+), 31 deletions(-) diff --git a/roles/docker_host/README.md b/roles/docker_host/README.md index 1c490ad..061ce30 100644 --- a/roles/docker_host/README.md +++ b/roles/docker_host/README.md @@ -1,25 +1,25 @@ # docker_host -Docker engine + Compose runtime applied to every host in the `docker_hosts` group. -Provides the container platform that the per-service roles (one service = one role, -ADR-004) deploy their Compose stacks onto. +Installs the Docker CE engine and the Compose plugin on every host in the +`docker_hosts` group. Provides the container runtime that per-service roles +(one service = one role, ADR-004) deploy their Compose stacks onto. -> **Status: scaffolded, not yet implemented.** This role has no tasks yet — applying it -> is a no-op. It is wired into `playbooks/site.yml` so the full standard state is -> expressed end-to-end, and so `make lint` covers it. See `STATUS.md`. +## Scope -## Planned scope +This role covers the **engine install only**. The following are deferred to Phase 2 +(when the Proxmox cluster and `base` host firewall exist): -- Install Docker engine + the Compose plugin, version-pinned (ADR-011). -- Daemon hardening: `iptables: false` (the host `base` firewall owns nftables, ADR-020), - log driver, `live-restore`, user-namespace remapping where practical (ADR-002). -- Render container forward/NAT rules into `/etc/nftables.d/*.nft` — the include hook the - `base` role's ruleset exposes (see `roles/base/README.md`). -- Provide the runtime the service roles deploy their Compose files onto. +- Daemon hardening (`iptables: false`, log driver, `live-restore`, userns remapping). +- Rendering container forward/NAT rules into `/etc/nftables.d/*.nft` (the `base` role + hook for container firewall integration, ADR-020). ## Variables -None yet. Placeholders will use the `docker_host__*` namespace (CLAUDE.md convention). +| Variable | Default | Description | +|---|---|---| +| `docker_host__packages` | `[docker-ce, docker-ce-cli, containerd.io, docker-compose-plugin]` | APT packages installed from the Docker CE repository | + +All variables use the `docker_host__` double-underscore namespace (CLAUDE.md convention). ## Example @@ -31,4 +31,14 @@ None yet. Placeholders will use the `docker_host__*` namespace (CLAUDE.md conven tags: [docker_host] ``` -See ADR-004 (`docs/decisions/004-docker-model.md`) for the Docker & Compose model. +## Tags + +All tasks carry the `packages` concern tag (APT package install, ADR-019). + +## Related + +- ADR-004 (`docs/decisions/004-docker-model.md`) — Docker & Compose model. +- ADR-020 (`docs/decisions/020-firewall.md`) — daemon hardening + `nftables.d` + integration (deferred to Phase 2). +- ADR-011 (`docs/decisions/011-update-management.md`) — version pinning policy + (future: pin Docker CE version explicitly). diff --git a/roles/docker_host/defaults/main.yml b/roles/docker_host/defaults/main.yml index ed97d53..0e22ea5 100644 --- a/roles/docker_host/defaults/main.yml +++ b/roles/docker_host/defaults/main.yml @@ -1 +1,8 @@ --- +# Docker engine install (ADR-004). Cluster-specific daemon hardening + nftables.d +# integration are deferred to when the cluster + host firewall exist. +docker_host__packages: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-compose-plugin diff --git a/roles/docker_host/molecule/default/verify.yml b/roles/docker_host/molecule/default/verify.yml index c87d14e..dd30601 100644 --- a/roles/docker_host/molecule/default/verify.yml +++ b/roles/docker_host/molecule/default/verify.yml @@ -4,8 +4,14 @@ gather_facts: true tasks: - - name: Add verification tasks here - ansible.builtin.assert: - that: true - msg: "Replace this with real assertions" + - name: Verify docker binary is present + ansible.builtin.command: docker --version + register: docker_version_output + changed_when: false + tags: [verify] + + - name: Assert docker --version succeeded + ansible.builtin.assert: + that: docker_version_output.rc == 0 + msg: "docker --version failed — Docker was not installed correctly" tags: [verify] diff --git a/roles/docker_host/tasks/main.yml b/roles/docker_host/tasks/main.yml index e5bd2f7..44f04f5 100644 --- a/roles/docker_host/tasks/main.yml +++ b/roles/docker_host/tasks/main.yml @@ -1,13 +1,39 @@ --- -# docker_host — Docker engine + Compose runtime for hosts in the docker_hosts group. -# -# SCAFFOLDED, NOT YET IMPLEMENTED. This role is referenced by playbooks/site.yml so the -# full standard state is expressed end-to-end, but it has no tasks yet — applying it is a -# no-op. See STATUS.md ("Scaffolded but empty") and ADR-004 (Docker & Compose model). -# -# Planned scope (ADR-002/004/020): -# - install Docker engine + compose plugin (version-pinned, per ADR-011) -# - daemon hardening: iptables:false (host nftables owns the firewall, ADR-020), -# log-driver, live-restore, userns where practical -# - render container forward/NAT rules into /etc/nftables.d/*.nft (the base-role hook) -# - deploy per-service Compose stacks from the service roles (one service = one role) +- name: Install prerequisites + ansible.builtin.apt: + name: [ca-certificates, curl, gnupg] + state: present + update_cache: true + tags: [packages] + +- name: Ensure /etc/apt/keyrings exists + ansible.builtin.file: + path: /etc/apt/keyrings + state: directory + mode: "0755" + tags: [packages] + +- name: Add Docker's APT GPG key + ansible.builtin.get_url: + url: https://download.docker.com/linux/debian/gpg + dest: /etc/apt/keyrings/docker.asc + mode: "0644" + tags: [packages] + +- name: Add the Docker APT repository + ansible.builtin.apt_repository: + repo: >- + deb [arch={{ 'amd64' if ansible_architecture == 'x86_64' else ansible_architecture }} + signed-by=/etc/apt/keyrings/docker.asc] + https://download.docker.com/linux/debian + {{ ansible_distribution_release }} stable + filename: docker + state: present + tags: [packages] + +- name: Install Docker engine + compose plugin + ansible.builtin.apt: + name: "{{ docker_host__packages }}" + state: present + update_cache: true + tags: [packages]