2014年5月12日月曜日

Vagrant1.6のDockerの機能使ってコンテナにSSH接続してWebサーバー立ててみたよ

このエントリーをはてなブックマークに追加 はてなブックマーク - Vagrant1.6のDockerの機能使ってコンテナにSSH接続してWebサーバー立ててみたよ

Vagrant1.6からDockerを利用できるという事で色々使ってみたのでそのメモ。

Feature Preview: Docker-Based Development Environments

  • Imageを指定してコンテナを起動
  • Dockerfileを利用してコンテナの起動
  • コンテナにSSH接続してみる
  • SSH接続してWebサーバー立ててみる

確認環境

  • MaxOSX 10.9.2
  • Vagrant 1.6.1

そもそもMacやWindowsだとDockerって動かないのでは?

DockerはMacWindowsのOSでは利用出来ません。 そのため、VagrantではDockerを動かす為に専用LinuxVM(boot2docker)を起動して、その上でDockerを動作させます。

コンテナを起動する

Vagrantでコンテナを起動する方法として以下の2つがあります。

  1. Imageを指定する
  2. Dockerfileを利用してコンテナを起動する

1.Imageを指定する

以下のようにVagrantfileを作成します。

VAGRANTFILE_API_VERSION = "2" 

Vagrant.configure("2") do |config|
    config.vm.provider "docker" do |d| 
        d.image = "paintedfox/postgresql"
    end 
end

上記の例では以下を設定しています。

  • 利用するProviderはdockerを指定
  • 利用するイメージはpaintedfox/postgresqlを指定

次に以下のコマンドでコンテナを起動させます。

$vagrant up --provider=docker

上記によって以下が順番に実行されます。

  1. VM(boot2docker)が起動する
  2. VM(boot2docker)で指定したイメージをpullする
  3. VM(boot2docker)上でdockerを実行し、指定したコンテナをrunする

初回実行時にはイメージのダウンロードを行うため、通信環境によっては多少時間が掛かりますが、辛抱強く待ちます。あまりにも遅いとVagrantのboot_wait時間を超えて起動に失敗してしまいますので、通信環境の良い所で実行するのをおすすめします。(一度pullが終われば、以降はダウンロードする処理は実行されません)

終わった後にVagrantの状態を1.6の新機能global-statusを利用して確認してみます。

$vagrant global-status
id       name    provider   state     directory                                      
-------------------------------------------------------------------------------------
2a00b3b  default virtualbox running   /Users/toshihirock/.vagrant.d/data/docker-host 
3b48b7b  default docker     preparing /Users/toshihirock/vagrant/docker              

providerがvirtualboxとなっているのが、コンテナを動かす為に起動されたVMで、dockerとなっているのが先ほどrunしたコンテナになります。

boot2dockerのVMにも接続する事ができるので、こちらからもコンテナの状態を確認してみます。 ログインする際にはglobal-statusで確認したidを指定します。

$vagrant ssh 2a00b3b 
                        ##        .
                  ## ## ##       ==
               ## ## ## ##      ===
           /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
           \______ o          __/
             \    \        __/
              \____\______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
boot2docker: 0.8.0
$docker ps -a
CONTAINER ID        IMAGE                          COMMAND                CREATED             STATUS                     PORTS               NAMES
2dc46197e3be        paintedfox/postgresql:latest   /scripts/start.sh /s   7 minutes ago       Exited (1) 2 minutes ago                       docker_default_1399814767  
$exit

既に処理を実行し、終了している事が確認できました。

Vagrantで経由でDockerの操作を行った際に何か困った事があれば、上記VMにSSHログインして調査すれば問題が解決しやすいかと思います。

コンテナの削除はvagrant destoryでvagrant global-statusで確認したidを指定すればOKです。 idは全て入力する必要はなく、一意に指定できれば良いので以下のようにしても動作が可能です。

$vagrant destroy 3

2.Dockerfileを指定する

以下のようにVagrantfileを作成します。

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure("2") do |config|
    v.vm.provider "docker" do |d|
        d.build_dir = "."
    end
end

上記の例では以下を設定しています。

  • 利用するProviderはdockerを指定
  • 利用するDockerifleはVagrantfileと同じディレクトリに配置

Dockerfileは先ほどと同じイメージを利用するようにしました。

FROM aintedfox/postgresql

これで先ほど同様にvagrant upすればOKです。

$vagrant up --provider=docker

1.Imageを指定するの手順を実行した後、上記を実行するとかなり早くコンテナの起動が出来るかと思います。

VM(boot2docker)の起動処理の時間とイメージをpullしてくる時間が省略された為です。

なお、VM(boot2docker)を削除すると、イメージを再度pullしてくる必要があるので必要です。

終わった後はコンテナを削除します。

$vagrant destroy 3

コンテナにSSH接続してみる

sshdのサービスを起動させるイメージを利用する事でVMと同じようにコンテナにもSSH接続が可能なようで試してみます。

以下のようなVagrantfileを用意します。

VAGRANTFILE_API_VERSION = "2" 

Vagrant.configure("2") do |config|
    config.vm.define "phusion" do |v| 
        v.vm.provider "docker" do |d| 
            d.cmd = ["/sbin/my_init", "--enable-insecure-key"]
            d.image = "phusion/baseimage:latest"
            d.has_ssh = true
        end 
        v.ssh.username = "root"
        v.ssh.private_key_path= "insecure_key"
        v.vm.provision "shell", inline: "echo hello"
    end 
end

上記の例では以下を設定しています。

  • 利用するProviderはdockerを指定
  • 利用するイメージはphusion/baseimageの最新(latest)
  • /sbin/my_initというコマンドを引数–enable-insecure-keyを指定して実行。
  • VagrantでSSHを利用する事を指定
  • SSHでログインするユーザーはroot
  • SSHでログインする際に利用する鍵はinsecure_key(詳細は後述)
  • コンテナの処理が完了したらhelloと出力する。

詳細は公式ドキュメントをご確認頂きたいのですが、本例では指定してるイメージがphusion/baseimageである事が大切です。

このイメージのドキュメントに詳細が書いてありますが、恐らく初期化処理の中でssdhのサービスを起動させる処理があり、これによってコンテナにも関わらず、SSH接続を可能にしているようです。

つまり全てのイメージでSSH接続が出来るという訳ではないのです

また、上記コンテナへのSSH接続は必ず指定された鍵を利用して認証を行う必要があります。そのため、以下のコマンドでVagrantfileと同じディレクトリに予めSSHで利用する鍵を配置しておく必要があります。

$curl -o insecure_key -fSL https://github.com/phusion/baseimage-docker/raw/master/image/insecure_key
$chmod 600 insecure_key

上記準備ができたら今まで同様に起動させます。

$vagrant up --provider=docker
・・・・
==> phusion: hello

正しく処理が完了した場合には、helloという出力がされる事も確認出来るかと思います。 ではコンテナにSSH接続してみます。

$vagrant ssh
==> phusion: SSH will be proxied through the Docker virtual machine since we're
==> phusion: not running Docker natively. This is just a notice, and not an error.
Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.8.0-35-generic x86_64)

 * Documentation:  https://help.ubuntu.com/
 root@cb4eb5281f86:~#

イメージのベースはUbuntu12.04であり、そのコンテナにVagrantを利用して簡単にSSH接続する事が出来ました!

確認後、コンテナは削除します。

$vagrant destroy 3

SSH接続してWebサーバー立ててみる

単純にSSH接続出来ただけだと意味が無いので、実際にローカルマシン(vagrantを動かしているマシン)からアクセス出来るようにしてみます。

上記については既にブログに記載している方がいらっしゃり、とても分かりやすく説明されています。

Vagrant1.6のDocker Provider

が、一応こちらでも記載します。(上記ブログの方の方が分かりやすいです!)

ローカルマシンからのアクセスを実現する為には、ローカルマシン→VM(boot2docker)→コンテナと接続しなければいけません。 つまり、ポートフォワードを2カ所(ローカルマシン→VM。VM→コンテナ。) で設定する必要があります。

VM→コンテナについては今まで編集してきたVagrantfileにポートフォワードの設定を記載すればOKです。

ローカルマシン→VM間のポートフォワードを指定する場合には、新しくVagrantfileを作成する必要があります。VM→コンテナ間のVagrantfileに以下のように追記を行います。

d.vagrant_vagrantfile = "host-vm/Vagrantfile"

指定した場所にVagrantfileを配置する必要があるのですが、デフォルトでVM(boot2docker)に適用されるVagrantfileがあるのでそれに追記を行います。

$mkdir host-vm && cd host-vm
$wget https://raw.githubusercontent.com/mitchellh/vagrant/master/plugins/providers/docker/hostmachine/Vagrantfile

配置したファイルにポートフォワードに関する追記を行うと以下のようになります。

Vagrant.configure("2") do |config|
  config.vm.box = "mitchellh/boot2docker"

  config.vm.provider "virtualbox" do |v|
    # On VirtualBox, we don't have guest additions or a functional vboxsf
    # in TinyCore Linux, so tell Vagrant that so it can be smarter.
    v.check_guest_additions = false
    v.functional_vboxsf     = false
  end

  ["vmware_fusion", "vmware_workstation"].each do |vmware|
    config.vm.provider vmware do |v|
      if v.respond_to?(:functional_hgfs=)
        v.functional_hgfs = false
      end
    end
  end

  # b2d doesn't support NFS
  config.nfs.functional = false
  config.vm.network :forwarded_port, guest: 8080, host: 8080
end

同じようにVM→コンテナ間のVagrantfileにもポートフォワードに関する追記を行います。最終的には以下のようになります。

VAGRANTFILE_API_VERSION = "2" 

Vagrant.configure("2") do |config|
    config.vm.define "phusion" do |v| 
        v.vm.provider "docker" do |d| 
           d.vagrant_vagrantfile = "host-vm/Vagrantfile"
                d.cmd = ["/sbin/my_init", "--enable-insecure-key"]
                d.image = "phusion/baseimage:latest"
                d.has_ssh = true
        end 
        v.ssh.username = "root"
        v.ssh.private_key_path= "insecure_key"
        v.vm.provision "shell", inline: "echo hello"
        v.vm.network :forwarded_port, guest: 80, host: 8080
    end 
end

準備ができたので、順番に操作をしていきます。

まず、VM(boot2docker)を一度停止します。 Vagrantfileを明示的に指定すると別のVM(boot2docker)が起動するのですが、その際に既に起動しているものとポートがバッティングしてエラーとなる為です。恐らく回避方法もありそうな気がしますが。。。

$vagrant halt {vm_id}

次にVM(boot2docker)とコンテナを起動します。

$vagrant up --provider=docker

次にコンテナにSSH接続してnginxをインストールし、サービスを起動します。

$vagrant ssh
$apt-get update
$apt-get install -y nginx
$service nginx start
$exit

これで準備完了です。

ローカルマシンからブラウザでhttp://localhost:8080/にアクセスしてみます。

コンテナのnginxのWebページを表示する事が出来ました。

最後に

実際に動いているのはコンテナでもVagrantを利用する事でさもVMを利用しているかのように操作を出来るこの機能はとても素晴らしいと思います。

Dockerにも任意のprovisonが適応できるようなので、Chefとか流したりもきっと出来そうな。今度時間があればやってみたい。。。

0 件のコメント:

コメントを投稿