まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:git

IBM Bluemix の利用者に提供されているサービスの1つに IBM DevOps Services(以下、IDS)があります。名前の通り、DevOps のための統合環境サービスなのですが、事実上「ウェブから使えるエディタ」として認識している人もいらっしゃるかもしれません:
2016091306


もちろん統合環境であるからには、こうした「ウェブだけでソースコードが編集できる」機能があることも重要ですが、それだけではありません。ソースコードのバージョン管理として事実上の標準となった Git のリポジトリ機能も使えますし、ビルド&デプロイの管理機能も付属しています。これらはバラバラに(=自分の使い慣れたツールと組み合わせて)使うこともできますし、この環境だけで全て利用することもできます。今回はその前者の例として、IDS を Git のリポジトリとして(のみ)使う例を紹介します。要はソースコードの編集は普段使い慣れたローカルマシンのエディタを使いつつ、ソースコードのバージョン管理に IDS を使おう、という考え方です。必ずしも Bluemix アプリケーションではない、普通のウェブアプリケーションやツールのソースコード管理としても IDS が使える、という使い方をイメージしています。

まずは IDS にウェブブラウザでアクセスして IBM Bluemix の ID とパスワードでログインします:
http://hub.jazz.net/


初めて IDS を使う場合はここでユーザー名の別名を聞かれたりするので適当に決めて答えておきましょう。ただ、ここで決めた名前がこの後作成する Git リポジトリの URL の一部になるのでそのつもりで。

ログイン直後の画面です。既にプロジェクトを利用していたりすると、それらが表示されている画面になるので、見た目は人によって多少変わるかもしれません。以下の画面はまだ何も使っていない、まっさらな状態でのプロジェクト一覧画面です:
2016091301


では早速 Git リポジトリとしてのプロジェクトを1つ追加しましょう。"Start coding" と書かれた大きなアイコン部分をクリックします:
2016091301


ここでプロジェクトの名称(以下の例では "my1stApp")を指定します。今回はこの IDS 内に新しいプロジェクトを作成するので、"Create a new repository" を選択します:
2016091302


続いてリポジトリの作成先を指定するので、"Create a Git repo on Bluemix" を選択します:
2016091303


するとアイコンのすぐ下に今から作成する Git のリポジトリ URL が確認できます。後で再確認することもできますが、一度ここでメモしておきましょう。 また作成するリポジトリにサンプルの README を含めるかどうかを選択するチェックボックスが表示されています。ここでは最初に README を含めておくことにします(任意です)ので、チェックボックスを ON にしておきます:
2016091304


続けてオプションが3つ表示されています。上から順に (1)プライベート(非公開)リポジトリにするか、(2) Scrum 管理機能を追加するか、(3) Bluemix アプリケーションプロジェクト機能を追加するか、です。この例では全て OFF にしていますが、いずれも必要に応じて ON/OFF してください。最後に "CREATE" ボタンを押すと、この設定で Git リポジトリが作成されます:
2016091305


Git リポジトリが作成されると、このような画面に切り替わります。指定した名前のプロジェクトが生成され、その中に License.txt と(オプションで指定した)README.md が含まれている状態で生成されています:
2016091306


画面内で Git のブランチ(この図では master)を表示する部分の右側にダウンロードアイコンが表示されています。現在のブランチの状態でソースコードをまとめてダウンロードする場合はこのアイコンをクリックします(今は行わなくて構いません):
2016091307


また、更にその右側に "Git URL" と書かれた箇所があり、そこをクリックすると改めて Git リポジトリの URL を確認することができます。忘れてしまった場合はこの方法で Git URL を確認してください(このすぐ後に使います):
2016091308


では試しにこの Git プロジェクトの中身を別マシンに clone してみましょう。Git が導入されている環境下で以下のように自分の Git URL(以下の例では https://hub.jazz.net/git/teyande/my1stApp)を指定して git clone してみます:
# git clone https://hub.jazz.net/git/teyande/my1stApp

成功するとこのように License.txt と README.md を含む my1stApp というディレクトリが作成され、現在のリポジトリがクローンできたことがわかります:
2016091301


次にこのプロジェクトディレクトリに移動して、ローカルマシンで変更を加えてみます。本当はここでは vim とか Sublime などの普段使い慣れたエディタ等を使ってファイルを編集することを想定していますが、以下の例では echo コマンドを使ってシンプルな phpinfo.php というファイルを1つ追加しています。何か新しいテキストファイルを1つ(以上)同じディレクトリ内に作成してみてください:
# cd my1stApp
# echo '<?php phpinfo(); ?>' > phpinfo.php

この時点でディレクトリにはもともと存在していた2つのファイルに加え、いくつかのファイルが追加されている状態になっています:
2016091302


ではこの変更を Gir リポジトリに反映させましょう。git add して、git commit します:
# git add .
# git commit -m 'phpinfo.php added.'

こんな感じでローカルリポジトリへのコミットが成功するはずです:
2016091303


では最後に、このローカルリポジトリへの変更をリモートリポジトリへも反映させるべく、git push します。途中でユーザー名やパスワードを聞かれるので、IBM Bluemix のIDおよびパスワードをそれぞれ指定して入力します:
# git push
  :
  :

Username for 'https://hub.jazz.net': bluemix@teyan.de
Password for 'https://bluemix@teyan.de@hub.jazz.net':
  :
  :

↓こんな感じになれば成功です:
2016091304


git push が成功すると、IDS 内のファイルにもその変更が反映されているはずです。この例では元のプロジェクトには存在していなかった phpinfo.php ファイルが git push によって送り込まれ、プロジェクトファイルの一部として追加されていることがわかります:
2016091305


とりあえず Git リポジトリとしての機能が使えることがわかりました。ただこれだけなら GitHub と変わりません。GitHub にない機能の1つとしては「(無料で)プライベートリポジトリが持てる」ことが挙げられます。例えば今回は作成時に Private チェックボックスをオフにしていたので、この時点ではリポジトリは公開されており、同じ URL を誰からでも(IBM Bluemix のアカウントを持っていない人からでも)参照することができる状態になっています:
2016091401


公開状態で作成されたリポジトリをプライベートな非公開状態に変更するには、リポジトリ画面右上の歯車アイコンをクリックし、左メニューから "OPTIONS" を選ぶと、"Private" のチェックボックスが現れます。ここにチェックが入っていれば非公開、入っていなければ公開状態となります:
2016091402


非公開状態に切り替えてみましょう。"Private" チェックボックスを ON にして、"SAVE" ボタンをクリックします:
2016091403


この状態で、同じリポジトリ URL にアクセスすると IBM Bluemix アカウントでログインしていない場合はログインが求められるようになります。また自分(リポジトリのオーナー)以外の ID でログインすると、以下の様な「非公開です」という画面だけが表示されて、中身を確認することはできなくなります:
2016091404


Git のリポジトリを非公開状態で管理しようとすると、GitHub では有償アカウントが必要になります。GitHub 以外にオープンソース製品などで独自にプライベートリポジトリを作れないことはないのですが、IBM Bluemix の IDS を使えば、実質的に無料でプライベートリポジトリまで含めて利用することができる、ということになりますね。 IDS は単なる Git のリポジトリ以上の機能がありますが、この無料のプライベートリポジトリ機能だけでも魅力的だと思っています。


Java で Git のリポジトリを操作するライブラリに JGit があります:
http://www.eclipse.org/jgit/
2016082801


現在は Eclipse 参加のサブプロジェクトとして提供されています。すごく便利な反面、ちょっとクセがあります。以下、基本的な使い方を説明しますが、まずは前提をいくつか:

【前提】
(1) 対象とする Git のリモートリポジトリ URI は http://xxxgit.com/name/project.git とします。
(2) 上記リポジトリにアクセス(特にプッシュ)する際の認証は ID: username, Password: password であるとします。
(3) ローカルリポジトリ(上記リポジトリをローカルにクローンする先)のディレクトリは ./project (つまりカレントディレクトリ上に project というサブディレクトリを作る)とします。


【準備】
JGit のダウンロードページから最新版の JGit をダウンロードし、展開して JAR を取り出し、自分のプロジェクト内に(Classpath を通すなどして)用意します。

ここまで用意できれば JGit を使うことができます。以下、一通りの git 操作(clone, pull, add, commit, push)を行う様子を順に紹介します。


【git clone】
目的のリモートリポジトリ(今回の例では http://xxxgit.com/name/project.git)からコードをクローンします:
try{
  Repository localRepo = new FileRepository( "./project/.git" );
  Git git = new Git( localRepo );

  if( git != null ){
    //. git clone
    git.cloneRepository().setURI( "http://xxxgit.com/name/project.git" ).setDirectory( new File( "./project" ) ).call();
  }
}catch( Exception e ){
  e.printStackTrace();
}

以下全ての例に言えることですが、ローカルリポジトリのインスタンス変数を作る際に指定するのは、ローカルリポジトリのフォルダに "/.git" をつけたものです。

一方、クローン実行時に指定するローカルフォルダはローカルリポジトリのフォルダそのものです。この辺りがクセのある所で、知らないと混乱します。


【git pull】
クローンしたローカルリポジトリに対し、リモートリポジトリに加えられている最新の変更を反映させます:
try{
  Repository localRepo = new FileRepository( "./project/.git" );
  Git git = new Git( localRepo );

  if( git != null ){
    //. git pull
    PullCommand pc = git.pull();
    pc.call();
  }
}catch( Exception e ){
  e.printStackTrace();
}

JGit では各コマンドを実行する際には ****Command クラスの(上記例では PullCommand クラス)インスタンスを作って、必要であれば設定を加えて、call() する、という処理を実行します。

そして次の add コマンドを実行する前に、このローカルリポジトリ内のファイルに何らかの変更が加わっていることを想定してください。


【git add】
ローカルリポジトリ内のファイルシステムに対して行った変更作業をリポジトリに加えます:
try{
  Repository localRepo = new FileRepository( "./project/.git" );
  Git git = new Git( localRepo );

  if( git != null ){
    //. git add
    AddCommand ac = git.add();
    ac.addFilepattern( "." );  //. 全ての変更を git add する
    try{
      ac.call();
    }catch( NoFilepatternException e ){
      e.printStackTrace();
    }
  }
}catch( Exception e ){
  e.printStackTrace();
}

AddCommand インスタンスにファイルパターンを指定して call() する、という手順です。


【git commit】
ローカルリポジトリの変更内容をコミットします:
try{
  Repository localRepo = new FileRepository( "./project/.git" );
  Git git = new Git( localRepo );

  if( git != null ){
    //. git commit
    CommitCommand cc = git.commit();
//. コミッターの名前とメールアドレス、コミットメッセージを指定 cc.setCommitter( "commiter_name", "committer_email" ).setMessage( "Some message." ); try{ cc.call(); }catch( NoHeadException e ){ e.printStackTrace(); }catch( NoMessageException e ){ e.printStackTrace(); }catch( ConcurrentRefUpdateException e ){ e.printStackTrace(); }catch( WrongRepositoryStateException e ){ e.printStackTrace(); } } }catch( Exception e ){ e.printStackTrace(); }

コミッターの名前とメールアドレス、そしてコミットメッセージを追加した上で call() します。


【git push】

ローカルリポジトリの変更内容をリモートリポジトリに対してプッシュします:
try{
  Repository localRepo = new FileRepository( "./project/.git" );
  Git git = new Git( localRepo );

  if( git != null ){
//. git push CredentialsProvider cp = new UsernamePasswordCredentialsProvider( username, password ); PushCommand pc = git.push(); pc.setCredentialsProvider( cp ).setForce( true ).setPushAll(); } }catch( Exception e ){ e.printStackTrace(); }

認証用の usernamepassword を指定してプッシュする、という流れです。


以上、JGit を使った基本的な git コマンドの実行方法を紹介しました。クセがある、と紹介しましたが、ある程度慣れてしまえばそんなに苦ではないと思います。何よりもプログラムから git が使えると複製機能をこれで実装できたりするのですごく便利です。

個人/仲間で作ったアプリのソースコードを管理したり、サンプルアプリ的なものを作ってそのコードを公開したりしようとすると、GitHub は非常に便利です。私も色々な形で使っています。

ただ、GitHub でソースコードを管理すると基本は誰からもソースコードが見れるように公開する形になります。GitHub でプライベート管理をすることは可能ですが、その場合は有償アカウントに切り替える必要があります。業務で使うケースでは(少なくとも開発中は)ソースコードを公開したくない、というケースも珍しくないと思うので、ソースコードをどうやってプライベート管理するか、という問題が生じます。自分も最近ありました。

自分の場合は自分で SubversionGitLab 環境を構築して使っています(両方使っています)。この中の GitLab は GitHub 互換のリポジトリ管理や問題トラッキングの環境を(Community Edition であれば)無料のオープンソースで構築することができるようになります。GitHub 互換なので、git コマンドを使ってソースコードをコミットしてプッシュして・・・という GitHub と同じ管理ができます。git コマンドに慣れた人には非常に便利です。 というわけで、この GitLab 環境を CentOS 上に構築する手順をまとめてみました。

【あらかじめ用意しておくもの】

SSH 鍵のペア。作成方法はこちらを参照:



【導入&設定手順】

GitLab の導入自体は用意されたインストールパッケージを実行するだけなので非常に簡単です。まずは Community Edition のダウンロードページへ行き、自分の環境にあった最新版 GitLab Community Edition のパッケージを選んで導入することになります:
https://packages.gitlab.com/gitlab/gitlab-ce
2015122401
 ↑ラズベリーパイ向けのもパッケージもあるのか・・・


ちなみに、2015/Dec/24 時点では 8.3.0 が最新バージョンでした。このバージョンではオートマージ機能が追加されているようです:
https://about.gitlab.com/2015/12/22/gitlab-8-3-released/


例えば自分の場合であれば 64bit 版の CentOS 6 を使っているので、"el6" と書かれた最新版の rpm パッケージの箇所をクリックすると、以下の様な導入のインストラクションが表示されます。ここに書かれている通りに CentOS 環境からコマンドを実行してインストールします:
2015122402


モジュールインストール後に、環境設定が必要です。具体的には GitLab に自分自身の URL を認識させる必要があります。root 権限で /etc/gitlab/gitlab.rb ファイルを編集し、external_url に自分自身の IP アドレス(以下 'XXX.XXX.XXX.XXX')を設定して保存します:
# vi /etc/gitlab/gitlab.rb
: : external_url 'http://XXX.XXX.XXX.XXX' # 'http://gitlab.example.com' から自分の IP アドレスに書き換え : :

これだけで動かすこともできます。が、この状態で使うと色々不都合が生じることもあります。以下はそのためのオプショナルな設定を加える場合についていくつか紹介します。

まずはこのまま使うとユーザー追加時にメール認証(新規に追加したユーザーにメールが送られて、そのメール内のリンクをクリックしたら本登録)が必要になります。そのためにはメールサーバーとその設定/管理を・・・ ということになりますが、プライベートリポジトリ目的だけで使うのであれば、メール認証(というかメールサーバー管理)が面倒なので、その手順をスキップさせることもできます(その場合は /opt/gitlab/embedded/service/gitlab-rails/app/models/user.rb ファイルをカスタマイズして、ユーザーの登録と同時にメール認証が済んでいるかのように振る舞わせることになります)。テキストエディタで同ファイルを開いて、"class User" で始まる行以降に default_value_for で始まる行が数行続いているはずですが、その最後に以下の一行を追加してください:
# vi /opt/gitlab/embedded/service/gitlab-rails/app/models/user.rb
: : class User < ActiveRecord::Base : : default_value_for :admin, false : : default_value_for :confirmed_at, Time.now # この一行を追加 : : : :

また、CentOS の環境によっては GitLab が使う git ユーザー(セットアップ時に作成されているはずです)に ssh アクセスが許可されていないこともあります。その解除のためには以下の2ファイルを編集する必要があります。

1つ目は /etc/shadow を編集して、パスワードを設定していないユーザーの SSH アクセスを許可してあげてください:
# vi /etc/shadow
: : git:!!:16793::::::  (こっちから)   ↓ git:*:16793::::::   (こっちに変更) : :

もう1つは /etc/ssh/sshd_config を編集して、SSH を許可するユーザーに git を追加した上で sshd をリロードします:
# vi /etc/ssh/sshd_config
: : AllowUsers xxxx yyyy git  (AllowUsers に git を追加) : :

# service sshd reload

以上の内容は環境依存の箇所もありますが、必要に応じて設定してください。

この状態で GitLab を reconfigure します。reconfigure にはしばらく時間かかりますが、"Runnning handers complete" と表示されれば無事成功、これで設定調整は完了です:
# gitlab-ctl reconfigure
  :
  :
  :
  :
Running handlers:
Running handlers complete
Chef Client finished, 211/281 resources updated in 01 minutes 30 seconds
gitlab Reconfigured!

ここからは作成した GitLab 環境に実際にログインしての作業になります。まずはウェブブラウザで GitLab サーバー(http://XXX.XXX.XXX.XXX/)にアクセスしてみます:
2015122403


初期ページが表示されれば一応動いていることになります。まずは管理ユーザーを有効にするため、ユーザーID(root) と初期パスワード(5iveL!fe)を指定してログインします。パスワードはすぐに変更するのでここでは記憶させる必要はありません:
2015122404


ログインに成功すると、とりあえず初期パスワードを変える必要があります。初期パスワード(5iveL!fe)と、新しい管理者用パスワード(確認のため2回)を指定して、新しいパスワードを登録してください:
2015122405


直後に再度ログイン画面に戻るので、ユーザー ID(root) と新しいパスワードを指定してログインしてください:
2015122406


ログイン後にこんな画面が表示されれば、とりあえず初期設定は完了です:
2015122407



【ユーザー追加手順】

自分1人でソースコード管理をするのであれば、このまま管理者権限で作業を続けてもいいのですが、多くのケースでユーザー管理をすることが多いと思います。そこで作業用のユーザーを登録して、以降はその作業ユーザーによるプロジェクト管理を行っていく内容を紹介します。

ユーザーを新規に登録するには、root で GitLab にログインした状態から、ダッシュボード右上の Admin Area をクリックします:
2015122401


続いて NEW USER ボタンをクリックします:
2015122402


新規に登録するユーザーの名前、ユーザー名(ログインID)、そしてメールアドレスを入力して CREATE USER ボタンでユーザーを作成します(この時点ではパスワードは登録しません):
2015122403


これで一般ユーザーの作成が行われました:
2015122404



メールサーバーが正しく設定されていて、メール認証が有効になっている場合は、指定したメールアドレスにメールが送られ、その本文内のリンクからパスワード設定を含めた本登録を行うことになります。

上記で紹介した手順でメール認証を無効にした場合は、このユーザーの初期パスワードを手動で登録してあげる必要があります。上記画面右上の EDIT ボタンをクリックして、初期パスワードを登録してあげてください:
2015122400


では、改めてこのユーザーでログインしてみます。root で GitLab にログインしている場合はダッシュボード右上の Sign out からログアウトしてください:
2015122406


改めて GitLab サーバーにアクセスして、今度は作成した一般ユーザーの ID とパスワードでログインします:
2015122407


一般ユーザーでログインできることを確認してください:
2015122408


このまま、このユーザー向けの SSH 鍵を登録しましょう。ダッシュボード左メニューから Profile Settings を選択します:
2015122401


続いて SSH Keys をクリックします:
2015122402


登録済み SSH 鍵の一覧が表示される画面ですが、この時点ではまだ何も登録されていないので表示されません。ではあらかじめ用意した SSH 鍵を登録してみます。ADD SSH KEY ボタンをクリックします:
2015122403


テキストエリアが表示されるので、この中に用意した公開鍵の内容をペーストします。また Title 欄に名前を付けて、最後に ADD KEY ボタンをクリックします:
2015122404


このユーザーが使える SSH 鍵が登録できました:
2015122405


同様にして、必要なユーザーと、そのユーザーの SSH 鍵を必要なだけ登録しておきます。


【プロジェクト追加手順】

では一般ユーザーでプロジェクトを追加してみます。ソースコードの管理をするにもまずはそのプロジェクトを作成する必要があります。

GitLab ダッシュボードに一般ユーザーでログインした後に、Project(初期状態でここが選ばれているはずです)の NEW PROJECT ボタンをクリックします:
2015122401


なお、一度プロジェクトを作成した後の二度目以降は画面右上の New Project をクリックしてください:
2015122408


プロジェクトの名前(下図では myhelloworld)や Description を入力後、Visivility Level に Private を指定すると(パブリックではない)プライベートなリポジトリを作ることができます。最後に CREATE PROJECT ボタンをクリックしてプロジェクトを作成します:
2015122402


GitLab 上にプロジェクト myhelloworld が新規に作成できました:
2015122403


画面を下にスクロールすると、この後のコマンド操作方法についての簡単なガイドが紹介されています。必要に応じて参照してください:
2015122404


このプロジェクトに他のユーザーをメンバー登録すると、そのユーザーからもこの Git リポジトリが使えるようになります。プロジェクト画面左の Members を選ぶと、GitLab ユーザーをプロジェクトメンバーに追加する画面に切り替わります:
2015122405


People にカーソルを持って行くと、GitLab 上のユーザー一覧が表示されます。ここから選んで指定することができます:
2015122406


プロジェクトに追加したい人と、その権限を指定し、ADD USERS TO PROJECT ボタンをクリックすると、そのユーザーは指定した権限でプロジェクトメンバーとして追加されます:
2015122407


この図では Administrator ユーザーが Master 権限でプロジェクトに追加されたことが分かります:
2015122408


これを必要なだけ繰り返して、プロジェクトにメンバーを追加します。



【プロジェクトの Git リポジトリを git クライアントから操作する手順】

ではこの myhelloworld プロジェクトの Git リポジトリを実際に使ってみましょう。まずは適当なファイル1つをコミット&プッシュしてみます。

まずは作業マシン上に git クライアントを導入しておきます。作業マシンが CentOS や RedHat であれば以下のコマンドで導入できます:
# yum install git

また、登録した SSH 鍵の秘密鍵ファイル(ファイル名 guestkey とします)を利用ユーザーの ~/.ssh/ 以下に用意しておきます。そして ~/.ssh/config ファイルを以下の内容で作成します:
Host mygitlab-server
        HostName XXX.XXX.XXX.XXX  (GitLab サーバーのIPアドレス)
        IdentityFile ~/.ssh/guestkey  (秘密鍵ファイル)
        User dotnsf  (GitLab サーバーのログインユーザー名)

そして鍵ファイルと config ファイルのパーミッションを 600 に設定します:
$ chmod 600 ~/.ssh/guestkey
$ chmod 600 ~/.ssh/config

では SSH の準備が整ったので、実際に git コマンドを使ってみます。まずは Global 設定で user.name と user.email を設定します:
$ git config --global user.name "K.Kimura"
$ git config --global user.email "xxxx@xxxxx.com"

まだ最初のコミット前なので、ゼロからリポジトリの中身を作る必要があります。というわけで専用のディレクトリを1つ作り、その中にプロジェクトのファイルを追加します。ここではとりあえずホームディレクトリ以下に myhelloworld というサブディレクトリを作り、その中に README.md ファイルを1つ追加しました(ソースコードなどを加える場合も myhelloworld 以下に追加していくことになります):
$ cd 
$ mkdir myhelloworld
$ cd myhelloworld
$ echo '# MyHelloWorld' > README.md

この myhelloworld ディレクトリを git リポジトリとして GitLab サーバーの myhelloworld プロジェクトにコミット&プッシュします(以下は myhelloworld ディレクトリで行います):
$ git init
$ git remote add origin git@mygitlab-server:dotnsf/myhelloworld.git
$ git add .
$ git commit -m 'first commit'
$ git push -u origin master

最後の git push 実行時に「接続を続けますか?」というプロンプトが表示されたら 'yes' と入力してください。また途中でパスフレーズの入力をするよう求められた場合は登録した SSH 鍵ファイルを作成した時に指定したパスフレーズを入力してください。成功するとこのような画面になるはずです:
$ git push -u origin master
The authenticity of host 'XXX.XXX.XXX.XXX (XXX.XXX.XXX.XXX)' can't be established.
RSA key fingerprint is aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'XXX.XXX.XXX.XXX' (RSA) to the list of known hosts.
Enter passphrase for key '/home/linux1/.ssh/guestkey': (SSH 鍵のパスフレーズを入力)
Counting objects: 3, done.
Writing objects: 100% (3/3), 222 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@mygitlab-server:dotnsf/myhelloworld.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.
$

この状態で GitLab サーバー上の myhelloworld プロジェクトを見ると、このコミット&プッシュが記録されて、以下のようになるはずです:
2015122401


画面左の Files をクリックすると、現在の Git リポジトリのファイル一覧(まだ README.md しかないので1つだけ)が確認できます。これでプライベート Git リポジトリが作成できました:
2015122402


同じユーザーでも、別ユーザーでもいいのですが、このリポジトリを操作する場合の手順も紹介しておきます。上記のグローバル設定を行うまでは共通です(同一ユーザーで行う場合は myhelloworld ディレクトリごと削除してから以下を行ってください)。その上で GitLab サーバーの myhelloworld リポジトリをクローンします。途中でパスフレーズの入力を求められた場合は同様に SSH 鍵ファイル作成時に指定したパスフレーズを入力してください:
$ cd (作業ディレクトリに移動 指定しない場合はホームディレクトリ)
$ git clone git@mygitlab-server:dotnsf/myhelloworld.git
Initialized empty Git repository in /home/linux1/src/myhelloworld/.git/
Enter passphrase for key '/home/linux1/.ssh/guestkey': (SSH 鍵のパスフレーズを入力)
remote: Counting objects: 3, done.
Receiving objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
$

この時点でカレントディレクトリに myhelloworld というディレクトリが作られ、その中に現在の myhelloworld リポジトリの内容がクローンされているはずです:
$ cd myhelloworld
$ ls -a
.   ..   .git   README.md


この中に以下の内容で index.php ファイルを追加します(名前は何でもいいし、どのような内容でも構いませんが、新規にファイルを作って追加してください):
$ echo '<?php echo "ハローワールド!\n"; ?>' > index.php

追加したファイルを GitLab のリポジトリにコミットしてプッシュします:
$ git add .
$ git commit -m 'index.php added.'
$ git push -u origin master
  (SSH 鍵のパスフレーズを入力してプッシュ)

ここまでの作業が成功すると、GitLab の myhelloworld プロジェクトのファイル一覧はこのようになり、index.php が追加された状態になります:
2015122403


「新規に作成してコミット&プッシュ」も、「クローンして作業してコミット&プッシュ」もできることがわかりました。



GitLab Community Edition を使えば、無料でプライベートな Git リポジトリを作って管理する、ということもできそうです。GitLab Community Edition にはラズベリーパイ用のモジュールも用意されているようなので、余った(?)ラズパイの使いみちとしても良さ気な感じです。


前回までの続きです:
Bluemix のビルドパックを作る(1/3)
Bluemix のビルドパックを作る(2/3)


このシリーズは3回に分けて IBM Bluemix 用のビルドパックをゼロから作成する手順を説明するもので、今回はその3回目です:
(1) ビルドパックを作る上で知っておくべきこと
(2) ビルドパックを作るための準備作業    
(3) ビルドパックを作成して、実際に動作確認
  ←今回はここ

前回までに、ビルドパックを作成する上で知っておくべき仕組みや制限事項についてをまとめ、実際に PHP + Apache HTTP Server 環境のビルドパックを作る上で必要になるモジュール(ビルドパック実行時の権限では作れないモジュール)の作成を終えました。

では今回はこれらのモジュールを使って、実際のビルドパックを作成し、実際に IBM Bluemix 上のランタイムとして起動し、動作を確認するまでを紹介します。

ではビルドパック作成環境にログインします。前回の作業は Ubuntu 環境下で行う必要がありましたが、ここからは Ubuntu である必要はありません(Windows や Mac, Ubuntu 以外の Linux でも構いません)。が、以下はそのまま Ubuntu を使って作業する前提(つまり前回の作業で出来上がったモジュールもローカル内にあるという前提)で紹介をします。 というわけで改めて Ubuntu 環境に SSH 等でログインします:
2015100901


作業用のディレクトリを用意します。今回は /tmp/buildpack というディレクトリを新たに作成して、この中で作業することにします:
$ mkdir -p /tmp/buildpack
$ cd /tmp/buildpack


上記作業内容の (1) で紹介したように、ビルドパックは3つのスクリプトを用意することで作成します。この3つのスクリプトを /tmp/buildpack/bin 以下に作成します。3つのスクリプトは Ruby などのスクリプト言語を利用することもできますが、今回は(個人的な慣れもあって)シェルを使って記述することにします:
$ mkdir bin
$ cd bin
$ touch detect
$ touch compile
$ touch release
$ chmod 775 detect
$ chmod 775 compile
$ chmod 775 release
$ cd ..


また、このスクリプト(具体的には compile スクリプト)の中では、前回の作業 (2) で作成した PHP と Apache HTTP Server 2つのモジュールを使うことになります。これらのモジュールをあらかじめビルドパックのディレクトリ内にコピー(または移動)しておきます。前回の作業 (2) と異なる環境で今回の作業をしている場合は、前回の環境からこれらのモジュールを SFTP などで転送して取得してください:
$ mkdir -p download/httpd/2.4
$ mv /app/apache-2.4.16.tar.gz download/httpd/2.4
$ mkdir -p download/php/5.6
$ mv /app/php-5.6.14.tar.gz download/php/5.6


また、PHP および Apache HTTP Server の動作設定とも言える php.ini と httpd.conf ファイルもあらかじめ用意しておきます:
$ mkdir config
$ vi config/httpd.conf
   :

$ vi config/php.ini
   :


これらのファイルの内容は皆さんが作成していただいても構わないのですが、今回は日本語を使う前提で、比較的緩めの条件設定で環境構築をするような内容にしています。具体的な内容は以下のリンク先と同じものです。これらと同じ内容で2つのファイルを用意/編集しておくと、かなりゆるゆるで、本番環境としてはともかく、開発テスト用に便利な PHP ランタイムができます:
https://github.com/dotnsf/php-apache-buildpack/tree/master/config

なお、注意事項として Apache HTTP Server が動作するポートは固定値ではなく、必ず環境変数 PORT から取得して起動させる必要があることに注意してください。したがって httpd.conf 内の Listen ディレクティブの指定は必ず以下の様な指定になっている必要があります:
  :
  :
Listen ${PORT}
  :
  :


あらためて、ここから3つのスクリプトを作っていきます。まずは detect スクリプトを作ります。このスクリプトはビルドパックの適用に適した環境が整っているかどうかを判断して、ふさわしいと判断した場合だけ次にすすめるようにする、というためのスクリプトです。 今回は PHP + Apache HTTP Server のビルドパックなので、選択肢としては「無条件にふさわしいと判断する」というのもアリですが、勉強目的もあるので多少強引に何らかの条件を付けるようにしてみましょう。

というわけで、今回の detect スクリプトでは
 ドキュメントルートに index.php ファイルが存在していたらビルドパック適用条件を満たしている、
 index.php が存在していない場合はビルドパックを適用しない

という条件判断をさせることにします。

また、これも (1) の中で説明していますが、detect スクリプトは実行ディレクトリ("cf push" を実行した時のカレントディレクトリ)を引数に受け取ります。この引数を使って、detect スクリプトを以下のような内容で編集します:

※ bin/detect の中身
#!/usr/bin/env bash
################################################################################
# bin/detect <build-dir>                                                       #
################################################################################

# ---------------------------------------------------------------------------- #
# ドキュメントルートに index.php が存在している時だけ有効                      #
# ---------------------------------------------------------------------------- #
if [ -f $1/index.php ]; then
  echo "My PHP Env"
  exit 0
else
  exit 1
fi


これで detect スクリプトによって、カレントディレクトリに index.php ファイルが存在している時だけ実行結果として 0 を返して compile スクリプト続行、存在してない場合は 1 が返されて処理が止まる、という実装にしました。


続いて compile スクリプトを作ります。ここがいわば「ビルドパックの本体」といえる部分で、実際のサーバー環境を、このスクリプト1つだけで構築していくことになるものです。

この compile スクリプトの中では前回の作業 (2) で作成したモジュールを使います:

※ bin/compile の中身
#!/usr/bin/env bash
################################################################################
# bin/compile <build-dir> <cache-dir>                                          #
################################################################################

# ---------------------------------------------------------------------------- #
# 変数を設定                                                                   #
# ---------------------------------------------------------------------------- #
BIN_DIR=$(dirname $0)
BUILDPACK_DIR=`cd $(dirname $0); cd ..; pwd`
BUILD_DIR=$1
CACHE_DIR=$2

APACHE_VERSION="2.4.16"
APACHE_PATH="apache"
PHP_VERSION="5.6.14"
PHP_PATH="php"

# ---------------------------------------------------------------------------- #
# ドキュメントルート(/app/www/)の設定                                          #
# ---------------------------------------------------------------------------- #
cd $BUILD_DIR

mkdir -p $CACHE_DIR/www
mv * $CACHE_DIR/www
mv $CACHE_DIR/www .

# ---------------------------------------------------------------------------- #
# コンパイル済みの Apache HTTP Server を展開                                   #
# ---------------------------------------------------------------------------- #
APACHE_DIR="${BUILDPACK_DIR}/download/httpd/2.4/apache-$APACHE_VERSION.tar.gz"
echo "-----> Bundling Apache version $APACHE_VERSION"
tar -xvf $APACHE_DIR

# ---------------------------------------------------------------------------- #
# コンパイル済みの PHP を展開                                                  #
# ---------------------------------------------------------------------------- #
PHP_DIR="${BUILDPACK_DIR}/download/php/5.6/php-$PHP_VERSION.tar.gz"
echo "-----> Bundling PHP version $PHP_VERSION"
tar -xvf $PHP_DIR 

# ---------------------------------------------------------------------------- #
# httpd.conf と php.ini を上書き                                               #
# ---------------------------------------------------------------------------- #
ls -al $BUILDPACK_DIR
cp $BUILDPACK_DIR/config/httpd.conf $APACHE_PATH/conf
cp $BUILDPACK_DIR/config/php.ini $PHP_PATH

# ---------------------------------------------------------------------------- #
# php のパスを設定                                                             #
# ---------------------------------------------------------------------------- #
mkdir -p bin
ln -s /app/php/bin/php bin/php

# ---------------------------------------------------------------------------- #
# Apache HTTP Server 起動スクリプト(boot.sh)作成                               #
# ---------------------------------------------------------------------------- #
cat >> boot.sh <<EOF
for var in \`env|cut -f1 -d=\`; do
echo "PassEnv \$var" >> /app/apache/conf/httpd.conf; done touch /app/apache/logs/error_log touch /app/apache/logs/access_log tail -F /app/apache/logs/error_log & tail -F /app/apache/logs/access_log & export LD_LIBRARY_PATH=/app/php/ext export PHP_INI_SCAN_DIR=/app/www echo "Launching apache" exec /app/apache/bin/httpd -DNO_DETACH EOF chmod +x boot.sh # ---------------------------------------------------------------------------- # # キャッシュディレクトリをクリア # # ---------------------------------------------------------------------------- # rm -rf $CACHE_DIR

最後に release スクリプトを作ります:

※ bin/release の中身
#!/usr/bin/env bash
################################################################################
# bin/release <build-dir>                                                      #
################################################################################

# ---------------------------------------------------------------------------- #
# boot.sh を実行するような YAML ファイルを生成                                 #
# ---------------------------------------------------------------------------- #
cat << EOF
config_vars:
    MYENV: myphp
default_process_types:
    web: sh boot.sh
EOF

これでビルドパックは完成です。作業した /tmp/buildpack 以下のディレクトリ/ファイル構成は以下の様な状態になっているはずです:
/tmp/buildpack/
 |- bin/
 |   |- compile
 |   |- detect
 |   |- release
 |- config/
 |   |- httpd.conf
 |   |- php.ini
 |- download/
     |- httpd/
     |   |- 2.4/
     |   |    |- apache-2.4.16.tar.gz
     |- php/
         |- 5.6/
              |- php-5.6.14.tar.gz


ではこのビルドパックを実際に使ってみます。が、そのためにはこのビルドパックをインターネット上の Git リポジトリに公開する必要があります。普段お使いの環境にオリジナルの Git 環境があればそこを使ってもいいのですが、今回は GitHub 上に公開しましょう。GitHub のアカウントを取得できていない場合は取得して、ログインまでを済ませておきます:
2015101002


画面右上の "+" 印をクリックし、"New repository" を選択して、新しいソースリポジトリを作成します:
2015101003


リポジトリの名前、説明(オプション)、そして Public リポジトリか Private リポジトリかを選択します。名前は何でもいいのですが、わかりやすいように "php-apache-buildpack" としました。説明はオプションで加えます。GitHub の有料アカウントであれば Private リポジトリを選ぶこともできますが、せっかくなので(というか、この後の話がややこしくならないように)Public を選択して公開しちゃいましょう。最後に "Create Repository" ボタンをクリックします:
2015101004


するとこんな感じの画面になり、ソースリポジトリが新規に追加できました。この時の URL (https://github.com/(ユーザー名)/(リポジトリ名)) を後で使うのでメモしておいてください。今はまだ中身が空ですが、ここに先程作ったビルドパックを転送します:
2015101005


改めて作業環境に戻ります。ここからは git クライアントによる作業になるため、git が必要です。git コマンド未導入の場合はコマンドラインで以下のように入力して git をインストールしておきます:
$ sudo apt-get install git

そしてビルドパックを作成したディレクトリ(/tmp/buildpack)に移動して、以下のコマンドを入力し、上記で作成した GitHub 上のリポジトリに転送します:
$ cd /tmp/buildpack
$ git init
$ git add .
$ git commit -m 'first commit'
$ git remote add origin https://github.com/****(先程メモしたリポジトリのURL)****.git
$ git push -u origin master
(GitHub 上のユーザー名を入力)
(GitHub のパスワードを入力)

転送完了後、改めてリポジトリの URL にブラウザでアクセス(まだ開いていればリロード)すると、作成したビルドパックが転送され、中身が入ったリポジトリになっているはずです。これでビルドパックの公開もできました:
2015101006



では最後にこのビルドパックを使って、実際に Bluemix 上にランタイムを1つ構築してみます。cf ツールをインストールしたマシンのあるディレクトリに index.php という名前で、以下のような phpinfo(); を実行するだけの内容のファイルを作成します:
<?php phpinfo(); ?>

また Bluemix 上にランタイムを1つ作ります。言語は(この後に変えるので)何を指定しても構いません。この例では dotnsf-php-20151010 という名前で作成していますが、実際には一意になるような名前を指定してください:
2015101001


そしてこの index.php ファイルが存在しているディレクトリから cf ツールで Bluemix 上にログインし、作成したビルドパックを指定してこのランタイムにプッシュします:
> cf login -a https://api.ng.bluemix.net/
(Bluemix のユーザー名を指定)
(パスワードを指定)

> cf push dotnsf-php-20151010 -b https://github.com/dotnsf/php-apache-buildpack.git
   :
   :
#0   running   2015-10-10 08:37:34 PM   0.2%   61.9M of 128M   163.5M of 1G


プッシュが成功したら、実際にこのランタイムの URL にアクセスして、phpinfo() の結果が表示されることを確認します。ちゃんと PHP のアプリケーションサーバーとして動いていることが確認できました:
2015101002


この中身をよく見ると、ビルドパックを作成した際に指定した内容で稼働していることが確認できます。というわけで元の(Bluemix の)PHP ランタイム環境ではなく、カスタマイズして作成した PHP ランタイムが動いていることも分かります:
2015101003


長い連載になりましたが、これで Bluemix のビルドパックを作って、公開して、実際に使ってみる所までが確認できました。PHP 以外のビルドパックを作る場合も、(権限の問題がないものであれば)この応用で作れると思います。是非色々チャレンジしていただけると嬉しいです。

個人的にご縁のある IDCF 様がゴールデンウィークにクラウドを使った面白い企画をやっていました:
抽選でスターバックスギフトカードプレゼント【IDCFからの宿題第2弾】

IDCF 様のクラウド環境を使って、git のサーバーである GitLab 環境を構築してみよう、というものです。GitLab は GitHub のサーバーを自分専用に作るような環境で、特に Community Edition は無料のオープンソースで提供されています。導入も非常に簡単で 22/80 番ポートの開いたサーバーがあれば数分で専用 GitHub が構築できる、というものです。 そして IDCF 様の企画では同環境を IDCF クラウド上に作成して、その活用方法を含めてブログにまとめると抽選でスタバのギフトカードがもらえる、というものです。興味ある方はこの週末にチャレンジしてみましょう!


で、自分はスタバカードにも興味はありますが、ちょっとだけ(?)脱線して、同じ環境を IBM Bluemix 上で作ってみることにしました。 完全な悪ノリです、はい。まあでも仮想マシン起動後の作業は共通ということで・・・ (^^;

なお、GitLab CE(Community Edition) 環境の具体的な構築方法はこちらを参照ください。以下は基本的にこの手順をそのまま実行しています:
Download GitLab Community Edition(CE)


まず GitLab を導入するには SSH でログインできるサーバーが必要です。というわけで Bluemix の OpenStack VM 機能を使って CentOS の仮想マシンを1つ作成します。バージョンは個人的に慣れている 6.5 で。この辺りの手順はこちらを参照ください:
Bluemix 上で OpenStack VM インスタンスを作成する


ちなみに GitLab の推奨環境としては 2CPU + 2GB メモリですが、100 ユーザー程度であれば 1CPU + 1GB メモリ + 1GB スワップメモリでも OK とのこと。Bluemix の仮想マシンは現時点で最小スペックの m1.small でも 1CPU + 2GB メモリ + 2GB スワップメモリなので、前提条件としては充分だと思います:
2015050801


仮想マシンが立ち上がったら Bluemix かどうかを意識する必要はありません。まず SSH でログインし、とりあえず root で yum update しておきます:
# yum update

最初に必要な依存ライブラリをまとめて導入&起動しておきます:
# yum install openssh-server postfix cronie git
# /etc/init.d/postfix start
# chkconfig postfix on
# lokkit -s http -s ssh

次に GitLab 本体をダウンロードしてインストールし、起動します:
# curl -O https://downloads-packages.s3.amazonaws.com/centos-6.6/gitlab-ce-7.10.1~omnibus.2-1.x86_64.rpm
# rpm -ivh gitlab-ce-7.10.1~omnibus.2-1.x86_64.rpm
# vi /etc/gitlab/gitlab.rg (external_url の値を自分自身のIPアドレスに変更)
# gitlab-ctl reconfigure
2015050802


最後にこのサーバーにブラウザでアクセスして、ユーザーID(root) と初期パスワード(5iveL!fe)を指定してログインします:
2015050803


初回ログイン時には初期パスワードを変更するよう指示されます。自分専用のパスワードに変更します:
2015050804


一度、強制ログアウトされるので再度 root ユーザーと新しいパスワードでログインするとウェルカム画面が表示されます。これで GitLab が使える環境が整ったことになります!
2015050805


あとはリポジトリの管理単位となるプロジェクトを作り(10,000個まで作れるらしい)、ユーザーのグループを作って、プロジェクト毎のアクセス権を柔軟に制御することもできます。

新規にユーザーを登録すると、メール認証が必要になります。となるとメールサーバーを用意/設定する必要があります。それが面倒な場合は以下の設定を加えて、ユーザー登録と同時にメール認証が済んだことにすることもできます:
# vi /opt/gitlab/embedded/service/gitlab-rails/app/modules/user.rb

(以下の行を追加)
  default_value_for :confirmed_at, Time.now


この設定後にユーザーを登録すると、同時にメール認証までは終わったことになります。ただその時点ではまだパスワードが設定されていないのでログインできません。管理者がユーザーを登録後に初期パスワードを設定してあげる必要があることに注意してください。

(参考)
ユーザを登録する


また、環境によっては GitLab が使う git ユーザーの ssh アクセスを許可していない可能性もあります。その場合は以下の2つの設定をしておくとアクセス制限を解除できます:
# vi /etc/shadow

git:!!:16569::::::
  ↓
git:*:16569:::::: (パスワードを設定していないユーザーの SSH ログインを許可する)
# vi /etc/ssh/sshd_config

AllowUsers xxxx yyyy git (AllowUsers に半角スペース区切りで git を追加)

# service sshd reload

もちろん github を使っている状況で無理に GitLab 環境に移行する必要はありませんが、ソースコードを自前環境で管理したい場合や、必ずしも公開したくないソースコードを管理したい場合などに GitLab は非常に簡単で便利だと思いました。


このページのトップヘ