Vagrant::Communicator::Docker
This is a communicator plugin allowing vagrant to access docker instances as if they have SSH.
This was created to facilitate host file management using a vagrant host file manager plugin, which requires SSH to fetch, edit, and put back container hosts files. The assumption that vagrant SSH communicator makes, is that all containers have SSH - They do not.
This communicator will make vagrant tasks that require SSH, interact with the docker instances, as if SSH exists, by using the Docker API.
Shell scripts used during provisioning will also be executed, so will facilitate provisioning shel scripts as well (from 1.0.8). Please note that these will always run as root inside the docker instance.
This has only been used in a Linux environment.
Requirements
- Docker API gem. Although set as a dependency for the communicator, you must install this as a vagrant plugin, else it will not be located to be used by vagrant.
vagrant plugin install docker-api
Installation
Needs to be installed as a vagrant plugin
vagrant plugin install vagrant-communicator-docker
Manual install
- install using:
vagrant plugin install vagrant-communicator-docker-[version].gem
- install dependency
vagrant plugin install docker-api
(must be version 2.0.0 or greater)
Usage
- You need to set your vagrant instance to have SSH using
has_ssh
- You need to set the communicator using
vm.communicator = 'docker'
- You can set the shell to use with
vm.communicator.bash_shell
- You can set the shell wait with
vm.communicator.bash_wait
Example vagrant definition:
config.vm.define "database", primary: false do |database|
database.hostmanager.aliases = [ "database."+dev_domain ]
database.vm.network :private_network, ip: "172.20.0.208", subnet: "172.20.0.0/16"
database.vm.hostname = "database"
database.communicator.bash_shell = '/bin/sh'
database.communicator.bash_wait = 30
database.vm.communicator = 'docker'
database.vm.provider 'docker' do |d|
d.image = "mysql:5.7"
d.has_ssh = true
d.name = "database"
d.remains_running = true
end
end
Communication over TCP with remote Docker
By default the communicator connects with Docker over a local socket. You can override this, and allow remote Docker connection by setting an environment variable:
DOCKER_HOST=tcp://[DOCKER HOST]:[PORT]
example:
DOCKER_HOST=tcp://127.0.0.1:2375
vagrant up
Shell
The default shell will be /bin/bash inside the docker container. You can override this using : vm.communicator.bash_shell = '/bin/sh';
to use /bin/sh (or any other shell)
If you get the error:
The guest operating system of the machine could not be detected!
Vagrant requires this knowledge to perform specific tasks such
as mounting shared folders and configuring networks. Please add
the ability to detect this guest operating system to Vagrant
by creating a plugin or reporting a bug.
you likely need to change the shell to /bin/sh OR increase the shell_wait (default is 10)
OR the docker image in use (example: debian:bullseye) is not staying active after created.
You can force that by passing -t
as a docker create arg in the vagrant setup
Vagrant.configure("2") do |config|
config.vm.define "test-case", primary: false do |d|
d.vm.communicator = 'docker'
d.vm.provider 'docker' do |box|
box.image = "debian:bullseye"
box.has_ssh = true
box.remains_running = true
box.create_args = ["-t"]
end
end
end
it would seem box.remains_running = true
don't work on all docker images !
shell_wait
I have found some docker instances need a little extra time to initialise, before docker can send commands The default wait timeout is 10s. Increase in increments of 5 to see if you can overcome issue.
Solved issues?
Not had this for some time, so I think solved due to ongoing changes.
Problems with some docker images, failing with message that image is not running
I have not managed to spend time on this, to pin it down, but some (random) docker images will fail if you set d.has_ssh = true
- The only fix is to set that to false, which can stop other functions (example usage of a hostmanager plugin)
You can run a global trigger to overcome this, allowing hostmanagers to update after it was completed:
config.trigger.after :up do |trigger|
trigger.run = {inline: "bash -c 'vagrant hostmanager --provider docker'"}
end
Debug
vagrant halt database && vagrant up database --debug &>/tmp/debug.log
then view the debug log.
You will see debug entries with the string: DOCKER COMMUNICATOR
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/ProxiBlue/vagrant-communicator-docker.
License
The gem is available as open source under the terms of the MIT License.