0

DockerホストVMのプロバイダーとしてVirtualBoxを備えたWindows 7マシンでvagrantとdockerを使用しています。コンテナーを開始するdockerように、プロバイダーで定義された vagrant プロジェクトがあります。docker ホスト VM でコンテナーをプロビジョニングしていません。vagrant upmongomongomongopostgres

このmongo場合、この実行中のmongoコンテナーに対していくつかの mongo コレクション初期化スクリプトを実行して、vagrant を使用してインデックスなどを設定しようとしています。mongoイメージは 以外のものを実行せず、コンテナーも同様であるmongodため、プロビジョナーを使用してこれらの操作を実行することはできません。has_sshfalse

実行中のコンテナにリンクされた別のコンテナでmongoシェルを実行しようとしましたが、それが機能するには、コマンドがコンテナで実行されるときに環境変数(および)mongodbを展開できる必要があります。mongoMONGO_PORT_27017_TCP_ADDRMONGO_PORT_27017_TCP_PORT

を使用してこれを実行しようとしましたがvagrant docker-run、これらの環境変数が正しく展開されるようにコマンドを適切に解釈する方法が見つかりません。試行するたびにmongo、ホストとポートが提供されていないというコマンドのエラーが発生しました (環境変数が空に展開されます)。

私が最終的にできるようにしたいのは:

  1. 実行中の mongo コンテナーにリンクされたコンテナーを開始します (環境変数を取得します)
  2. やりたいmongoの初期化を含むJavaScriptファイルを新しいコンテナにアップロードします
  3. 次のようにコンテナでシェル コマンドを実行します。

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(これは、コンテナーにリンクされた mongo 環境変数が正しく展開されるようにコマンドを実行しようとしてvagrant docker-runいるmongodコンテナーです):

# -*- 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 コンテナー操作の範囲がかなり制限されていることがわかりました。

sshmongo コンテナー内で実行することを検討しました。これにより、Vagrant のプロビジョナーをコンテナーで実行できるmongoようになり、これらのスクリプトをそのように実行できるようになりました。sshただし、これには、a) カスタム イメージを定義し、エントリポイントを再加工して と の両方を開始する必要があります。mongodまた、b) has_ssh=truedocker プロバイダーで設定する必要がありますVagrantfile

残念ながら、そのオプションは現在のバージョンの vagrant ではうまく機能しません。docker providervagrant upに設定has_sshすると、実行時に Windows システムでハングします。trueVagrantfile

したがって、この Vagrant 初心者にとって、私の選択肢は限られているようです。

現在、より良いアプローチは、両方の docker プロバイダーVagrantfileプロジェクトの使用を完全に中止し、代わりに 1 つの docker host でさまざまなプロビジョナーを定義することだと考えていますVagrantfile

次に、特定のコンテナーを起動したい場合は、そのコンテナーを実行するだけのプロビジョナーを定義して実行できます (mongo の初期化は実行しません)。これらの mongo 初期化スクリプトを実行したい場合は、それらの操作を実行する別のプロビジョナーを用意します。

コンテナーを破棄するにはvagrant ssh、対応するdocker rmコマンドを実行する必要があります。

それに頼るのは残念ですが、を介してmongoを初期化しようとしてもあまり運がありませんvagrant docker-run

更新: 2015 年 12 月 4 日

私は Vagrant の docker プロバイダーの使用を完全に断念しました。これは主に、少なくとも私の場合、docker プロバイダーがサポートする docker ボキャブラリーが私のニーズを満たすにはあまりにも限られていることがわかったためです。この結論は、私が Vagrant または Docker のベテランではないという事実によって修飾されているため、何かを見落としている可能性は十分にあります。

たとえば、mongo データベースを初期化するには、ターゲット サイトの管理者が実行する可能性のある同じ JavaScript 初期化ファイルを使用して実行できるようにしたいと考えていますmongoDB。これらは開発ソース ツリーから取得されます。これらのファイルで事前にプロビジョニングされたカスタム docker mongo コンテナーを構築する必要があるのは、オーバーヘッドが大きすぎます。

Vagrant の方法は、少なくとも私が理解している限りでは、プロビジョナーを使用しfileてそのファイルを実行中のコンテナーにコピーし、プロビジョナーを使用してコンテナーでscript実行することです。Vagrantfilescriptプロビジョナーが機能するには、コンテナーで SSH が必要です。

しかし、ドッカーランドでは、いくつかの理由からコンテナーで SSH を実行しないことが一般的に推奨されているようです。そのため、必要がなければ実行しないことをお勧めします。

これらのファイルで事前にプロビジョニングされたカスタム コンテナーを作成せずにこれを実現する (または 1 つの) Docker の方法は、実行中のコンテナーでこれを実現するためにdocker cp <container>使用することです。docker exec <container>これらはいずれも、Vagrant の docker プロバイダー コマンドでは表示されないため、docker プロバイダーを介してそこに到達する方法がわかりませんでした。

したがって、Vagrant のプロビジョナーを使用することは完全に合理的であると私は信じていますが、それは Docker ホスト VM (私の場合は VirtualBox ボックス) と対話する場合に限られます。 )。

コンテナーのライフサイクル操作 (作成、開始、停止、再起動、RM など) をすべてVagrantfile、docker ホストの構成のプロビジョナーに移動しました。これらの操作を実行するために、私は 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

...次に、これらすべてを配線しgradleて、 bmuschko: の vagrant プラグインを使用します'com.bmuschko:gradle-vagrant-plugin:2.0'。そのため、私の開発環境は のような gradle タスクで自動化できます。これらのさまざまなプロビジョナーでコマンドinitializeMongoAndRunを発行して作業を完了させます。vagrant provision --provision-with

これは、このプロジェクトに取り組んでいるすべての開発者が、たとえ Linux システムであっても、vm で docker をホストすることに同意する必要があることを意味します。マシン間で一貫した Docker とコンテナーのエクスペリエンスを得るためには、これは許容できるトレードオフのようです。

私は Vagrantdockerプロバイダーに注目します。おそらく、これらのタイプの使用に対してより機能的になるか、それを機能させるために何が欠けていたかを理解するでしょう.

于 2015-12-04T02:14:42.337 に答える