Run Command Inside of Docker Container Using Ansible
Solution 1
You should be able to execute a script (with your sequence of command in it) with docker exec
:
docker exec container-name bash -l -c /path/to/script > /path/to/log
(See also "Why do I have to use bash -l -c
inside my container?")
-
/path/to/script
should be accessible by your Ansible process. -
/path/to/log
is a path inside the container, that could be shared in a volume.
Solution 2
After discussion with some very helpful developers on the ansible github project, a better way to do this is like so:
- name: add container to inventory
add_host:
name: [container-name]
ansible_connection: docker
changed_when: false
- name: run command in container
delegate_to: [container-name]
raw: bash
If you have python installed in your image, you can use the command module or any other module instead of raw.
If you want to do this on a remote docker host, add:
ansible_docker_extra_args: "-H=tcp://[docker-host]:[api port]"
to the add_host block.
See the Ansible documentation for a more complete example.
Solution 3
You can run commands within docker containers using the command module For example this code will execute echo "Hello remote machine"
within my_container on the remote machine:
tasks:
- name: Execute commands in docker container
command: docker exec -it my_container bash -c 'echo "Hello remote machine"'
For running the same command within the local machine, just use the local_action
flag:
tasks:
- name: Execute commands in docker container
local_action: command docker exec -it my_container bash -c 'echo "Hello local machine"'
Solution 4
Since Ansible 2.10 docker_container_exec
is part of the community.docker
collection:
- name: Run a simple command (command)
community.docker.docker_container_exec:
container: foo
command: /bin/bash -c "ls -lah"
chdir: /root
register: result
- name: Print stdout
debug:
var: result.stdout
Nigel Earle
Always learning and growing. Love building full-stack JavaScript web applications!
Updated on July 09, 2022Comments
-
Nigel Earle almost 2 years
what I'm trying to accomplish is to run commands inside of a Docker container that has already been created on a Digital Ocean Ubuntu/Docker Droplet using Ansible.
Can't seem to find anything on this, or I'm majorly missing something. This is my Ansible task in my play book. I'm very new to Ansible so any advice or wisdom would be greatly appreciated.
- name: Test Deploy hosts: [my-cluster-of-servers] tasks: - name: Go Into Docker Container And Run Multiple Commands docker: name: [container-name] image: [image-ive-created-container-with-on-server] state: present command: docker exec -it [container-name] bash
-
schmidlop over 8 yearsCould you clarify the meaning of "should be accessible by your Ansible process."? Does that mean the script should be on the ansible control machine? The docker host? or inside the container?
-
VonC over 8 years@schmidlop I meant: there is an container already running. Inside that container, there is
/path/to/script
which did not execute properly. A way to try again that script is to execute it (from adocker exec
command run from the Linux host) and log its results on the host in/path/to/log
-
VonC over 8 years@schmidlop I agree. My answer is meant to be run from the docker host.
-
Bernie over 7 yearsThis works if the docker container is on the same machine on which the ansible script is running. What if the docker container is running on a different machine?
-
VonC over 7 yearsInteresting, and more precise than my answer. +1
-
techraf over 7 yearsThanks for help. As usually, restarting from scratch resolved problems.
-
DMCoding over 7 yearsI don't believe that's true, @Bernie. My understanding is that local_action does as you describe, but the command module always runs on the remote host, unless the delegate_to parameter is supplied.
-
RichVel about 7 yearsThis does require Docker API access to the host with the Docker Engine (if not localhost) - if firewall rules block this, you may need to use the
docker exec ... bash -c ...
approach. I don't see how you could use delegate_to for the remote host, since it's already being used for the docker connection to container. -
vikas027 almost 7 yearsI had to use
docker exec -i <my_container>
to avoid this errorthe input device is not a TTY
-
Christian Berendt about 6 yearsThe PR was not merged and the author closed it with the note "I admit now, there is no point to my module.".
-
idjaw almost 6 yearsThis answer should be updated to reflect that the MR is closed. The upvotes are misleading as well. Unless the code can be directly shared as an alternative where someone can leverage this as their own custom plugin to do this?
-
Bernie almost 6 years@idjaw See the first line of the answer. Also, if you read through the comments in the pull request it seems like there may be some value to the plugin after all. I was able to solve my problem at the time without using the plugin, so have left it for others to take the code from my pull request and use it as they see fit. The code is still available in the pull request: github.com/ansible/ansible/pull/20112/files. I haven't copied it here as I think it's easily enough accessible from GitHub.
-
idjaw almost 6 years@Bernie Thanks for the message back! (I just noticed the 'other' answer is your answer as well.... :)). The other answer did in fact help me get on track to solving my problem. I ended up doing something like this when it came to the execution of the actual command. My challenge was having to copy a templated file to the container, while wanting to minimize custom docker commands in shell to facilitate testing for idempotent behaviour. Thanks again. :)
-
Ayra over 5 yearsI know it's been a long time but anyone would be abble to explain why did he put the "changed_when: false" to make it worked ?
-
Jack_Hu over 5 years@Ayra - It's not strictly necessary. It will just make the play feedback show:
ok: [127.0.0.1]
, instead of:changed: [127.0.0.1]
-- It's just arguably more descriptive of what's going on, as the host has been added, rather than changed (when talking about it in English anyway). -
Mani almost 5 yearsIs there a way to use this to run commands inside docker container in remote hosts?
-
Mani almost 5 years@Bernie No that's not the proper thing to do when you use Ansible. I was looking into something like using
docker_container
withdelegate_to
. -
Bernie almost 5 years@Mani Well, if you say so. You can read through my discussion with the Ansible devs here, along with the link to the Ansible documentation on non-ssh connections at the end of the answer. This answer is more than 2 years old, if it doesn't answer your question, perhaps you need to ask a new one.
-
Vano over 4 years@Mani has a point. One don't necessarily has to configure custom remote docker deamon access. Just access docker locally from the target host... Mani plz share if you found a way...
-
Liam over 3 yearsJust a note to be careful if you're using
ansible_ssh_user
, especially via the CLI, as it'll try to login to that user on the container. -
shgnInc about 3 yearsThe link for
non-ssh-connection-types
has been broken and the right one is: docs.ansible.com/ansible/latest/user_guide/… -
VonC almost 3 yearsThat seems a more up-to-date approach than my answer. Upvoted.