如何使用vagrant docker-run与容器环境变量扩展

时间:2015-12-03 22:08:32

标签: mongodb docker vagrant vagrant-windows

我在Windows 7计算机上使用vagrant和docker,VirtualBox作为docker主机VM的提供程序。我有一个使用docker提供程序定义的vagrant项目,以便vagrant up将启动mongo容器。我没有在docker host VM中配置mongo容器,因为我有时需要mongo,有时候需要postgres等。

对于mongo情况,我正在尝试针对此正在运行的mongo容器运行一些mongo集合初始化脚本,以使用vagrant设置索引等。 mongo图片不会运行mongod以外的任何内容,因此容器的has_sshfalse,因此使用配置程序运行这些操作不是一种选择。

我尝试在链接到运行mongodb的容器的单独容器中运行mongo shell,但为了实现这一点,我需要能够扩展mongo环境变量({{ 1}}和MONGO_PORT_27017_TCP_ADDR)命令在容器中运行时。

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

我最终希望能够做到的是:

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

    1. 删除容器
    2. 我可以尝试任何建议或其他方法吗?

      典型故障命令的示例

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

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

      来源

      泊坞主机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容器的mongo环境变量得到正确扩展):

      mongod

1 个答案:

答案 0 :(得分:0)

目前,我发现Vagrant的码头提供商在我可以用它执行的码头集装箱操作范围方面相当有限。

我考虑在mongo容器中运行ssh,这样我就可以在mongo容器上运行Vagrant的配置程序,这样我就可以让这些脚本以这种方式运行。但是,这需要a)定义自定义图像并重新处理入口点,以便启动sshmongod,以及b)在docker provider has_ssh=true中设置Vagrantfile

遗憾的是,该选项与当前版本的vagrant不兼容,如果我在docker中将vagrant up设置为has_ssh,则当我运行true时会在我的Windows系统上挂起提供者Vagrantfile

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

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

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

拆除容器需要使用相应的Vagrantfile命令运行vagrant ssh

诉诸于此似乎是一种耻辱,但我没有太多运气试图通过docker rm初始化mongo。

更新:2015年12月4日

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

例如,为了初始化mongo数据库,我希望能够使用可能由目标站点上的vagrant docker-run管理员运行的相同javascript初始化文件来执行此操作,并且这些来自开源树。如果必须构建一个预先配置了这些文件的自定义docker mongo容器,则需要花费太多的开销。

至少在我理解的情况下,流浪的方式是使用mongoDB配置程序将该文件复制到正在运行的容器,并使用file配置程序在容器上执行它。 Vagrant的scriptfile配置程序需要在容器上使用SSH才能工作。

但是,在码头工人的土地上似乎是a common recommendation并不是出于各种原因在容器中运行SSH,所以如果我没有,我不想这样做到。

在不创建预配置这些文件的自定义容器的情况下实现此目的的(或一个)docker方法是使用scriptdocker cp <container>以在正在运行的容器上实现此目的。这些都不是由Vagrant的docker provider命令浮出水面的,所以我没有看到我将如何通过docker provider到达那里。

所以,我相信,使用Vagrant的配置程序是完全合理的,但只有在与Docker主机VM(我的情况下是一个VirtualBox盒)进行交互时,才能使用SSH访问权限。任何争议(据我所知)。

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

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

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

...然后我使用bmuschko:$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 的vagrant插件将所有这些连接到gradle。因此,我的开发环境可以通过诸如'com.bmuschko:gradle-vagrant-plugin:2.0'之类的gradle任务实现自动化,这些任务会在这些不同的配置程序上发出initializeMongoAndRun命令以完成工作。

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

我会关注Vagrant vagrant provision --provision-with提供商。对于这些类型的用途,它可能会变得更加实用,或者我会弄清楚我失去了什么使它成功。