Ansible中community.docker连接插件报docker command not found问题排查
在Ansible Playbook中将任务委托至远程Docker主机时,community.docker集合下的docker_image、docker_container等模块能正常执行拉取、安装镜像等操作,但使用同属该集合的docker连接插件(设置ansible_connection: docker)时,出现如下报错:
fatal: [localhost -> instance-139.xxx.xxx.xxx]: FAILED! => { "msg": "docker command not found in PATH" }
此前同类问题多涉及用户权限,但本次操作使用root用户,权限无异常,需排查为何仅连接插件出现该报错。
Playbook代码(截断版):
- name: Create an API instance hosts: localhost gather_facts: no collections: - linode.cloud - community.docker tasks: - block: - name: Linode IPS debug: msg: "{{ linode_ips }}" - name: Update apt and install dependencies apt: update_cache: yes name: "{{ item }}" force_apt_get: yes state: present loop: - apt-transport-https - ca-certificates - curl - gzip - software-properties-common - name: Add Docker GPG key apt_key: url: https://download.docker.com/linux/ubuntu/gpg state: present - name: Add Docker repository apt_repository: repo: deb https://download.docker.com/linux/ubuntu focal stable state: present - name: Install Docker apt: name: docker-ce state: present force_apt_get: yes update_cache: yes - name: Start and enable Docker systemd: name: docker state: started enabled: yes - debug: msg: "Registry: docker.registry.aksantinet.com/{{ host_group }}" - name: Pull the image from the registry community.docker.docker_image: name: "docker.registry.aksantinet.com/{{ host_group }}" tag: latest source: pull - name: Run Docker container community.docker.docker_container: name: "{{ container_name }}" image: "docker.registry.aksantinet.com/{{ host_group }}" network_mode: host state: started capabilities: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun privileged: yes become: yes - name: Copy LetsEncrypt from ansible to Docker become: yes block: - lineinfile: path: "test" line: "example" create: yes state: present - ansible.builtin.copy: src: /etc/letsencrypt/ dest: /etc/letsencrypt/ - shell: nginx vars: ansible_docker_host: "{{ container_name }}" ansible_connection: docker - name: Instance added debug: msg: "Addded instance at {{ linode_ip }}" delegate_to: "instance-{{ linode_ip }}"
排查与解决方法
核心原因
community.docker的模块(如docker_image)是通过Docker API与远程Docker daemon交互的,不需要在控制节点(localhost)上安装Docker CLI;而docker连接插件是在控制节点上执行docker exec命令来进入容器的,所以要求控制节点的PATH中必须存在docker命令。
你的场景中,所有Docker相关模块都委托到了远程主机执行,控制节点本身没有安装Docker CLI,因此触发了"docker command not found"报错。
解决步骤
方案1:在控制节点安装Docker CLI
在运行Playbook的localhost上安装Docker CLI,确保docker命令能被找到:
# 以Ubuntu为例 apt-get update && apt-get install -y docker-ce-cli
安装完成后,执行docker --version验证命令可用。
方案2:修正连接插件的变量配置
当前ansible_docker_host配置为容器名称是错误的,需要指向远程Docker daemon的地址:
vars: ansible_connection: docker ansible_docker_host: "tcp://{{ linode_ip }}:2375" # 需确保远程Docker daemon开启TCP端口 ansible_docker_extra_args: "--tls" # 生产环境建议启用TLS认证,需添加此参数
同时,远程Docker daemon默认只监听Unix socket,需要修改/etc/docker/daemon.json开启TCP监听,然后重启Docker服务:
{ "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"] }
方案3:改用容器专用模块替代连接插件
如果不想在控制节点安装Docker CLI,可以使用community.docker集合内的容器操作模块,避免使用docker连接插件:
- 执行容器内命令用
docker_container_exec:
- name: Execute nginx command inside container community.docker.docker_container_exec: container: "{{ container_name }}" command: nginx delegate_to: "instance-{{ linode_ip }}"
- 复制文件到容器用
docker_container_copy_into:
- name: Copy LetsEncrypt files into container community.docker.docker_container_copy_into: container: "{{ container_name }}" src: /etc/letsencrypt/ dest: /etc/letsencrypt/ delegate_to: "instance-{{ linode_ip }}"
内容的提问来源于stack exchange,提问作者Rad

