Pri používaní Ansible, keď je vzdialený stroj na Arch, existuje niekoľko nástrah, ktoré stojí za to poznať. Viem, zvláštna kombinácia. Čoraz viac to vyzerá, že prakticky nikto nepoužíva Arch remote s Ansible. Ale mne sa to páči, takže naučiť sa (a zdokumentovať) jednu či dve veci po ceste nemusí byť na škodu. Tiež poznamenajte, že tento príspevok je celkom špecifický pre nástroj docker-compose, takže ak ho nepoužívate, zvyšok môžete pokojne preskočiť.

Začíname #

Najprv nainštalujte rootless Docker na stroji. Dá sa to urobiť aj cez Ansible, ale to je mimo rozsahu tohto článku. Ak by ste s tým potrebovali pomoc, napíšte mi (e-mail nájdete niekde na blogu). Podelím sa s mojím riešením, alebo snáď dovtedy vyjde celý príspevok o tom. Zatiaľ môžete získať inšpiráciu v mojom predchádzajúcom článku.

Ďalej budeme potrebovať dve Ansible kolekcie. Prvá je pre pacman kolekciu, odkazovanú ako community.general.pacman:

ansible-galaxy collection install community.general

Druhá je pre docker-compose kolekciu, odkazovanú ako community.docker.docker_compose:

ansible-galaxy collection install community.docker

To by malo byť všetko. Teraz sa pustime do práce.

Inštalácia docker-compose na vzdialenom stroji #

Zvážte najintuitívnejší prístup — nainštalovať docker-compose a vyskúšať službu, ako dve Ansible úlohy, za predpokladu, že súbor path/to/compose/project/docker-compose.yml existuje:

tasks:
  - name: Intall docker-compose
    become: yes
    community.general.pacman:
      state: present
      name:
        - docker-compose

  - name: Create and start the service
    community.docker.docker_compose:
      project_src: path/to/compose/project

Pri spustení ako playbook zlyhá:

TASK [Create and start the service] *********************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'docker'
fatal: [X.X.X.X]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker above 5.0.0 (Python >= 3.6) or docker before 5.0.0 (Python 2.7) or docker-py (Python 2.6)) on vmi732184.contaboserver.net's Python /usr/bin/python3. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` (Python >= 3.6) or `pip install docker==4.4.4` (Python 2.7) or `pip install docker-py` (Python 2.6). The error was: No module named 'docker'"}

Jasné. Kolekcia požaduje prítomnosť PyPi balíka docker, alebo aspoň docker-py pre staršie verzie Pythonu ako 2.6.

python-docker cez pacman #

Preferovaný spôsob inštalácie python balíkov na Arch je uprednostniť pacman pred pip, keď je to možné. Našťastie, python-docker je dostupný v community repozitári. Žiadny problém. Pridajme ho do playbooku a spustime znova:

tasks:
  - name: Intall docker-compose
    become: yes
    community.general.pacman:
      state: present
      name:
        - docker-compose
        - python-docker

  - name: Create and start the service
    community.docker.docker_compose:
      project_src: path/to/compose/project

Zlyhá opäť, s niečím v zmysle:

"msg": "Unable to load docker-compose. Try `pip install docker-compose`. Error: Traceback (most recent call last):\n  File \"/tmp/ansible_community.docker.docker_compose_payload_0elyc4fq/ansible_community.docker.docker_compose_payload.zip/ansible_collections/community/docker/plugins/modules/docker_compose.py\", line 497, in <module>\nModuleNotFoundError: No module named 'compose'\n"

Teraz, žiadny balík v oficiálnych repozitároch neobsahuje slová python a compose. Podľa odporúčaní vyššie, nič relevantné nenájdeme ani v AUR.

docker-compose cez pip #

Poznamenajte, že Python balík docker-compose ťahá balík docker ako závislosť. Takže je bezpečné ho už neuvádzať cez pacman v playbookoch. Keďže v repozitároch nie je žiadny compose balík, je čas siahnuť po pip:

tasks:
  - name: Intall docker-compose
    become: yes
    community.general.pacman:
      state: present
      name:
        - docker-compose
        - python-pip

  - name: Install pip docker-compose
    ansible.builtin.pip:
      name: docker-compose

  - name: Create and start the service
    community.docker.docker_compose:
      project_src: path/to/compose/project

Python časť sa teraz vyrieši. Môžeme nezávisle potvrdiť, že balík docker na PyPi je závislosťou balíka docker-compose na PyPi:

pip show docker-compose | grep Requires | cut -d' ' -f2- | tr , '\n'

Výsledok s verziou 1.29.2:

docker
dockerpty
texttable
jsonschema
websocket-client
python-dotenv
requests
docopt
PyYAML

Vyššie uvedený playbook však zlyhá naposledy a bolo pre mňa trochu ťažké identifikovať problém. Problém je teraz Docker. Skrátená chybová správa:

fatal: [X.X.X.X]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            ...
            "dependencies": true,
            "docker_host": "unix://var/run/docker.sock",
            "env_file": null,
            ...
        }
    },
    "msg": "Error connecting: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))"
}

Skutočná chyba je trochu dlhšia, ale obsahuje väčšinou traceback. Problém je s atribútom docker_host. Pri rootless Docker je skutočný socket umiestnený v user space, napríklad na unix:///run/user/1000/docker.sock, špecifikovaný buď parametrom CLI alebo premennou prostredia DOCKER_HOST, viac v dokumentácii.

Záver #

Väčšina návodov odporúča exportovať premennú niekde do .profile, .bashrc alebo .zshrc takto:

export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

Keďže však Ansible otvára neinteraktívny shell, táto premenná v takej podobe nebude dostupná. Musíme ju zostrojiť manuálne a dúfať, že ju nikto nezmenil:

tasks:
  - name: Intall docker-compose
    become: yes
    community.general.pacman:
      state: present
      name:
        - docker-compose
        - python-pip

  - name: Install pip docker-compose
    ansible.builtin.pip:
      name: docker-compose

  - name: Create and start the service
    community.docker.docker_compose:
      docker_host: "unix://{{ ansible_env.XDG_RUNTIME_DIR }}/docker.sock"
      project_src: path/to/compose/project

Poznámka: aby bolo ansible_env dostupné, možnosť gather_facts musí byť ponechaná zapnutá. Zmienka v dokumentácii. Príjemnú prácu!