2014年6月24日火曜日

[AWS]EC2及びローカル環境からRDSのMySQLに接続した時のメモ

このエントリーをはてなブックマークに追加 はてなブックマーク - [AWS]EC2及びローカル環境からRDSのMySQLに接続した時のメモ

EC2及びローカル環境からRDSのMySQLに接続した時のメモ なお、予めEC2は起動済みでSSH接続出来る事が前提。

EC2からRDSへの接続

RDSを以下の内容で作成する。

  • Public AccessibleはNOにする
  • EC2と同じSecurityGroupを設定する。

RDS作成後、以下の情報をメモしておく。

  1. エンドポイント(例:dbtest.hogefuga.ap-northeast–1.rds.amazonaws.comなど)
  2. ポート(例:3306)
  3. DBユーザー名(例:dbuser)
  4. DBパスワード

次に設定したSecurityGroupのInboundを確認する。 もし、DBのポート(上記の場合3306)の設定がされていない場合、以下のように同じSecurityGroup間の3306ポートの接続は可能なように設定する。

設定後、EC2にSSH接続し、以下のようなコマンドを実行。

$mysql -h dbtest.hogefuga.ap-northeast-1.rds.amazonaws.com -P 3306 -u dbuser -p

パスワードが聞かれるので入力すればRDSのmysqlへの接続が出来る。

ローカルマシンからRDSへの接続

  • Public AccessibleはYESにする
  • SecurityGroupの設定でRDSに割り当てているもののInboundにアクセス元のローカルのグローバルIPとDBのポートによる接続許可のルールを追加する。(自分は確認の為にアクセス元を0.0.0.0/0にしましたが、セキュリティ的に通常設定すべきではありません)

ローカルマシンからEC2と同様にmysqlコマンドで接続が可能である。

2014年6月10日火曜日

svnコマンドで証明書を無視する

このエントリーをはてなブックマークに追加 はてなブックマーク - svnコマンドで証明書を無視する

svn exportとかした時にこの証明書信用していいんですか、みたいなのが出て落とせない。

(R)eject, accept (t)emporarily or accept (p)ermanently? 

みたいな感じで。

普通にコマンドを打っている場合にはキーボードから入力すれば良い訳ですが、Chefとか使っている場合だと自動化したいのでどうしようかな、と思ったのですが、オプションを指定したら無視出来ました。

svn  checkout https://hogefuga --non-interactive --trust-server-cert --username "hoge" --password "fuga"

expectコマンドとかyesコマンドとか使うのも手かもしれませんが、こちらの方が楽。

[Chef]expectコマンドを使ってAndroidSDKをインストールするレシピを作成してみた

このエントリーをはてなブックマークに追加 はてなブックマーク - [Chef]expectコマンドを使ってAndroidSDKをインストールするレシピを作成してみた

Chefを利用してAndroidSDK本体のインストール及び特定AndroidSDKインストールを自動化させたいと思っていました。

が、指定したAndroidSDKのインストールの途中で利用許諾の承認が必要であり、単純にexecuteコマンドを利用してインストールが出来ませんでした。

調査するとexpectコマンドを使うと対話形式の入力が必要な処理を自動化出来るとのことで実際に実施する事が出来たいのでそのメモを記載します。

そもそもexpectコマンドとは?

  • telnetやsshなどパスワード入力を求められるような処理を自動化出来る
  • 同様にインストール時に許諾への同意などが必要なものも自動化させる事が出来る

前提

  • Chef、Berkshelfなどはインストール済み
  • ホストはMac OSX 10.9.3
  • test-kitchenを利用。ドライバはvagrantを利用。

Chefやtest-kitchenの詳細は過去のブログを参考の事。

Berkshelf version3+Knife soloでnginx環境をVagrantに作ってみた話

[Chef]Berkshelfを利用したJenkinsクックブックを作成してserverspec+Kitchenでテストした話

参考

こちらのクックブックを参考にさせて頂きました。

gildegoma/chef-android-sdk

Github

置きました。

toshihirock/AndroidSDK

  • Ubuntuのテストはしてません
  • URLやAndroidSDKのバージョンは適宜変更してください。(そのうちattribute化したい。。。)

準備

クックブック作成します。

$knife cookbook create android -o .

AndroidSDKを利用する為にJavaのインストールが必要ですが、サードパーティのクックブックを利用 します。 また、AndroidSDKのダウンロード、展開の為にopscodeのarkというクックブックを利用します。

サードパーティのクックブックを使う為にBerksheflを利用する準備をします。

$berks init .

利用するためにmetadata.rbに追記を行います。

$cd android
$vi metadata.rb

name             'android'
maintainer       'YOUR_COMPANY_NAME'
maintainer_email 'YOUR_EMAIL'
license          'All rights reserved'
description      'Installs/Configures android'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          '0.1.0'

depends "ark"
depends "java"

また、test-kitchenを使ってプロビジョニングを行うのでその為のファイルを作成します。

$kitchen init

既にBerkshlefで.kitchen.ymlが作成済みの場合にはコンフリクトしますが、yを入力して鵣川書きします。

今回、試験ははCentOSのみに今回はするため、.kitchen.ymlの一部をコメントアウトします。

$vi .kitchen.yml

編集。

platforms:
  #- name: ubuntu-12.04
  - name: centos-6.4

AndroidSDK本体のダウンロード、展開

まずはAndroidSDK本体のダウンロード、展開までのレシピを書きます。 本来はURLやパスはattributesの値とすべきですが、とりあえずベタ書きします。

$vi recipes/default.rb

編集。

include_recipe 'java'

%w{unzip expect}.each do |pkg|
  package pkg do
    action :install
  end
end

ark 'android' do
  url 'http://dl.google.com/android/adt/22.6.2/adt-bundle-linux-x86_64-20140321.zip'
  path '/usr/local/android'
end

URLはAndroidのサイトをみて確認してください。(ビット数に応じてダウンロードするzipが違いますが、今回は判定処理は割愛して64bitで確認)

試験環境の準備

VMの起動。

$kitchen create

VMにChefやBerkshelfのインストール、及びレシピの適用を行います。

$kitchen setup

状態を確認します。

$kitchne list

SSH接続して確認してみます。

$kitchen login
$ll /usr/local
lrwxrwxrwx. 1 root root   20 Jun  9 14:30 android -> /usr/local/android-1

expectコマンドを使ってみる

Chefのコードを書く前に正しく動作出来るかVMでコマンドを実行して確認してみます。

$kitchen login
$sudo su
$cd /usr/local/android/sdk/tools
$vi expectTest.sh

確認用のシェルスクリプトを編集します。

#!/bin/bash

expect -c '

spawn /usr/local/android/sdk/tools/android update sdk --no-ui --filter android-17
set timeout 1800
expect {
  -regexp "Do you accept the license.*" {
    exp_send "y\r"
    exp_continue
  }
}
'

ざっくり説明します。

  • spawn:実際に実行させたいコマンド
  • set timeout:expectの実行を許容する時間。短すぎるとコマンドの途中で強制終了してしまう。
  • regrexp:どの文字列が表示されたら入力を自動的に行うかの正規表現。今回の場合、利用規約のDo you accept …という文字列が表示された時に入力を行う事を示す。
  • exp_send:regrexpで合致する文字列が表示された時に自動入力する文字列。
  • exp_continue:これを指定しないと自動入力したあと復帰出来ないっぽいです。

実行権限を付与して、実行してみます。

$chmod a+x expectTest.sh
$./expectTest.sh

Chefのレシピでexpectコマンドを実行する

成功すればこれをChefのレシピに落とし込みます。

$exit
$vi recipes/default.rb

レシピに追記します。

script 'Install Android SDK' do
  android_version="android-17"
  interpreter 'expect'
  not_if { ::File.exists?("/usr/local/android/sdk/#{android_version}") }
  code <<-EOF
    spawn /usr/local/android/sdk/tools/android update sdk --no-ui --filter #{android_version}
    set timeout 1800
    expect {
      -regexp "Do you accept the license.*" {
        exp_send "y\r"
        exp_continue
      }
    }
  EOF
end

テストも書きます。今回はserverspecを利用します。 Gemfileに追加します。

$echo "gem \'serverspec\'" >> Gemfile

$mkdir -p test/integration/default/serverspec/localhost/
$vi test/integration/default/serverspec/localhost/default_spec.rb

テストを書きます。

require 'serverspec'
include Serverspec::Helper::Exec
include Serverspec::Helper::DetectOS

describe command('which java') do
  it { should return_exit_status 0 }
end

describe command('ls /usr/local/android/sdk/platforms/android-17') do
  it { should return_exit_status 0 }
end

色々実験したので一度、VM環境を削除します。

$kitchen destroy

その後、VMの作成、Chefの適用、serverspecのテストを実施します。

$kitchen test

問題なく完了すればOKです。

2014年6月7日土曜日

Shell勉強会bashの話のみメモ

このエントリーをはてなブックマークに追加 はてなブックマーク - Shell勉強会bashの話のみメモ

Shell勉強会の私的メモ。 bashの話のみ抜き出し。

参考

nanapi 勉強会 vol2-shell勉強会

シェル苦手な人に、今日から始めて欲しい3つの考え方

基本

  • Ctrl+b 1文字戻る
  • Ctrl+f 1文字進む
  • Ctrl+a 先頭に移動
  • Ctrl+e 末尾に移動
  • Ctrl+d カーソル位置の1文字削除
  • Ctrl+h カーソル位置の1文字削除してカーソルが一つ前に進む
  • Ctrl+k 後ろを全部消す
  • Ctrl+u 全部消す
  • Ctrl+r 後方インクリメンタル検索
  • Ctrl+s 全方インクリメンタル検索

コピペとか

  • tmux
  • screen

ワンライナーでシェルスクリプト

  • わざわざシェルスクリプト書かなくても;を使えばコマンドラインで動作が可能
  • $for i in {1..10};do;echo ${i};done # 1 2 3 … 10
  • forコマンドがマジで使える
  • ブレース展開便利
  • $echo {1..10} # 1 2 3 ..10
  • $echo {10..1} # 10 9 8 ..1
  • $echo b{ed,ird} #bed bird
  • for i in $(ls); do; mv $i{,.bak}; done #カレントディレクトリのファイルを.bakに変更
  • seqコマンドでインクリメント数を指定する事も出来る
  • $echo $(seq 1 2 10) #1 3 5 7 9
  • seqコマンドでゼロ埋めも出来る
  • seq -w 0 0.5 1 #0.0 0.5 1.0

2014年6月5日木曜日

[chef]test-kitchenのテストをAWSのEC2で実施する

このエントリーをはてなブックマークに追加 はてなブックマーク - [chef]test-kitchenのテストをAWSのEC2で実施する

前回のブログでJenkinsのレシピを作成し、Vagrantを利用してローカル環境のVMでtest-kitchenを利用してserverspecのテストを実行するようにしました。

今回、kitchen-ec2を使ってその環境をローカルでなく、AWSのEC2を利用してテストするようにします。

参考

Chefのテストツール kitchen-ec2を使う – 導入、チュートリアル

test-kitchen/kitchen-ec2

前提

  • AWSのアカウントがあること
  • AWS のアクセスキー/シークレットアクセスキーが存在すること。
  • EC2のキーペアを作成済みである事
  • VagrantやChefなどがインストール済みである事

環境の準備

必要なものをインストールします。

$gem install test-kitchen
$gem install kitchen-ec2

対象レシピのディレクトリに移動し、.kitchen.ymlを変更します。 既に.kitchen.ymlが存在する場合には上書きするかの確認が表示されますが、必要に応じてバックアップを取得しておいてください。

$cd {repo_dir}
$kitchen init --driver=kitchen-ec2

.kitchen.ymlの編集

.kitchen.ymlを編集します。

---
driver:
  name: ec2
  aws_access_key_id: <%= ENV['AWS_ACCESS_KEY'] %>
  aws_secret_access_key: <%= ENV['AWS_SECRET_KEY'] %>
  aws_ssh_key_id: <%= ENV['AWS_SSH_KEY_ID'] %>
  ssh_key: <%= ENV['SSH_KEY'] %>
  security_group_ids: ["Vagrant"]
  region: ap-northeast-1
  availability_zone: ap-northeast-1a
  require_chef_omnibus: true

provisioner:
  name: chef_solo

platforms:
  - name: ubuntu-12.04
    driver:
      image_id: ami-0596ef04
      username: ubuntu
      flavor_id: t1.micro
  - name: centos-6.4
    driver:
      image_id: ami-99fa7098
      username: root
      flavor_id: t1.micro

suites:
  - name: default
    run_list:
      - recipe[jenkins::default]
    attributes:

ポイントだけ記載します。

  • aws_access_key_id:AWSのアクセスキー
  • aws_secret_access_key:AWSのシークレットアクセスキー
  • aws_ssh_key_id:キーペアの名称
  • ssh_key:キーペア(pem)のファイルパス
  • security_group_ids:設定するセキュリティグループ

詳細は test-kitchen/kitchen-ec2を確認ください。

上記のように環境変数から読み込む設定の場合、~/.bashrcなどに以下のように記載します。

export AWS_ACCESS_KEY="xxx"
export AWS_SECRET_KEY="xxxxxxxx" 
export AWS_SSH_KEY_ID="hogeKeyPair" 
export SSH_KEY="~/.ssh/hogeKeyPair.pem" 

image_idについては自分で作成したAMIでも大丈夫ですし、aws marketplaceのものも利用出来るようです。

aws marketplaceのものを利用する場合、利用承諾をしていないとインスタンス起動時にエラーとなります。その場合には、利用承諾用URLが表示されるのでリンクがエラー文に表示されるのでそこから利用承諾を行うと以降の起動が成功します。

テストの実行

テストの実行は以下のコマンドで可能です。

$kitchen test

上記で

  • インスタンスの作成
  • AWSへのChefのインストール、レシピの適用
  • テストの実行
  • インスタンスの削除

をplatformsに書かれたOSの数分実行されます。

それぞれを個別にやるには

  • kitchen create
  • kitchen coverage
  • kitche verify
  • kitchen destroy

というコマンドが対応しています。

インスタンスの各状態はkitchen listコマンドで確認が出来ます。

2014年5月23日金曜日

外部のbareリポジトリとオレオレGitlabを連携させてみる

このエントリーをはてなブックマークに追加 はてなブックマーク - 外部のbareリポジトリとオレオレGitlabを連携させてみる

オレオレGitlabを構築して、外部のbareリポジトリと連携してみたのでその時のメモ。 (メール機能については除外)

状況

  • 外部サーバーにGitのbareリポジトリがある
  • 外部サーバーにGitlab立てたいけど色々あって却下された
  • じゃあ社内ネットワークにGitlab立ててHookさせれば良いんじゃね?
  • VagrantでVM立ててそこにGitlab立てよう

完成イメージ

環境

  • ホストマシン:Mac OSX 10.9.3
  • VM:Ubuntu12.04(64bit)
  • Vagrant1.6.2
  • Gitlab 6.8.2

UbuntuのVMを起動する

Gitlabが簡単にインストール出来るOmnibusが利用出来るUbuntu12.04(64bit)のVMを立てます。

まずはVagrantfileを用意。大切な箇所だけ抜粋。

# ubuntu12.04 64bitのBOXを予めインストール
config.vm.box = "precise64"

# 80ポートへのフォワード設定
config.vm.network "forwarded_port", guest: 80, host: 1234

起動させます。

$vagrant up

GitLabのインストール

まずはsshアクセスします。

$vagrant ssh

GitlabをVMにインストールします。 取得するGitLabのOmnibusの最新版は こちらで確認し、各自変更してください。

$wget https://downloads-packages.s3.amazonaws.com/ubuntu-12.04/gitlab_6.8.2-omnibus-1_amd64.deb
$sudo dpkg -i gitlab_6.8.2-omnibus-1_amd64.deb
$sudo gitlab-ctl reconfigure

インストールが終わったか、確認します。

$wget http://localhost:8080/

外部からのアクセスする際のURLを設定します。

$sudo vi /etc/gitlab/gitlab.rb
external_url "http://localhost"
$sudo chmod 600 /etc/gitlab/gitlab.rb

再度設定をします。

$sudo gitlab-ctl reconfigure

本例の場合、ブラウザからhttp://localhost:1234/でアクセスします。 実際に会社などで利用する場合には自身のマシンに設定されているIPアドレスでも接続出来るはずです。なお、その場合、gitlab.rbのexternal_urlもマシンに降られているIPアドレスを記述する必要があります。

最初のログインはID「root」、パスワード「5iveL!fe」と入力します。

bareリポジトリをGitLabにも追加する

本例では確認他の為にGithubを利用します。 まず、Githubに適当なプロジェクトを作成します。

その後、該当のプロジェクトのgit cloneする時のURLをメモします。

GitlabのNew ProjectでImport existing repository?を選択し、先ほどコピーしたURLにユーザー名とパスワードを設定して指定します。(https://username:password@gitlab.com/company/project.git. など)

上記によってGitLabにbareリポジトリを作成されます。

bareリポジトリは/var/opt/gitlab/git-data/repositories/{namespace}/配下に配置されています。

git configコマンドで確認すると以下のようになっており、originはGithubとなっている事が確認出来ます。

$cd /var/opt/gitlab/git-data/repositories/root/helloworld.git
$git config -l
core.repositoryformatversion=0
core.filemode=true
core.bare=true
remote.origin.url=https://username:password@github.com/toshihirock/Hello-World.git

Gitabへのpush時に取得元のリポジトリにもpushするようにする

Gitlabへのpushタイミングで取得元にもpushする為にHookスクリプトを利用します。

こちらは以下のサイトを参考にさせてもらいました。

git hooks を利用したデプロイを導入しました

gitでbareリポジトリを同期する方法

まず、直接取得元へpushするユーザーが居る事もあると思うので、push時に取得元とGitLabとの間で同期を取るようにします。 この方法を実現する為に、pushの取り込み前に実行されるpre-receiveスクリプトを利用します。

$su git
$cd hooks
$touch pre-receive
$chmod +x pre-receive
$vi pre-receive

編集します。

#!/bin/bash
echo "start pre-receive"
git fetch origin 'refs/heads/*:refs/heads/*'
echo "end pre-receive"

これで取得元の差分があれば取り込む事が出来ます。

また、post-updateスクリプトを利用してGitlabへのpushが完了したタイミングで、取得元にもpushするようにします。 post-receiveスクリプトといのもあるのですが、こちらは複数のブランチへのpushの際にも一度しか呼ばれないので、今回の用途ではブランチ毎に呼び出されるpost-updateスクリプトを利用します。

$touch post-update
$chmod +x post-update
$vi post-update

編集します。

#!/bin/bash
echo "start post-update"
BRANCH=$(git rev-parse --symbolic --abbrev-ref $1)
git push origin ${BRANCH}
echo "end post-update"

上記のようにすると変数BRANCHにpushしたブランチ名が入るので、対象のブランチを取得元にpushすることができます。 先ほどgit configで見たようにGitlabに作成されたbareリポジトリのoriginは取得元(本例だとGithub)となっているので上記のようにすることで取得元へのpushが出来ます。

Gitlabからのクローンを確認

Gitlabからクローン出来るか確認してみます。 ユーザー名、パスワードは置き換えて下さい。

$git clone http://username:password@localhost:1234/root/helloworld.git

Githubからのクローンとpush先の変更

Githubから対象のリポジトリをcloneします。

$git clone http://username:password@github.com/hogefuga.git

git remoteコマンドを利用してoriginの向き先をGitlabに変更します。

$git clone Github url
$git remote set-url origin http://username:password@localhost:1234/root/helloworld.git

originの向き先がGitlabとなっている事を確認します。

$git config remote.origin.url 

pushしてみる

ではcloneしてきたリポジトリを編集してGitlabにpushし、その後、Githubに反映されているか確認します。

$vi README
$git add .
$git commit -m "Github"
$git push origin master
Hello-World [master] git push origin master
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 262 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: start pre-receive
remote: end pre-receive
remote: start post-update
remote: To https://username:password8@github.com/toshihirock/Hello-World.git
remote:    e9c6f5f..35d1433  master -> master
remote: end post-update
To http://username:password@localhost:1234/root/helloworld.git
   e9c6f5f..35d1433  master -> master

上記のようにHookスクリプトで標準出力される内容ははpush時に確認出来ます。(ユーザー名、パスワードは変更しています)

上記実施後、Githubでもpushしたコメントが反映されている事を確認できました。

また、上記の場合には取得元のパスワードがバレバレになるのでその場合にはpost-updateを以下に変更すれば出力がされないようになります。

git push origin ${BRANCH} >/dev/null 2>&1

本例ではhttpプロトコルで確認しましたが、sshプロトコルでも可能です。

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はMacやWindowsの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とか流したりもきっと出来そうな。今度時間があればやってみたい。。。