boot2dockerで各言語の実行環境作成


ここ最近、go, python, nodeと用途によって様々な言語で開発することが多くなったので、VM上に実行環境を作成することにする。

VirtualBoxにboot2docker(core Linux)を構築し、以下の実行環境を構築
  ・go lang
  ・node.js(python)

【用意した環境 】
・VirtualBox
・Vagrant v1.7.1

VMware Fusionも持ってるのでそちらでも確認したかったのでですが、
ライセンスが必要なので、今回はパス。
　参考　：　https://www.vagrantup.com/vmware
　　　　　　$79 (≒9,384 yen) ちょと高い...
## Vagrant のインストール

<a href="http://www.vagrantup.com/" target="_blank">公式サイト</a>から、dmgをダウンロードしてインストール。


## VirtualBoxのインストール

<a href="https://www.virtualbox.org/wiki/Downloads" target="_blank">公式サイト</a>から、OS X用のdmgをダウンロードしてインストール。


## boot2dockerの準備

```bash
$ mkdir -p /Users/<USER NAME>/Documents/Vagrant/boot2docker
$ cd /Users/<USER NAME>/Documents/Vagrant/boot2docker

# boot2dockerの起動
$ vagrant init mitchellh/boot2docker
```
###boot2dockerのISOイメージを作成する場合
(ISOが不要な場合は起動へ)

<a href="https://www.packer.io/downloads.html">ここ</a>からPackerをインストール

インストール後にターミナルから以下を実行

```bash

$ cd /Users/<USER NAME>/Documents/Vagrant
$ git clone https://github.com/mitchellh/boot2docker-vagrant-box.git
$ cd boot2docker-vagrant-box.git
$ vagrant up
$ vagrant ssh -c 'cd /vagrant && sudo ./build-iso.sh'
$ vagrant destroy --force
$ packer build -only=virtualbox-iso template.json
```
上記を実行すると
 ・b2d.iso
 ・boot2docker_virtualbox.box
 ・boot2docker_virtualbox.iso
が作成されます。

------

### boot2dockerの起動

ポートフォワードを設定する

``` bash

$vi Vagrantfile

　：　省略
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080

# Add port forwarding
config.vm.network "forwarded_port", guest: 80, host: 8080

# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
　：　省略
```

boot2dockerを起動

```bash
$ vagrant up
$ vagrant ssh
````

![スクリーンショット 2014-12-13 22.11.15.png](https://qiita-image-store.s3.amazonaws.com/0/52867/8069ec82-84fc-1c7a-b62f-00dc1a07db3f.png)





## boot2dockerのデータ永続化

次にboot2dockerで作成したデータの永続化を行う。

boot2docker上で以下のコマンドを実行

```bash
$ sudo su -
# cat > /var/lib/boot2docker/bootlocal.sh <<EOF
> echo "tar cf /var/lib/boot2docker/userdata.tar . -C /home/docker/" >> /opt/shutdown.sh
> EOF
# chmod +x /var/lib/boot2docker/bootlocal.sh
# sudo reboot
```
 
※これでrebootやshutdownの時に/home/docker/が/var/lib/boot2docker/userdata.tarに
　バックアップされる。 

【確認】
Macからssh 

```bash
$ vagrant ssh
# pssword : tcuser
```

```bash
# boot2dockerでの作業
$ touch test
$ ls -l 
  -rw-r--r--    1 docker   staff            0 Dec 13 13:22 test
$ sudo reboot
```

Macから再びssh 

```bash
$ vagrant ssh
# pssword : tcuser
```

boot2docker

```bash
$ ls -l 
   -rw-r--r--    1 docker   staff            0 Dec 13 13:22 test
# 存在していることを確認
```

## dockerイメージを作成(Golang)

せっかくなので、Dockerfileからイメージを作成
 ※ docker pull dockerfile/go でもOK

go lang
-------------

```bash
$ mkdir golang
$ cd golang
$ vi Dockerfile

#
# Go Dockerfile
#
# https://github.com/dockerfile/go
#
  
# Pull base image.
FROM dockerfile/ubuntu
  
# Install Go
RUN \
  mkdir -p /goroot && \
  curl https://storage.googleapis.com/golang/go1.3.1.linux-amd64.tar.gz | tar xvzf - -C /goroot --strip-components=1
  
# Set environment variables.
ENV GOROOT /goroot
ENV GOPATH /gopath
ENV PATH $GOROOT/bin:$GOPATH/bin:$PATH
  
# Define working directory.
WORKDIR /gopath
  
# Define default command.
CMD ["bash"]
```

docker imageの作成

```bash
$ docker build -t ubuntu/golang .
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu/golang       latest              ff635337559a        3 minutes ago       614 MB
dockerfile/ubuntu   latest              c8f87bf54eb2        8 days ago          414.6 MB
```

docker上のgoでHelloWorldをやってみる。

```bash

$ docker run -i -p 80:80 -t ubuntu/golang /bin/bash

$ go version
go version go1.3.1 linux/amd64

$ vi testserver.go

package main

import (
  "fmt"
  "net/http"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello Go lang")
}

func main() {
  http.HandleFunc("/", indexHandler)
  http.ListenAndServe(":80", nil)
}


# テストなのでコンパイルなしで実施
$ go run testserver.go

```

Macからブラウザでアクセスして実行の確認

![スクリーンショット 2014-12-14 0.10.18.png](https://qiita-image-store.s3.amazonaws.com/0/52867/ebb90c41-1382-ec04-3eaf-1114b6151400.png)

-----

## dockerイメージを作成(nodejs, python)

python 環境はnodejsのベースになっているのでNodejs環境のみ作成

```bash
$ mkdir ~/nodejs
$ cd ~/nodejs
$ vi Dockerfile


#
# Node.js Dockerfile
#
# https://github.com/dockerfile/nodejs
#

# Pull base image.
FROM dockerfile/python

# Install Node.js
RUN \
  cd /tmp && \
  wget http://nodejs.org/dist/node-latest.tar.gz && \
  tar xvzf node-latest.tar.gz && \
  rm -f node-latest.tar.gz && \
  cd node-v* && \
  ./configure && \
  CXX="g++ -Wno-unused-local-typedefs" make && \
  CXX="g++ -Wno-unused-local-typedefs" make install && \
  cd /tmp && \
  rm -rf /tmp/node-v* && \
  npm install -g npm && \
  echo -e '\n# Node.js\nexport PATH="node_modules/.bin:$PATH"' >> /root/.bashrc

# Define working directory.
WORKDIR /data

# Define default command.
CMD ["bash"]

```

docker imageの作成

```bash

$ docker build -t ubuntu/nodejs .
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu/nodejs       latest              60d7f5969d7a        30 seconds ago      496.6 MB
ubuntu/golang       latest              42a919d3c0ea        23 minutes ago      614 MB
dockerfile/python   latest              f08c82e36872        8 days ago          471 MB
dockerfile/ubuntu   latest              c8f87bf54eb2        8 days ago          414.6 MB

$ docker run -i -p 80:80 -t ubuntu/nodejs /bin/bash

$ npm version
{ http_parser: '1.0',
  node: '0.10.33',
  v8: '3.14.5.9',
  ares: '1.9.0-DEV',
  uv: '0.10.29',
  zlib: '1.2.3',
  modules: '11',
  openssl: '1.0.1j',
  npm: '2.1.12' }

# serverの作成
$ vi app.js
var http = require('http');

var server = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World node.js');
});
server.listen(80);

```

![スクリーンショット 2014-12-14 0.27.25.png](https://qiita-image-store.s3.amazonaws.com/0/52867/53dffa9b-2eab-5b6f-72c5-0c76fc95622a.png)


同じ環境でpythonもテスト

```bash 
# ubuntu/nodejsで実行

$ python --version
Python 2.7.6

$ vi index.html
<html>
<body>
    Hello Python
</body>
</html>

$ python -m SimpleHTTPServer 80

```
![スクリーンショット 2014-12-14 0.25.21.png](https://qiita-image-store.s3.amazonaws.com/0/52867/e3e4d1ef-2e87-a7b4-1317-3a25fbf18084.png)


----

## docker 不要コンテナの削除
dockerでは起動後の差分ファイルを保持しているので不要になったら削除する。

```bash
$ docker ps -a
CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                      PORTS               NAMES
8675a8897319        ubuntu/nodejs:latest   "/bin/bash"         8 seconds ago       Exited (0) 7 seconds ago                        hungry_carson       
f71e1d22b5e6        ubuntu/golang:latest   "/bin/bash"         56 seconds ago      Exited (0) 54 seconds ago                       prickly_shockley    

#不要コンテナのIDを指定
$ docker rm 8675a8897319 f71e1d22b5e6


# イメージを削除する場合
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu/nodejs       latest              60d7f5969d7a        About an hour ago   496.6 MB
ubuntu/golang       latest              42a919d3c0ea        About an hour ago   614 MB
dockerfile/python   latest              f08c82e36872        8 days ago          471 MB
dockerfile/ubuntu   latest              c8f87bf54eb2        8 days ago          414.6 MB

$ docker rmi < IMAGE ID >

```


コンテナやイメージを一括で削除する場合

```bash
# remove container
$ docker rm `docker ps -a -q`

# remove images
$ docker rmi $(docker images | awk '/^<none>/ { print $3 }')
```

マルチロケーション開発やアジャイル開発する際にはGitHubでソース管理して
Dockerfileで環境管理すればモビリティに適した開発ができます。

そろそろ、Macが限界なのでboot2dockerはベアメタルで構築したいと思います。