GitHubにあるRailsアプリをVSTSでビルドして、Azureにデプロイする with Docker

11/15に社内の人とハッカソン練習会をした。 Railsで作ったアプリを、VSTSでビルドして、AzureとDockerを使って動かすのに挑戦...したんだけど、上手くいかなかった。 ので、日を改めてチャレンジした記録。

目標

考えていること

  • 以下を自動化したい。
    • Dockerイメージのビルド
    • プライベートレジストリへのPush
    • デモ用サーバへのデプロイ
  • Docker Machine使いたい
    • Docker Machineでプライベートレジストリや、デモ用サーバを作りたい。(楽だったから)

ビルドエージェントの構築

VSTSからビルドエージェント上でDockerコマンドを実行できるようにする。

VSTSプロジェクトの作成

Azure Portal にアクセス

新規 -> 開発者向けサービス -> Team Project から作成。 いろいろ聞かれるので適当に入れる。

VSTSプロジェクトの設定変更

ユーザとパスワードを使ってVSTSに接続できるようにする。

Alternate authentication credentials を有効にする

  1. VSTSにアクセス
  2. 鍵マーク -> Settings をクリック
  3. Application Connections にある Alternate authentication credentials を Allow に変更

認証するユーザと、パスワードを指定する

  1. 名前 -> My Profile
  2. Security -> Alternate authentication credentials をクリック
  3. Enable alternate authentication credentials をチェック
  4. Password, Confirm Password を入力して、Save をクリック

Passwordは以下の条件を満たす必要がある。

Passwords must be between 8 and 32 characters long, and must include 3 or more of the following: numbers, uppercase letters, lowercase letters, and special symbols.

ちなみに Alternate authentication credentials を使うと、VSTSからツッコミがある。

Personal access tokens are a more convenient and secure replacement for Alternate authentication credentials. Please use personal access tokens instead.

ので、Personal access tokenを使いたいんだけど、後回しにする。

Agent Poolの作成

  1. VSTSにアクセス
  2. 鍵マーク -> Settings をクリック
  3. Agent pool -> New pool をクリック

名前を入れて、OKをクリックする。

プロジェクトの作成

  1. VSTSにアクセス
  2. Recent Projects & Terms にある New をクリック
  3. パラメータ設定して、Create project をクリック

ビルドエージェント用サーバの作成

VMの作成

AzureからUbuntu Server 14.04 LTSでVMを作成する。

  1. 参照 -> 仮想マシン -> 追加をクリック

ビルドが早くなるかもということで、Standard_D1にした。

適当にパラメータを設定。

ランゲージパックの更新

ログインするとやれと言われたので。

sudo apt-get -y install language-pack-ja

Dockerのインストール

http://docs.docker.com/engine/installation/ubuntulinux/ を見ながらインストール。 sudo 必要ないようにdockerグループにユーザを追加する。

sudo usermod -aG docker [ユーザ名]

VSTS Agentのインストール

Node.jsのインストール

nvmでインストールするので、まずはnvmのインストール。 https://github.com/creationix/nvm を見ながら。

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
source ~/.bashrc

バージョンを指定してインストール。

nvm install v4.2.3

azure-cliのインストール

npm install -g azure-cli

azure-cliでAzureにログインする

azure login

標準出力に出てくるガイドに沿ってログインプロセスを進める。 サブスクリプションが適用されているかどうか確認する。

azure account list

利用したいサブスクリプションがカレントではない場合は、以下のコマンドでカレントにする。

azure account set [サブスクリプションID]

VSTS Agentのインストール

https://github.com/Microsoft/vso-agent を見ながら。

npm install vsoagent-installer -g
mkdir myagent; cd myagent
vsoagent-installer

VSTS Agentの起動

node agent/vsoagent

ユーザ名、パスワードを聞かれるので、上の方で設定したユーザ名とパスワードを入力する。 パラメータを幾つか聞かれるので入力。 無事接続すると、以下のようなメッセージが表示される。(最後にAgent Started.が出れば多分OK)

...
...
2015-12-11T15:45:09.233Z: Agent Started.

VSTSのAgent Poolでビルドエージェントが起動していることを確認する。

動作確認

テスト用ビルド定義を作成、Dockerが動作するかどうか確認する。

テスト用スクリプトの作成

ビルド定義からはバイナリファイルを直接呼び出すことができない。 ので、ビルドエージェントに以下の内容のシェルスクリプトを用意する。 (test.shとした)

docker run hello-world

vsoagentを再起動(ログインからやり直し)しないと、以下のようなエラーが出るかも。

2015-12-11T16:11:06.376Z: Cannot connect to the Docker daemon. Is the docker daemon running on this host?

テスト用ビルド定義の作成

  1. プロジェクトにアクセス
  2. BUILD -> "+" をクリック
  3. Empty を選択して、Next をクリック
  4. Create をクリック

ビルドができたので、ステップを追加する。

  1. Add Build Step をクリック
  2. Utility -> Shell script -> Add をクリック
  3. Close をクリック
  4. Script path にテスト用スクリプトのパスを入力して Save をクリック
  5. 名前を聞かれるので、適当に名前をつけて保存

実行するビルドエージェントを変更する。 さっき作ったビルド定義を開いていると思うので、以下の手順を流す。

  1. General -> Default agent queue をビルドエージェント名にする
  2. Save -> OK をクリックする

ビルドの実行

  1. プロジェクトにアクセス
  2. BUILD -> Build definition -> [ビルドの名前] をクリック
  3. 右ペインの queue build... をクリック
  4. OKをクリック

ビルドが成功して、以下のようなログが出力されたらOK。

レジストリ、デモ用サーバを作成する

Docker Machineを使ってサーバを作ってみる。

準備

Docker Machineのインストールと、証明書の作成。

Docker Machineのインストール

unzipないと怒られるので先に入れる。

sudo apt-get -y install unzip

後は https://docs.docker.com/machine/install-machine/ 見ながらインストール。

curl -L https://github.com/docker/machine/releases/download/v0.5.0/docker-machine_linux-amd64.zip >machine.zip && \
unzip machine.zip && \
rm machine.zip && \
sudo mv docker-machine* /usr/local/bin

一応、動作確認。

docker-machine --version

証明書の作成

AzureでDocker Machine使うのに必要。

mkdir ~/azure-cert; cd ~/azure-cert
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout azure.pem -out azure.pem

いろいろ聞かれるので、入力。

openssl pkcs12 -export -out azure.pfx -in azure.pem -name "Azure Certificate"
openssl x509 -inform pem -in azure.pem -outform der -out azure.cer
chmod 600 azure.pem

証明書の登録

  1. https://manage.windowsazure.com/ にアクセス。
  2. 設定 -> 管理証明書 をクリック
  3. アップロードをクリック
  4. azure.cer をアップロード

レジストリサーバの構築

サブスクリプションIDが必要なので確認。

azure account list

docker-machineでサーバを作る。

docker-machine create -d azure \
--azure-subscription-id "[サブスクリプションID]" \
--azure-subscription-cert "[azure.pemのパス]" \
--azure-location 'Japan West' \
--azure-username '[ユーザ名]'  \
--azure-password '[パスワード]' \
--azure-ssh-port 10022 \
--azure-size 'Small' \
--azure-docker-port 52376 \
[レジストリサーバ名]

エンドポイントを設定。

azure vm endpoint create \
--name docker-registry \
[レジストリサーバ名] \
5000 \
5000

デモサーバの構築

レジストリサーバの構築と同じ手順で、サーバを作成する。楽チンだ。 エンドポイントも設定。

azure vm endpoint create \
--name rails \
[デモサーバ名] \
3000 \
3000

動作確認

サーバの確認

docker-machine ls

レジストリサーバ

eval $(docker-machine env [レジストリサーバ名])
docker run -d -p 5000:5000 registry

リクエストを送ってみる。

curl http://[レジストリサーバ]:5000/v1/search

以下のような結果が返ってくればOK。

{"num_results": 0, "query": "", "results": []}

デモサーバ

GitHubRailsアプリをビルド、レジストリに登録、評価サーバへのデプロイまでやってみる。 ビルドには、Railsアプリ用のDockerイメージ rails:onbuild を使う。 rails:onbuildを使うと、任意のRailsアプリをDockerイメージにできる。

コード: https://github.com/agilecommunity/home_kpt

プライベートレジストリにhttpでアクセスさせる

httpでアクセスするようにビルドエージェント上のDockerサービスにinsecure-registryのオプションを指定する。 ビルドエージェントと、デモ用サーバで、/etc/default/dockerのDOCKER_OPTを変更し、サービスを再起動する。

/etc/default/dockerを変更する。

DOCKER_OPTS=--insecure-registry [レジストリサーバ]:5000

サービスを再起動する。

service docker restart

念のため、デモ用サーバでも実行するのを忘れないこと。(忘れててPullに失敗した...)

Dockerイメージのビルド

リポジトリをクローン。

git clone https://github.com/agilecommunity/home_kpt.git

直下のディレクトリにDockerfileを作成。

FROM rails:onbuild

ビルド。

cd home_kpt
docker build -t ajako/home_kpt .

Dockerイメージの動作確認

Railsが上がればOKとする。

docker run -it --rm ajako/home_kpt

プライベートレジストリに登録

プライベートレジストリに登録するので、タグつける。

docker build -t [レジストリサーバ]:5000/ajako/home_kpt

レジストリに登録

docker push [レジストリサーバ]:5000/ajako/home_kpt

レジストリの内容を確認。

curl http://[レジストリサーバ]:5000/v1/search

レジストリにイメージが登録されていたら、以下のような結果が返ってくる。

{"num_results": 1, "query": "", "results": [{"description": "", "name": "ajako/home_kpt"}]}

デモ用サーバにデプロイ

Railsが動けばOKとする。

eval $(docker-machine env [デモ用サーバ名])
docker run -it --rm [レジストリサーバ]:5000/ajako/home_kpt

VSTSからビルド、デプロイを実行

シェルスクリプトの作成

ビルドと、デプロイで分ける。 ビルド用。カレントディレクトリでビルドをする想定。

docker build -t [レジストリサーバ]:5000/ajako/home_kpt .
docker push [レジストリサーバ]:5000/ajako/home_kpt

デプロイ用。Docker Composeで実行する。

eval $(docker-machine env [デモ用サーバ])
docker stop ajako_home_kpt
docker rm ajako_home_kpt
docker run -d -p 3000:3000 [レジストリサーバ]:5000/ajako/home_kpt --name ajako_home_kpt

初回失敗するのだよなぁ。これだと。

ビルド定義の作成

外部サービスの登録

GitHubにアクセスするために外部サービスの登録をする。

GitHub personal access tokenの作成

  1. GitHubにログイン
  2. 自分のアイコン -> Settingsをクリック
  3. Personal access tokens -> Generate access tokenをクリック
  4. 名前と、scopeを指定し、Generate tokenをクリック VSTSによると repo, user, admin:repo_hook がいいらしい

access tokensの画面にアクセストークンが表示されてると思うので、それをメモ。

コネクションの作成

  1. プロジェクトを表示
  2. 鍵マーク -> Services をクリック
  3. New Service Endpoint -> GitHub をクリック
  4. RepositoryタグでRepository typeにGitHubを指定
  5. ConnectionのところのManageをクリック
  6. New Service Endpoint -> GitHubを選択
  7. 名前と、Personal access token -> トークンを指定してOKをクリック

ビルド定義の作成

新しいビルド定義をEmptyテンプレートで作成する。

リポジトリの指定

  1. Repository をクリック
  2. Repository typeを、GitHubにする
  3. Connectionで、作成したコネクションを選択
  4. Repositoryに選択できるリポジトリが表示されるので、対象のリポジトリを選択

ステップと、エージェントプールの指定

  1. Buildで、上記で作ったビルドとデプロイのシェルスクリプトをそれぞれ指定する。
  2. Generalで、Default agent queueにUbuntuを指定する

Saveで、保存。

動作確認

ブラウザからアクセスして、画面が出たらOK。 なんだけど、実はこのアプリ、DBにPostgreSQL使ってるので、エラー画面が出るのだなぁ...orz まぁ、なんとかDockerイメージ作って、レジストリにPush、デプロイまではできたということで、ここまでに...いや、やろう。

デモサーバでPostgreSQLを実行して、Railsアプリと連携させる

Docker Composeでやるのが面倒なくていいので、そっちでやる。

ビルドエージェントにDocker Composeをインストールする

https://docs.docker.com/engine/installation/ubuntulinux/ を見ながら。 rootで以下を実行

curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

動作確認

docker-compose --version

データベースの起動と初期化

設定ファイルの作成

以下の内容で docker-compose.yml を作成する。 説明はごめんなさい。はしょります。 Rails環境変数 DATABASE_URLを指定すると、設定ファイルを無視して、環境変数の内容で接続してくれるらしい。ありがたい。

DBは永続化するデータをDockerホスト側に出した。

web:
  image:[レジストリサーバ]:5000/ajako/home_kpt
  ports:
    - "3000:3000"
  links:
    - db
  environment:
    - DATABASE_URL=postgresql://[DBユーザ]:[DBパスワード]@db/home_kpt_db
db:
  image: postgres:9.4
  environment:
    - POSTGRES_PASSWORD=[postgresのパスワード]
  volumes:
    - [デモサーバのどこか]/home_kpt_db:/var/lib/postgresql/data

起動確認

docker-compose.ymlのあるディレクトリで以下を実行。

docker-compose up

ブラウザからアクセスすると、DBに接続しようとしてエラー。ユーザ作ってないからね。

DBユーザとデータベースの作成

コンテナの中に入ってDBユーザと、データベースを作成する。 docker ps で名前確認して、以下のコマンドでシェルを実行。

docker exec -it [名前] /bin/bash

DBを初期化する

su - postgres
cd /usr/lib/postgresql/9.4/bin
./createuser -P [DBユーザ名]

パスワード聞かれるので入れよう。 オーナーを指定してDBを作成。

./createdb -O home_kpt home_kpt_db

次にあるマイグレーションのように docker-compose で実行できればいいのに...。

マイグレーション

ビルドエージェントから実行。

docker-compose run web rake db:migrate    

デプロイスクリプトの修正

eval $(docker-machine env ajakohackathonDockerDemo)
cd [docker-compose.ymlのある場所]
docker-compose pull web
docker-compose up -d web

動作確認

無事画面が出た!!!

ということで、GitHubRailsアプリをVSTSを使ってDockerイメージにして、Azureにデプロイするまでが完了。 長かったなぁ。

今後やりたいこと

  • エージェントをサービス化する
  • Personal access tokenを使ってビルドエージェントを接続する
  • Docker Machineでリソースグループを指定してVMを作る方法を調べて見る
    • Docker Machineで作ると、クラッシックタイプになるので、そこも変えたい
  • そもそもこの手順が長いので、もっと楽にできる方法はないのか探してみたい