Ernst de Haan
Ernst de Haan

Reputation: 467

What is the simplest way to install Redis in Docker+Vagrant

I would like to have a Docker container running Redis, inside a Vagrant VM. I'd like things to be as simple as they can possibly be, so minimal configuration.

A little bit of research shows:

So the setup should be really straight forward, I expected to just have to connect the dots. So I came up with this Vagrantfile:

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "chef/centos-6.5"
  config.vm.provision "docker" do |docker|
    docker.run "dockerfile/redis"
  end
end

Looks simple - good. Now when I run vagrant up I would expect:

  1. The VM starts up.
  2. Docker gets installed.
  3. The Docker daemon dockerd is started.
  4. The Docker container for Redis dockerfile/redis is downloaded and installed.
  5. The container is started.

All seems to work except step 3, since with this Vagrantfile I get:

==> default: Verifying vmnet devices are healthy...
==> default: Preparing network adapters...
==> default: Starting the VMware VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 192.168.249.190:22
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection refused. Retrying...
==> default: Machine booted and ready!
==> default: Forwarding ports...
    default: -- 22 => 2222
==> default: Configuring network adapters within the VM...
==> default: Waiting for HGFS kernel module to load...
==> default: Enabling and configuring shared folders...
    default: -- /Users/ernst/nikon/nikon-elk-vm2: /vagrant
==> default: Running provisioner: docker...
    default: Installing Docker (latest) onto machine...
    default: Configuring Docker to autostart containers...
==> default: Starting Docker containers...
==> default: -- Container: dockerfile/redis
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!


          rm -f /var/lib/vagrant/cids/cc3cfcdebad9167099d85261c6311a0011838655
          docker run --cidfile=/var/lib/vagrant/cids/cc3cfcdebad9167099d85261c6311a0011838655 -d --name dockerfile-redis  dockerfile/redis


Stdout from the command:



Stderr from the command:

2014/11/26 12:38:40 Cannot connect to the Docker daemon. Is 'docker -d' running on this host?

I could obviously revert to using the shell provisioner, but I would love to keep my Vagrantfile simple and use the docker provisioner that Vagrant offers.

So what am I missing?

Upvotes: 4

Views: 3501

Answers (2)

Yser
Yser

Reputation: 2106

I think you confused provider and provisioner. Provisioner offer an environment for configuring the VM. In case of Docker that means you can add containers to the docker-host which so to say "configures" the VM in some way. Other provisioners are "Shell", "Chef" or "Puppet". Providers are tools to spawn VM's or in this case containers. Other Providers are for example "VirtualBox" or "AWS".

Here's some code which may help you get started:

ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
Vagrant.configure(2) do |config|
  config.vm.define "docker-host", autostart: false do |host|
    host.vm.hostname = "docker-host"
    host.vm.box = "chef/centos-6.6"
    # The following line terminates all ssh connections. Therefore
    # Vagrant will be forced to reconnect.
    # That's a workaround to have the docker command in the PATH
    host.vm.provision "shell", inline: "ps aux | grep 'sshd:' | awk '{print $2}' | xargs kill"
    host.vm.provision "docker"
  end

  host.vm.define 'container', primary: true do |ws|
    ws.vm.hostname = 'container'
    ws.vm.provider "docker" do |d|
      d.image = "library/redis:latest"
      d.vagrant_machine = "dev-host"
      d.vagrant_vagrantfile = "./Vagrantfile"
      d.force_host_vm = true
    end
  end
end

Output:

$ vagrant up container
Bringing machine 'container' up with 'docker' provider...
==> container: Docker host is required. One will be created if necessary...
    container: Vagrant will now create or start a local VM to act as the Docker
    container: host. You'll see the output of the `vagrant up` for this VM below.
    container:  
    container: Importing base box 'chef/centos-6.6'...
    container: Matching MAC address for NAT networking...
    container: Checking if box 'chef/centos-6.6' is up to date...
    container: Setting the name of the VM: dev-host
    container: Clearing any previously set network interfaces...
    container: Preparing network interfaces based on configuration...
    container: Adapter 1: nat
    container: Forwarding ports...
    container: 22 => 2222 (adapter 1)
    container: Running 'pre-boot' VM customizations...
    container: Booting VM...
    container: Waiting for machine to boot. This may take a few minutes...
    container: SSH address: 127.0.0.1:2222
    container: SSH username: vagrant
    container: SSH auth method: private key
    container: Warning: Connection timeout. Retrying...
    container: Warning: Connection timeout. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Warning: Remote connection disconnect. Retrying...
    container: Machine booted and ready!
    container: Checking for guest additions in VM...
    container: Setting hostname...
    container: Mounting shared folders...
    container: /vagrant => <PATH>
    container: /tmp/vagrant-cache => <PATH>
    container: Configuring cache buckets...
    container: Running provisioner: docker...
    container: Installing Docker (latest) onto machine...
    container: Configuring Docker to autostart containers...
    container: Configuring cache buckets...
    container: Running provisioner: shell...
    container: Running: inline script
    container: Configuring cache buckets...
==> container: Syncing folders to the host VM...
    container: Mounting shared folders...
    container: /var/lib/docker/docker_1417023698_82709 => <PATH>
==> container: Warning: When using a remote Docker host, forwarded ports will NOT be
==> container: immediately available on your machine. They will still be forwarded on
==> container: the remote machine, however, so if you have a way to access the remote
==> container: machine, then you should be able to access those ports there. This is
==> container: not an error, it is only an informational message.
==> container: Creating the container...
    container:   Name: virtual-dev_container_1417023701
    container:  Image: library/redis:latest
    container: Volume: /var/lib/docker/docker_1417023698_82709:/vagrant
    container:  
    container: Container created: 2f020d26797f3bd0
==> container: Starting container...
==> container: Provisioners will not be run since container doesn't support SSH.

Usage:

Use vagrant up to start the redis container. Since we force a host for the container vagrant will automatically start it if it's not available. You can start the host directly with vagrant up docker-host --provider=virtualbox. After everything started you can ssh into the docker-host by using vagrant ssh docker-host. Note that most Docker containers don't have SSH so you can't ssh them by using vagrant ssh container. What you can do to look into the container is using the following "trick" as long as the container is running:

  • SSH into the docker-host
  • use docker ps copy the ID of the container
  • use docker exec -it <ID-of-container> /bin/bash
  • now you are on the container without SSH

Additional notes:

ENV['VAGRANT_DEFAULT_PROVIDER'] - 'docker' - Sets the default Provider. In case of Docker you don't have to type vagrant up --provider=docker. Default is virtualbox.

d.vagrant_vagrantfile = "./Vagrantfile" - Sets the location of the Vagrantfile of the docker host. Thus you can have a own Vagrantfile for every container! Anyway, this example uses the multi-mechine structure [1].

You can adress docker-host or container by adding it to your command. For example vagrant up docker-host --provider=virtualbox

Further reading:

Vagrant Multi-Machine

Vagrant Docker Provisioner

Vagrant Docker Provider

Upvotes: 2

Fedalto
Fedalto

Reputation: 1567

Your Vagrantfile is correct.

This seems to be an issue with the chef/centos-6.5 box.

On this box, you have to update device-mapper-libs first.

I had success with this Vagrantfile:

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "chef/centos-6.5"

  config.vm.provision "shell",
    inline: "yum update -y device-mapper-libs"

  config.vm.provision "docker" do |docker|
    docker.run "redis"
  end
end

Inside the VM:

[vagrant@localhost ~]$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
7d55185f859c        redis:2             "/entrypoint.sh redi   10 seconds ago      Up 9 seconds        6379/tcp            redis

Upvotes: 2

Related Questions