0

我在 Windows 7 机器上使用 vagrant 和 docker,VirtualBox 作为 docker 主机 VM 的提供者。我有一个用docker提供者定义的流浪项目,以便vagrant up启动mongo容器。我没有mongo在 docker 主机 VM 中配置容器,因为我有时会想要mongo,有时postgres等等。

对于这种mongo情况,我正在尝试针对这个正在运行的mongo容器运行一些 mongo 集合初始化脚本,以使用 vagrant 设置索引等。除了之外,mongo镜像不运行任何东西,对于容器也是如此,因此使用配置器来运行这些操作不是一个选项。mongodhas_sshfalse

我尝试在链接到容器 running 的单独容器中运行 mongo shell mongodb,但要使其正常工作,我需要能够在命令在容器中运行时扩展mongo环境变量(MONGO_PORT_27017_TCP_ADDR和)。MONGO_PORT_27017_TCP_PORT

我一直在尝试使用 来执行此操作vagrant docker-run,但我找不到正确解释命令以正确扩展这些环境变量的方法。每次尝试都会导致mongo命令抱怨没有提供主机和端口(环境变量扩展为空)。

我最终希望能够做的是:

  1. 启动一个链接到正在运行的 mongo 容器的容器(因此它获取其 env 变量)
  2. 将 javascript 文件上传到包含我想做的 mongo 初始化的新容器
  3. 在容器上运行 shell 命令,如下所示:

mongo "$MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/db-name" initialize.js

  1. 取出容器

我可以尝试任何建议或其他方法吗?

典型的失败命令示例

Powershell 是这个 Windows 系统上的命令行解释器:

PS C:\Users\hoobajoob\Documents\Eclipse\workspace-sts-luna\project\.environment\vagrant\mongo-provisioner> vagrant docker-run default -- mongo
 '$MONGO_PORT_27017_TCP_ADDR:`$MONGO_PORT_27017_TCP_PORT/test' --eval "printjson(db.getCollectionNames())"
==> default: Docker host is required. One will be created if necessary...
    default: Docker host VM is already ready.
==> default: Creating the container...
    default:   Name: mongo-provisioner_default_1449193166_1449193166
    default:  Image: mongo
    default:    Cmd: mongo $MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test
    default:   Link: mongo-container:mongo
    default:

    default: Container is starting. Output will stream in below...
    default:
    default: MongoDB shell version: 3.0.7
    default: 2015-12-04T01:38:20.037+0000 E QUERY    Error: Missing host name in connection string ":/test"
    default:     at Error (<anonymous>)
    default:     at connect (src/mongo/shell/mongo.js:160:15)
    default:     at (connect):1:6 at src/mongo/shell/mongo.js:160
    default: exception:
    default: connect failed
    default:
A Docker command executed by Vagrant didn't complete successfully!
The command run along with the output from the command is shown
below.

Command: "docker" "run" "--name" "mongo-provisioner_default_1449193166_1449193166" "--link" "mongo-container:mongo" "--rm=true" "mongo" "mongo" "$MONGO_POR
T_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test" "--eval" "printjson(db.getCollectionNames())"

Stderr: exception: connect failed

Stdout: MongoDB shell version: 3.0.7
2015-12-04T01:38:20.037+0000 E QUERY    Error: Missing host name in connection string ":/test"
    at Error (<anonymous>)
    at connect (src/mongo/shell/mongo.js:160:15)
    at (connect):1:6 at src/mongo/shell/mongo.js:160

来源

码头主机Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 1.6.0"
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.hostname = "docker-host"
  config.vm.box_check_update = false
  config.ssh.insert_key = false
  config.vm.box = "williamyeh/ubuntu-trusty64-docker"
  config.vm.network "forwarded_port", guest: 27017, host: 27017
  config.vm.synced_folder ".", "/vagrant", disabled: true
end

mongod容器Vagrantfile:_

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 1.6.0"
VAGRANTFILE_API_VERSION = "2"
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.provider "docker" do |docker|
    docker.vagrant_vagrantfile = "../docker-host/Vagrantfile"
    docker.image = "mongo"
    docker.ports = ['27017:27017']
    docker.name = 'mongo-container'
  end
end

mongo shell容器Vagrantfile(这是我试图运行命令的容器,以便vagrant docker-run链接到mongod容器的 mongo 环境变量得到正确扩展):

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Specify Vagrant version and Vagrant API version
Vagrant.require_version ">= 1.6.0"
VAGRANTFILE_API_VERSION = "2"
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'

# Create and configure the Docker container(s)
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.provider "docker" do |docker|
    docker.vagrant_vagrantfile = "../docker-host/Vagrantfile"
    docker.image = "mongo"
    docker.link("mongo-container:mongo")
  end
end
4

1 回答 1

0

目前,我发现 Vagrant 的 docker 提供商在我可以使用它执行的 docker 容器操作范围方面相当有限。

我研究了ssh在 mongo 容器中运行,这将允许我在mongo容器上运行 Vagrant 的配置程序,这样我就可以让这些脚本以这种方式运行。但是,这需要 a) 定义自定义映像并重新处理入口点,以便启动sshmongodb)has_ssh=true在 docker 提供程序中进行设置Vagrantfile

不幸的是,该选项不能很好地与当前版本的 vagrant 配合使用,vagrant up如果我在 docker provider 中设置has_ssh,它会在我运行时挂在我的 Windows 系统上。trueVagrantfile

所以,对于这个 Vagrant 新手来说,我的选择似乎是有限的。

我目前认为更好的方法可能是完全放弃使用这两个 docker 提供程序Vagrantfile项目,而是在一个 docker host 中定义一堆不同的配置器Vagrantfile

然后,如果我想启动一个特定的容器,我可以定义并运行一个只运行该容器的配置器(不执行任何 mongo 初始化)。如果我想运行这些 mongo 初始化脚本,那么我有一个单独的配置器来执行这些操作,依此类推。

拆除容器然后需要vagrant ssh使用相应的docker rm命令运行。

诉诸这一点似乎很可惜,但我没有太多运气试图通过vagrant docker-run.

更新:2015 年 12 月 4 日

我完全放弃了使用 Vagrant 的 docker 提供程序,主要是因为至少在我的情况下,我发现 docker 提供程序在其支持的 docker 词汇方面太有限了,无法满足我的需求。这个结论是由我既不是 Vagrant 也不是 Docker 的老手来证明的,所以我完全有可能错过了一些东西。

因此,例如,为了初始化 mongo 数据库,我希望能够使用可能由mongoDB管理员在目标站点上运行的相同 javascript 初始化文件来执行此操作,这些文件来自开发源树。必须构建一个预先配置了这些文件的自定义 docker mongo 容器的开销太大了。

至少据我所知,Vagrant 的方式是使用file配置器将该文件复制到正在运行的容器中,并使用script配置器在容器上执行它。Vagrantfilescript供应商需要在容器上使用 SSH 才能工作。

但是,出于多种原因,在 docker Land 中似乎普遍建议不要在容器中运行 SSH,所以如果我不必这样做,我宁愿不这样做。

在不创建预置有这些文件的自定义容器的情况下实现此目的的(或一种)docker 方法是使用docker cp <container>docker exec <container>在运行的容器上实现此目的。Vagrant 的 docker 提供程序命令都没有显示这些,所以我没有看到我将如何通过 docker 提供程序到达那里。

所以,我相信,使用 Vagrant 的配置器是完全合理的,但只有在与 docker 主机 VM(在我的例子中是一个 VirtualBox 盒子)交互时,SSH 访问没有任何争议(据我所知)。

我将所有容器生命周期操作——创建、启动、停止、重新启动、rm 等移动到Vagrantfiledocker 主机配置上的配置器中。为了执行这些操作,我坚持使用 docker cli。

Docker Host VM 上的Vagrantfile配置器如下所示:

# provisioners
  config.vm.provision "host.provision.scripts.mongo", type: "file", source: $mongoProvisionInit, destination: $hostProvisionMongoInit
  config.vm.provision "mongo.run", type: "shell", inline: $dockerRun_mongo
  config.vm.provision "mongo.provision.scripts", type: "shell", inline: $dockerCp_MongoInit
  config.vm.provision "mongo.db.init", type: "shell", inline: $dockerExec_mongoDbInit
  config.vm.provision "mongo.stop", type: "shell", inline: $dockerStop_mongo
  config.vm.provision "mongo.start", type: "shell", inline: $dockerStart_mongo
  config.vm.provision "mongo.restart", type: "shell", inline: $dockerRestart_mongo
  config.vm.provision "mongo.rm", type: "shell", inline: $dockerRm_mongo
e

...inline脚本看起来像这样:

$dockerRun_mongo = <<MONGO
echo '>>> docker run --name mongo-container -p 27017:27017 -d mongo'
docker run --name mongo-container -p 27017:27017 -d mongo
MONGO

$dockerCp_MongoInit = <<MONGO
echo '>>> docker exec mongo-container mkdir /home/vagrant'
docker exec mongo-container mkdir -p /home/vagrant
echo '>>> docker cp ./provision/mongo/initialize.js mongo-container:/home/vagrant/mongo.initialize.js'
docker cp ./provision/mongo/initialize.js mongo-container:/home/vagrant/mongo.initialize.js
MONGO

$dockerExec_mongoDbInit = <<MONGO
echo '>>> docker exec mongo-container mongo mongo db-name /home/vagrant/mongo.initialize.js'
docker exec mongo-container mongo db-name /home/vagrant/mongo.initialize.js
MONGO

$dockerStop_mongo = <<MONGO
echo '>>> docker stop mongo-container'
docker stop mongo-container
MONGO

...然后我将所有这些连接到gradle使用来自 bmuschko: 的 vagrant 插件'com.bmuschko:gradle-vagrant-plugin:2.0'。因此,我的开发环境可以通过 gradle 任务实现自动化,这些任务initializeMongoAndRun会在这些不同的供应商上发出vagrant provision --provision-with命令以完成工作。

这意味着所有从事这个项目的开发人员都需要同意在 vm 中托管 docker,即使在 Linux 系统上也是如此。为了在机器上获得一致的 docker 和容器体验,这似乎是一个可以接受的权衡。

我会密切关注 Vagrantdocker提供者。也许它对于这些类型的用途会变得更加实用,或者我会弄清楚我错过了什么才能让它发挥作用。

于 2015-12-04T02:14:42.337 回答