skip to Main Content

I configured nginx on diffrent docker using ansible. Now I want to change different index.html using Jinja2.

I configured nginx using localhost. But now how can I use template Jinja2 and transfer it on container using ansible.

---
- hosts: localhost
  vars:
    server_name: "server"
  connection: local
  become: yes
  tasks:
  - package:
      name: docker
      state: present
  - service:
      name: docker
      state: restarted
  - command: docker run -it --name ngixserver21 -d -p 8090:80 nginx

#how I can transfer html_template.j2 on container - ngixserver21

  - name: Run a simple command (command)
    community.docker.docker_container_exec:
        container: ngixserver21
    template:
          src: "html_template.j2"
          desc: "/usr/share/nginx/html/index.html"
          notify: Restart Nginx

2

Answers


  1. I actually support what’s been said in the comments. It’s a little bit of anti-pattern.

    I used something like this in the past. I’m sure you get the gist.

      - name: Run a simple command (command)
        community.docker.docker_container_exec:
            container: ngixserver21
            argv:
                 - /bin/bash
                 - "-c"
                 - "echo {{ lookup('template', 'index.j2') | b64encode }} | base64 -d > index.html"
            chdir: "/usr/share/nginx/html"
    
        
    

    This assumes of course that you have bash(sh should work too) and base64. If your template does not have single quotes, you may not need base64.

    Login or Signup to reply.
  2. Important preliminary note: I urge you to read the comments from DavidMaze and β.εηοιτ.βε above regarding good practice to understand why you don’t want to go through ansible in your specific case and you should not modify a running container.

    Meanwhile, since there are other use cases (like testing ansible roles inside a docker container), I’ll still answer the overall question hopping that all the above warnings were enough for you to use that information very wisely.

    To start with, if you want to deploy and run your image with ansible, it should be done using the relevant docker_container module rather than calling shell.

    Once this is done, ansible has a docker connection plugin that will let you interact with containers on your host 1. The idea is to have an entry in your inventory for the relevant container using the correctly configured connection. You can then use a normal play host loop with usual ansible tasks to reach your remote target container 2.

    In my example below, I deploy an image and add it to the in-memory inventory in the same playbook using the add_host module. Those two actions can be done totally independently and there are several options to add your containers to an inventory among which the docker_containers dynamic inventory plugin.

    I used the following test.j2 template for this test

    Dummy template
    Node name: {{ ansible_nodename }}
    Environment:
    {{ ansible_env | to_nice_yaml }}
    

    This the demo playbook.yml:

    ---
    - name: spin-up container and add to inventory
      hosts: localhost
      gather_facts: false
    
      vars:
        container_name: my_test_container
    
      tasks:
        - name: Deploy a dummy container
          docker_container:
            name: "{{ container_name }}"
            image: python:latest
            command: tail -f /dev/null
            state: started
    
        - name: store container name as a fact on localhost for later use in last play
          set_fact:
            container_name: "{{ container_name }}"
    
        - name: Add the created container to inventory
          add_host:
            name: "{{ container_name }}"
            groups:
              - docker_test
            ansible_connection: docker
    
    - name: do some stuff on container
      hosts: docker_test
    
      tasks:
        - name: show a gathered info from the container
          debug:
            var: ansible_os_family
    
        - name: test our template is deployable
          template:
            src: test.j2
            dest: /test.txt
    
        - name: get result back to check
          slurp:
            path: /test.txt
          register: deploy_template
    
        - name: show result
          debug:
            msg: "{{ (deploy_template.content | b64decode).split('n') }}"
    
        # Put here anything else that should target your container(s)
    
    - name: do some cleanup
      hosts: localhost
      gather_facts: false
    
      tasks:
        - name: destroy test container
          docker_container:
            name: "{{ container_name }}"
            state: absent
    

    Which gives:

    $ ansible-playbook playbook.yml 
    
    PLAY [spin-up container and add to inventory] *******************************
    
    TASK [Deploy a dummy container] *********************************************
    changed: [localhost]
    
    TASK [store container name as a fact on localhost for later use in last play] *
    ok: [localhost]
    
    TASK [Add the created container to inventory] *******************************
    changed: [localhost]
    
    PLAY [do some stuff on container] *******************************************
    
    TASK [Gathering Facts] ******************************************************
    ok: [my_test_container]
    
    TASK [show a gathered info from the container] ******************************
    ok: [my_test_container] => {
        "ansible_os_family": "Debian"
    }
    
    TASK [test our template is deployable] **************************************
    changed: [my_test_container]
    
    TASK [get result back to check] *********************************************
    ok: [my_test_container]
    
    TASK [show result] **********************************************************
    ok: [my_test_container] => {
        "msg": [
            "Dummy template",
            "Node name: 1608185a4e43",
            "Environment:",
            "GPG_KEY: A035C8C19219BA821ECEA86B64E628F8D684696D",
            "HOME: /root",
            "HOSTNAME: 1608185a4e43",
            "LANG: C.UTF-8",
            "PATH: /usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "PWD: /",
            "PYTHON_GET_PIP_SHA256: c518250e91a70d7b20cceb15272209a4ded2a0c263ae5776f129e0d9b5674309",
            "PYTHON_GET_PIP_URL: https://github.com/pypa/get-pip/raw/3cb8888cc2869620f57d5d2da64da38f516078c7/public/get-pip.py",
            "PYTHON_PIP_VERSION: 21.2.4",
            "PYTHON_SETUPTOOLS_VERSION: 57.5.0",
            "PYTHON_VERSION: 3.10.2",
            ""
        ]
    }
    
    PLAY [do some cleanup] ******************************************************
    
    TASK [destroy test container] ***********************************************
    changed: [localhost]
    
    PLAY RECAP ******************************************************************
    localhost:         ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    my_test_container: ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
    

    1 docker plugin uses the docker cli to run commands. If you prefer to use the api directly, you can do the same thing with the docker-api plugin

    2 Note that your target container will need to satisfy to ansible managed nodes requirements and have python installed


    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search