├── .dockerignore ├── Dockerfile ├── README.md └── test ├── docker-compose.yml ├── inventory ├── playbook.yml └── remote.yml /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | README.md 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gliderlabs/alpine:3.4 2 | ARG VERSION=2.7.2 3 | 4 | RUN \ 5 | apk-install \ 6 | curl \ 7 | openssh-client \ 8 | python \ 9 | py-boto \ 10 | py-dateutil \ 11 | py-httplib2 \ 12 | py-jinja2 \ 13 | py-paramiko \ 14 | py-pip \ 15 | py-setuptools \ 16 | py-yaml \ 17 | tar && \ 18 | pip install --upgrade pip python-keyczar && \ 19 | rm -rf /var/cache/apk/* 20 | 21 | RUN mkdir /etc/ansible/ /ansible 22 | RUN echo "[local]" >> /etc/ansible/hosts && \ 23 | echo "localhost" >> /etc/ansible/hosts 24 | 25 | RUN \ 26 | curl -fsSL https://releases.ansible.com/ansible/ansible-${VERSION}.tar.gz -o ansible.tar.gz && \ 27 | tar -xzf ansible.tar.gz -C ansible --strip-components 1 && \ 28 | rm -fr ansible.tar.gz /ansible/docs /ansible/examples /ansible/packaging 29 | 30 | RUN mkdir -p /ansible/playbooks 31 | WORKDIR /ansible/playbooks 32 | 33 | ENV ANSIBLE_GATHERING smart 34 | ENV ANSIBLE_HOST_KEY_CHECKING false 35 | ENV ANSIBLE_RETRY_FILES_ENABLED false 36 | ENV ANSIBLE_ROLES_PATH /ansible/playbooks/roles 37 | ENV ANSIBLE_SSH_PIPELINING True 38 | ENV PATH /ansible/bin:$PATH 39 | ENV PYTHONPATH /ansible/lib 40 | 41 | ENTRYPOINT ["ansible-playbook"] 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Playbook Docker Image 2 | 3 | Executes ansible-playbook command against an externally mounted set of Ansible playbooks 4 | 5 | ``` 6 | docker run --rm -it -v PATH_TO_LOCAL_PLAYBOOKS_DIR:/ansible/playbooks philm/ansible_playbook PLAYBOOK_FILE 7 | ``` 8 | 9 | For example, assuming your project's structure follows [best practices](http://docs.ansible.com/ansible/playbooks_best_practices.html#directory-layout), the command to run ansible-playbook from the top-level directory would look like: 10 | 11 | ``` 12 | docker run --rm -it -v $(pwd):/ansible/playbooks philm/ansible_playbook site.yml 13 | ``` 14 | 15 | Ansible playbook variables can simply be added after the playbook name. 16 | 17 | ## SSH Keys 18 | 19 | If Ansible is interacting with external machines, you'll need to mount an SSH key pair for the duration of the play: 20 | 21 | ``` 22 | docker run --rm -it \ 23 | -v ~/.ssh/id_rsa:/root/.ssh/id_rsa \ 24 | -v ~/.ssh/id_rsa.pub:/root/.ssh/id_rsa.pub \ 25 | -v $(pwd):/ansible/playbooks \ 26 | philm/ansible_playbook site.yml 27 | ``` 28 | 29 | ## Ansible Vault 30 | 31 | If you've encrypted any data using [Ansible Vault](http://docs.ansible.com/ansible/playbooks_vault.html), you can decrypt during a play by either passing **--ask-vault-pass** after the playbook name, or pointing to a password file. For the latter, you can mount an external file: 32 | 33 | ``` 34 | docker run --rm -it -v $(pwd):/ansible/playbooks \ 35 | -v ~/.vault_pass.txt:/root/.vault_pass.txt \ 36 | philm/ansible_playbook site.yml --vault-password-file /root/.vault_pass.txt 37 | ``` 38 | 39 | Note: the Ansible Vault executable is embedded in this image. To use it, specify a different entrypoint: 40 | 41 | ``` 42 | docker run --rm -it -v $(pwd):/ansible/playbooks --entrypoint ansible-vault philm/ansible_playbook encrypt FILENAME 43 | ``` 44 | 45 | ## Testing Playbooks - Ansible Target Container 46 | 47 | The [Ansible Target Docker image](https://github.com/philm/ansible_target) is an SSH container optimized for testing Ansible playbooks. 48 | 49 | First, define your inventory file. 50 | 51 | ``` 52 | [test] 53 | ansible_target 54 | ``` 55 | 56 | Be sure your testing playbooks include the correct host and remote user: 57 | 58 | ``` 59 | - hosts: test 60 | remote_user: ubuntu 61 | 62 | tasks: 63 | ... tasks go here ... 64 | ``` 65 | 66 | When testing the playbook, you'll need to link the two containers: 67 | 68 | ``` 69 | docker run --rm -it \ 70 | --link ansible_target \ 71 | -v ~/.ssh/id_rsa:/root/.ssh/id_rsa \ 72 | -v ~/.ssh/id_rsa.pub:/root/.ssh/id_rsa.pub \ 73 | -v $(pwd):/ansible/playbooks \ 74 | philm/ansible_playbook tests.yml -i inventory 75 | ``` 76 | 77 | Note: the SSH key used above should match the one used to run Ansible Target. 78 | 79 | ### Docker Compose 80 | 81 | An sample *docker-compose.yml* file is in this repo's test directory. 82 | 83 | Example: 84 | ``` 85 | docker-compose run --rm test remote.yml -i inventory 86 | ``` 87 | 88 | And if you'd like the ansible_target container to be recreated each time, do: 89 | ``` 90 | docker rm -v -f ansible_target 91 | ``` 92 | 93 | (Eventually Compose will be able to automatically remove services after each run, see https://github.com/docker/compose/issues/2774) 94 | 95 | #### Privileged Operations 96 | 97 | Notice the ```privileged: true``` option in the compose file. This enables us to better mimic a VM environment and perform operations such as installing the Docker Engine during a playbook run see [Docker Reference](https://docs.docker.com/engine/reference/commandline/run/#full-container-capabilities-privileged). 98 | -------------------------------------------------------------------------------- /test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | target: 2 | image: philm/ansible_target:latest 3 | container_name: ansible_target 4 | expose: 5 | - "22" 6 | volumes: 7 | - ~/.ssh/id_rsa.pub:/home/ubuntu/.ssh/authorized_keys 8 | privileged: true 9 | 10 | test: 11 | image: philm/ansible_playbook 12 | links: 13 | - target 14 | volumes: 15 | - ~/.ssh/id_rsa:/root/.ssh/id_rsa 16 | - ~/.ssh/id_rsa.pub:/root/.ssh/id_rsa.pub 17 | - .:/ansible/playbooks 18 | -------------------------------------------------------------------------------- /test/inventory: -------------------------------------------------------------------------------- 1 | [test] 2 | ansible_target 3 | -------------------------------------------------------------------------------- /test/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: 127.0.0.1 3 | connection: local 4 | tasks: 5 | - debug: msg="it works!" 6 | -------------------------------------------------------------------------------- /test/remote.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: test 3 | remote_user: ubuntu 4 | become: yes 5 | become_user: root 6 | 7 | # sample tasks to ensure things *just work* 8 | tasks: 9 | 10 | - name: view current distro 11 | shell: cat /etc/*-release 12 | register: distro 13 | - debug: var=distro 14 | 15 | # perform an action that requires root access 16 | - name: create user foo 17 | user: name=foo 18 | --------------------------------------------------------------------------------