読者です 読者をやめる 読者になる 読者になる

ROMANCE DAWN for the new world

Microsoft Azure を中心とした技術情報を書いています。

Azure 上に Jenkins を使って CI 環境を構築する

Microsoft Azure Jenkins Docker

この記事は、Azure Advent Calendar 2016 の 25 日目 の記事です。
qiita.com
Azure 上に Jenkins を インストールして、継続的インテグレーション(CI)環境を構築してみました。
Jenkins のような CI ツールを使ってビルドやテストなどの作業を自動化する場合、オンプレミスにサーバーを用意してインストールするのは手間なので、Azure を使うと簡単に構築することができます。
ASP.NET のアプリケーションをビルドするシナリオを想定しているので、Jenkins をインストールする Linux の Master ノードのほかに、プラグインを使って MSBuild を実行できる Windows の Slave ノードも構築します。

Jenkins の Master Node を構築する

Azure ポータルで Jenkins を検索すると、Docker、Bitnami、CloudBees などいくつか種類がありますが、今回は Docker を使います。Ubuntu Server 16.04.0-LTS 上で動作するコンテナに Jenkins がインストールされた環境を構築できます。
コンピュータ名やユーザー名、そして SSH の公開鍵などを入力して作成します。仮想マシンのサイズやオプション設定は、初期値のままで進めます。

f:id:TonyTonyKun:20161224124058p:plain

作成が完了したら Public IP Address(52.185.154.89)を確認し、ポート番号:8080 にアクセスすると、Jenkins の管理者パスワードを入力する画面が表示されます。

f:id:TonyTonyKun:20161224124149p:plain

管理者パスワードを取得するには、画面に表示されているパスは Docker 内のパスなので、コンテナに接続する必要があります。MAC であればターミナルを使って、まずは Linux の仮想マシンに SSH接続します。

ssh -i ~/.ssh/id_rsa thara@52.185.154.89

次に、接続する Docker のコンテナ名を確認します。

docker ps

確認したコンテナ名(compose_crate_1)を指定して、管理者のパスワードを取得できます。

docker exec compose_crate_1 cat /var/jenkins_home/secrets/initialAdminPassword

次の画面では、プラグインをインストールします。推奨のプラグインで構わないので、初期値の Install suggested plugins を選択したまま、処理を進めます。

f:id:TonyTonyKun:20161224145232p:plain

プラグインのインストール完了後、初期ユーザーを作成して Save and Finish ボタンを押します。

f:id:TonyTonyKun:20161224145306p:plain

これで環境構築が完了です。Jenkins のダッシュボード画面が表示されます。

f:id:TonyTonyKun:20161224145347p:plain

Jenkins の Windows Slave Node を構築する

Jenkinsの管理 - プラグインの管理を選択して、Azure Slave Plugin をインストールします。インストールが完了したら、システムの設定で Azure のサブスクリプション ID などを設定します。

f:id:TonyTonyKun:20161224145454p:plain

Management Service Certificate は、こちらのリンクからダウンロードできる publish.setteing ファイルから取得できます。Verify Configuration ボタンで検証して、成功することを確認しておきます。

続いて、Add Azure Virtual Machine Template から、仮想マシンのテンプレートを追加します。仮想マシンの名前やサイズなどを指定します。Labels は、ジョブを特定のノードだけで実行させる際に指定するキーとなりますので、分かりやすい名前にしておきます。今回は、"Windows" を指定しました。

f:id:TonyTonyKun:20161224145647p:plain

次に、仮想マシンのイメージを指定します。今回は、Visual Studio 2015 が入った Windows Server 2012 R2 を選択しました。Windows の仮想マシンなので、Launch Method は "JNLP" を選択します。2つの警告が表示されている通り、別途対応が必要なので、ひとまず UserName と Password を入力して保存します。

f:id:TonyTonyKun:20161224145807p:plain

1つ目の警告には、Windows Slave Node から Master Node に通信できるようにポートを開放しておく旨が記載されています。

Make sure the Azure slave can reach the master via the Jenkins URL and ensure to configure fixed TCP port for JNLP slave. Refer to help for details.

Jenkinsの管理 - グローバルセキュリティの設定を選択すると、TCP port for JNLP agents の固定ポート番号を確認できます。

f:id:TonyTonyKun:20161224150151p:plain

Azure ポータルを開いて、Network Security Group の Inbound Security Rules に、先ほど確認したポート番号(50000)を開放する設定を追加します。

f:id:TonyTonyKun:20161224150230p:plain

2つ目の警告には、Windows Slave Node の起動時に実行される初期化スクリプトを設定しておく旨が記載されています。

Ensure image is pre-configured with a Java runtime or provide a script to install Java in headless (silent) mode. If using JNLP, you can leave this blank for default script to execute or refer here for a sample script.

こちらのスクリプトを貼りければ良いですが、credentails の "username:apitoken" の部分は、環境に合わせて編集してください。API トークンは、Jenkinsの管理 - ユーザーの管理を選択して、歯車アイコンをクリックすると、確認することができます。

f:id:TonyTonyKun:20161225050048p:plain

Jenkinsの管理 - システムの設定に戻り、Init Script に初期化スクリプトを貼り付けたら、設定は完了です。

動作確認

新しいジョブを作成します。フリースタイル・プロジェクトのビルドを選択し、このジョブを実行するノードを制限します。ラベル式には、先ほど設定した "Windows" を指定することで、Master ではなく Slave のノードで実行されるようになります。

f:id:TonyTonyKun:20161224150607p:plain

ビルド手順を追加し、シンプルな Windows バッチコマンドを設定します。

f:id:TonyTonyKun:20161224150634p:plain

ビルド実行をクリックすると、ジョブが実行されます。初回のビルド実行は、Windows Slave Node の仮想マシンが作成されるので少し時間がかかりますが、無事にジョブが実行されたことを確認できます。

f:id:TonyTonyKun:20161224150659p:plain

ダッシュボードに戻ると、ビルド実行状態に Master と Slave のノードが待機中であることがわかります。Retension Time の初期値が 60 分なので、最後にビルドされてから 60 分が経過すると、Slave のノードが停止するので、無駄なコストも発生しません。

f:id:TonyTonyKun:20161224150715p:plain

まとめ

Azure のようなクラウドに CI 環境を構築することで、イニシャルコストを抑えることができますし、ビルドやテスト作業の負荷に応じてノードを増やしたり減らしたりすることもできます。
CI 環境は、簡単に作り直したり複製したりすることができる Docker と相性が良いので、今回のような仮想マシンベースではなく、Docker をベースに構築するとさらに便利になると思います。

Visual Studio for MAC を試してみた

ASP.NET ASP.NET Core Xamarin

先日の Microsoft Connect(); で発表された MAC 向けの Visual Studio(Preview)を試してみました。
ASP.NET Core で作った Web API を Xamarin Forms のアプリから呼び出してみます。

インストール

こちらから無料でダウンロードすることができます。
www.visualstudio.com
Xcode が必須なので最初にインストールしましたが、それ以外はウィザード通りに進めれば、問題なくインストールできました。

ASP.NET Core で Web API を作る

Visual Studio for MAC を起動して、新しいプロジェクトを作成します。テンプレートは、ASP.NET Core Empty Web Application を選択します。

f:id:TonyTonyKun:20161127052227p:plain

Web API を実装するために必要な NuGet ライブラリをインストールします。

  • Microsoft.AspNetCore.Mvc
  • Json.NET

f:id:TonyTonyKun:20161127052323p:plain

ASP.NET Core プロジェクトで MVC を有効にするため、Startup クラスに AdddMvc と UseMvc の2つのメソッドを追加します。

public class Startup
{
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddMvc();
	}

	public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
	{
		loggerFactory.AddConsole();

		app.UseMvc();

		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}
		app.Run(async (context) =>
		{
			await context.Response.WriteAsync("Hello World!");
		});
	}
}

モデルとして、Person クラスを追加します。

public class Person
{
	public int Id { get; set; }
	public string Name { get; set; }
}

コントローラーとして、PersonController クラスを追加します。

[Route("api/person")]
public class PersonController : Controller
{
	public List<Person> Get()
	{
		return new List<Person> {
			new Person{ Id = 1, Name = "立花 瀧"},
			new Person{ Id = 2, Name = "宮水 三葉"},
		};
	}
}

これで Web API の実装は完了です。デバッグ実行して「localhost:5000/api/person」にアクセスすると、JSON が返却されます。

f:id:TonyTonyKun:20161127052626p:plain

Xamarin Forms から Web API を呼び出す

Xamarin Forms 用にもうひとつ Visual Studio for MAC を起動するには、ちょっとしたコツが必要です。Dock からでは複数の Visual Studio for MAC を起動できないので、ターミナルからコマンドで起動します。

open -n "/applications/Visual Studio.app"

もう1つの Visual Studio for MAC が起動したら、新しいプロジェクトを作成します。テンプレートは、Xamarin Forms App を選択します。

f:id:TonyTonyKun:20161127052747p:plain

Web API を呼び出すために必要な NuGet ライブラリをインストールします。

  • Microsoft.HTTP.Client.Libraries
  • Json.NET

f:id:TonyTonyKun:20161127052828p:plain

Xamarin Forms プロジェクトにボタンとリストビューを追加して、コードビハインドから Web API を呼び出すコードを追加します。

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XamarinApp01" x:Class="XamarinApp01.XamarinApp01Page">
  <StackLayout>
    <Button Text="your name" Clicked="getPerson" />
    <ListView x:Name="personList" >
      <ListView.ItemTemplate>
        <DataTemplate>
          <TextCell Text="{Binding Name}" />
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </StackLayout>
</ContentPage>
public partial class XamarinApp01Page : ContentPage
{
	public XamarinApp01Page()
	{
		InitializeComponent();
	}

	public async void getPerson(object sender, System.EventArgs e)
	{
		using (var client = new HttpClient())
		{
			var response = await client.GetAsync("http://localhost:5000/api/person");
			if (response.IsSuccessStatusCode)
			{
				var json = await response.Content.ReadAsStringAsync();
				this.personList.ItemsSource = JsonConvert.DeserializeObject<List<Person>>(json);
			}				
		}
	}
}
public class Person
{
	public int Id { get; set; }
	public string Name { get; set; }
}

これで Xamarin Forms の実装は完了です。

結果確認(iOS)

まず、ASP.NET Core プロジェクトをデバッグ実行しておきます。
次に、Xamarin Forms プロジェクトで iOS のプロジェクトをスタートアップに設定してデバッグ実行すると、エミュレータが起動して Web API を呼び出して結果を表示することができます。

f:id:TonyTonyKun:20161127053054p:plain

なお、iOS のプロジェクトにも Json.NET の NuGet ライブラリを追加しておく必要がありました。

結果確認(Android)

同様に Android のプロジェクトをスタートアップに設定してデバッグ実行すると、エミュレータが起動しますが、Web API を呼び出すタイミングでエラーが発生しました。

f:id:TonyTonyKun:20161127053207p:plain

Android のエミュレータには詳しくないのですが、どうやら localhost には接続できないようです。
そのため、Web API を Azure Web Apps にデプロイすることで、結果を表示することができました。

f:id:TonyTonyKun:20161128064749p:plain

まとめ

Visual Studio for MAC は、開発者が好みのデバイスで得意な言語を使ってモバイルとクラウドのアプリケーションを作れる時代を目指していることを実感できます。
まだプレビュー版ということもあり、Windows 版の Visual Studio にある Azure にダイレクトにデプロイする機能などはありませんが、正式リリースに向けて機能が充実していくことを期待しています。

ASP.NET Core を Docker Cloud で Azure に自動デプロイする

ASP.NET ASP.NET Core Microsoft Azure Docker

最近、ASP.NET Core を触り始めたので、de:code 2016 のセッションで行われていたデモを試してみました。

f:id:TonyTonyKun:20161010132905p:plain

セッションでは Azure と AWS にデプロイしていましたが、今回は Azure だけにデプロイします。

  1. Mac 上で ASP.NET Core のプロジェクトを作成する
  2. GitHub にプッシュする
  3. Docker Hub でビルドが実行され、Docker イメージが作成される
  4. Docker Cloud が Docker イメージを Azure にデプロイする

前準備(ASP.NET Core)

ASP.NET Core の環境構築については、前回の記事を参照してください。
gooner.hateblo.jp

前準備(Docker Hub)

Docker Hub は、Docker イメージを公開・共有できるサービスです。公開されている公式リポジトリを使ったり、自分で作った Docker イメージをアップロードできます。今回は、Automated Build という機能を利用して、GitHub のリポジトリと連携させます。

事前に、GitHub でリポジトリを作成しておきます。DockerCloudTest という名前で作成しました。
Docker Hub にログインして、右上の Create Automated Build を選択して GitHub のリポジトリとリンクさせます。

f:id:TonyTonyKun:20161010133543p:plain

前準備(Docker Cloud)

Docker Cloud は、コンテナ化されたアプリケーションを Docker Hub から取り出し、任意のクラウドやデータセンターへデプロイし、運用管理する機能を提供するサービスです。Docker 社が Tutum を買収し、Docker Cloud に名前を変えて提供しています。

Docker Cloud にログインして、Link Provider から Azure とのリンクを設定します。Azure のサブスクリプションID を入力して、証明書をダウンロードします。ダウンロードした証明書は、旧 Azure ポータルの設定の管理証明書からアップロードしておきます。

f:id:TonyTonyKun:20161010134017p:plain

次に、Create a Node を選択して、Node Cluster を作成します。

f:id:TonyTonyKun:20161010134112p:plain

数分待つと、DEPLOYING が DEPLOYED に変わり、Azure 上にホスト用の VM が作成されます。

f:id:TonyTonyKun:20161010134134p:plain

ちなみに、Azure ポータルで見ると、Linux の仮想マシンが作成されていることが分かります。

f:id:TonyTonyKun:20161011032403p:plain

Azure 以外では、AWS や SoftLayer などのクラウドにもデプロイすることができます。

ASP.NET Core アプリケーションを GitHub にプッシュする

Mac 上で Yeoman を使って、ASP.NET Core MVC アプリケーションを作成します。ローカルの git にコミットした後、GitHub にプッシュします。

git init
git add -A
git commit -m ‘initial commit’
git remote add origin https://github.com/xxx/DockerCloudTest.git
git push -u origin master

Docker Hub に Docker イメージを作成する

Yeoman で作成したプロジェクトには、Dockerfile が含まれています。

FROM microsoft/dotnet:latest
RUN apt-get update && apt-get install -y sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*
COPY . /app
WORKDIR /app
RUN ["dotnet", "restore"]
RUN ["dotnet", "build"]
RUN ["dotnet", "ef", "database", "update"]
EXPOSE 5000/tcp
CMD ["dotnet", "run", "--server.urls", "http://*:5000"]

GitHub にプッシュして数分待つと Building が Success に変わり、Docker イメージが作成されます。

f:id:TonyTonyKun:20161010134251p:plain

Docker Cloud から Azure にデプロイする

Docker Cloud では、デプロイする Docker イメージを Service として管理します。Create a Service の My repositories から Docker Hub のリポジトリを選択します。

f:id:TonyTonyKun:20161010134331p:plain

ポート番号は 80 で接続したいので、Published にチェックを入れて設定します。

f:id:TonyTonyKun:20161010134352p:plain

Create & Deploy ボタンを押して数分待つと、Starting が Running に変わり、デプロイが完了します。Service Endpoints の URL をクリックして、tcp を http に変えてブラウザからアクセスすると、ASP.NET Core MVC のページが表示されます。

f:id:TonyTonyKun:20161010134427p:plain

CI / CD を設定してデプロイを自動化する

Docker Cloud と Docker Hub に CI / CD を設定して繋げることで、先ほどは手動でデプロイした部分を自動化します。
まずは、Docker Cloud で Redeploy のトリガーを作成します。

f:id:TonyTonyKun:20161010134511p:plain

次に、Docker Hub で Web Hooks を設定します。Docker Cloud で作成した Redeploy トリガーの URL を貼り付けて、先頭に https://cloud.docker.com/ を付加します。

f:id:TonyTonyKun:20161010134550p:plain

結果確認

Visual Studio Code を使って、ASP.NET Core MVC アプリケーションの About.cshtml を変更して、GitHub にプッシュします。

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<h4>Hello Docker Cloud !!!</h4>

GitHub → Docker Hub → Docker Cloud の順番で処理が自動化され、最終的に Azure にデプロイされます。

f:id:TonyTonyKun:20161010134715p:plain

まとめ

Docker を使うと、クラウド上のいろいろなサービスを繋げることで、開発ライフサイクルを自動化できます。
今回は Docker Cloud の無償版を利用したので Azure 上 に1つのノードしか展開できませんでしたが、有償版であれば Azure と AWS にノードを分けて展開したり、一方のベンダーに障害が発生したら別のベンダーにフェールオーバーしたりできます。
自分の作ったアプリケーションが、クラウドベンダーを超えて展開した Docker 上で動かせるのは面白いと思いました。