【问题标题】:How to use vagrant docker-run with container environment variable expansion如何使用 vagrant docker-run 和容器环境变量扩展
【发布时间】:2016-03-08 17:25:44
【问题描述】:

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

对于mongo 案例,我正在尝试针对这个正在运行的mongo 容器运行一些mongo 集合初始化脚本,以使用vagrant 设置索引等。 mongo 镜像不运行除 mongod 之外的任何东西,因此 has_ssh 是容器的 false,因此不能使用配置器来运行这些操作。

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

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

我最终想做的是:

  1. 启动一个链接到正在运行的 mongo 容器的容器(这样它就可以获取其环境变量)
  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

来源

docker主机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

【问题讨论】:

    标签: mongodb docker vagrant vagrant-windows


    【解决方案1】:

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

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

    不幸的是,该选项不适用于当前版本的 vagrant,如果我在 docker 提供程序 Vagrantfile 中将 has_ssh 设置为 true,则当我运行 vagrant up 时,它会挂在我的 Windows 系统上。

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

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

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

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

    诉诸于此似乎很可惜,但我没有太多运气尝试通过 vagrant docker-run 初始化 mongo。

    更新:2015 年 12 月 4 日

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

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

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

    但是,由于多种原因,在 docker land 中似乎是a common recommendation 不在容器中运行 SSH,所以如果我不必这样做,我宁愿不这样做。

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

    因此,我相信,使用 Vagrant 的配置器是完全合理的,但仅在与 docker 主机 VM(在我的情况下为 VirtualBox 机器)交互时,SSH 访问没有任何争议(就我知道)。

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

    Docker 主机 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
    

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

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

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

    【讨论】:

      猜你喜欢
      • 2018-04-29
      • 2023-03-03
      • 2016-05-06
      • 2017-12-18
      • 2020-11-28
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      • 2023-03-30
      相关资源
      最近更新 更多