はじめに
ここまで自分が投稿した記事を使って、下記が作れるようになりました。
これらを利用して、private Docker Hub を作ってみます。
今回作成する private Docker Hub の仕組み
- ローカルで作成したDockerfileをGitLabにpush
- GitLabからWebHookでJenkinsに通知
- JenkinsにてDockerfileをビルド
- Jenkinsはdockerコンテナで起動している
- Jenkinsコンテナ内でDockerfileをビルドしているわけではない
- ホストのdockerAPI(docker-py経由)を利用している
- docker build
- 成功した場合、private registryにpush
- 失敗した場合、Gmailに通知を行う
環境
- OS: Ubuntu14.04
- docker version: 1.4.1
- /etc/default/dockerにこちらの設定を行う
- 上記ホストを2台用意
下記のような構成を目指します。(全てdockerコンテナです。)
- ホストA
- private dockcer registry
- private dockcer registry(Web UI)
- ホストB
- GitLab
- Jenkins
ローカルGitリポジトリは下記のような構成にすること
- ubuntu1404_test
- Dockerfile
- hoge
- Dockerfile
- fuga
- Dockerfile
設定(ホストA)
private dockcer registry
下記を参考にregistryコンテナを用意します。
$ sudo docker ps
IMAGE PORTS
konradkleine/docker-registry-frontend:latest 443/tcp, 0.0.0.0:8080->80/tcp
registry:latest 0.0.0.0:5000->5000/tcp
※CONTAINER IDなどは省略
設定(ホストB)
GitLab 初期設定
下記を参考にGitLabコンテナを用意します。
$ sudo docker ps
IMAGE PORTS NAMES
sameersbn/gitlab:latest 443/tcp, 0.0.0.0:10022->22/tcp, 0.0.0.0:10080->80/tcp hungry_ardinghelli
sameersbn/mysql:latest 3306/tcp gitlab-mysql
sameersbn/redis:latest 6379/tcp gitlab-redis
※CONTAINER IDなどは省略
GitLabにログイン後、プロジェクトを作成し、ローカルと連携します。
なお、ubuntu1404_testディレクトリの中には簡単なDockerfileが入っています。
※ディレクトリ名をイメージタグに使用するので、重複などしないように注意して下さい。
Jenkins 初期設定
下記を参考にしつつ、必要なモジュールを追加したJenkinsコンテナを用意します。
$ sudo git clone https://github.com/doragon/Dockerfile.git
$ sudo mv Dockerfile/debian/8.0/jenkins/ ./
$ sudo rm -rf Dockerfile
$ cd jenkins/
$ mkdir jenkins_home
$ chmod 777 jenkins_home
$ sudo docker build -t koide/jenkins .
$ sudo docker run -p 28080:8080 -d \
-v [PATH]/jenkins/jenkins_home:/var/jenkins_home \
-v [PATH]/jenkins/workspace:/var/workspace \
koide/jenkins
$ sudo docker ps
IMAGE PORTS
koide/jenkins:latest 50000/tcp, 0.0.0.0:28080->8080/tcp
ここで、GitLabと連携を行うため、jenkinsユーザーの個別設定を行います。
※本来ならDockerfileで完結すべきなのですが、rootユーザー以外での権限設定がうまくいかないためコンテナ内で作業を行います。
$ sudo docker exec -it 3fbc958b8006 bash
jenkins@3fbc958b8006:/$
jenkins@3fbc958b8006:/$ cd
jenkins@3fbc958b8006:~$ pwd
/var/jenkins_home
jenkins@3fbc958b8006:~$ mkdir .ssh
jenkins@3fbc958b8006:~$ cd .ssh
jenkins@3fbc958b8006:~/.ssh$ ssh-keygen -t rsa -f id_rsa -C "jenkins@test.com" -N ""
jenkins@3fbc958b8006:~/.ssh$ chmod 744 $HOME/.ssh
jenkins@3fbc958b8006:~/.ssh$ chmod 700 $HOME/.ssh/id_rsa
jenkins@3fbc958b8006:~/.ssh$ vim config
Host [GITLAB_ON_DOCKER_HOST]
User git
Hostname [GITLAB_ON_DOCKER_HOST]
Port [DOCKER_HOST_PORT_MAPPED_GITLAB_PORT_22]
IdentityFile ~/.ssh/id_rsa
※[GITLAB_ON_DOCKER_HOST]、[DOCKER_HOST_PORT_MAPPED_GITLAB_PORT_22]は適宜修正して下さい。
※[DOCKER_HOST_PORT_MAPPED_GITLAB_PORT_22]はここでは10022です。(上述のGitLabコンテナ作成時を参照)
後ほど、GitLabに登録するため、id_rsa.pubを控えておきます。
jenkins@3fbc958b8006:~/.ssh$ cat id_rsa.pub
jenkins@3fbc958b8006:~/.ssh$ git config --global user.email "jenkins@test.com"
jenkins@3fbc958b8006:~/.ssh$ git config --global user.name "jenkins"
ここまでで、Jenkinsコンテナ内での作業は終わりです。
次にJenkinsのWebUIにて、必要なプラグインをインストールします。
Jenkinsの管理 ⇒ プラグインの管理 ⇒ 利用可能
から「Gitlab Hook Plugin」をインストールします。
GitLab へ Jenkins ユーザーを追加
GitLabにAdmin権限を持つユーザーでログインします。
Admin area ⇒ New user
からjenkinsユーザーを作成します。
※パスワードはユーザー作成後に、編集できます。
次に、Admin権限を持つユーザーをログアウトして、作成したjenkinsユーザーでログインします。
Profile settings ⇒ SSH Keys ⇒ Add SSH Key
を選択し、先ほどjenkinsコンテナ内で生成したid_rsa.pubを設定して下さい。
再度、ログアウトをし、Dockerfile_CIプロジェクトを作成したユーザーでログインします。
ProjectのSettings ⇒ Members ⇒ New project member
を選択し、jenkinsユーザーを追加します。
続いて、jenkinsへのweb hook設定を行います。
ProjectのSettings ⇒ Web Hooks
http://[JENKINS_ON_DOCKER_HOST]:[DOCKER_HOST_PORT_MAPPED_JENKINS_PORT_8080]/job/Dockerfile_CI/build?delay=0sec
※[JENKINS_ON_DOCKER_HOST]:[DOCKER_HOST_PORT_MAPPED_JENKINS_PORT_8080]は適宜修正して下さい。
※[DOCKER_HOST_PORT_MAPPED_JENKINS_PORT_8080]はここでは28080です。(上述のJenkinsコンテナ作成時を参照)
Jenkins にてジョブの作成
新規ジョブ作成 ⇒ フリースタイル・プロジェクトのビルド
を選択します。(ジョブ名は何でも構いません。)
ソースコード管理 ⇒ Git ⇒ Repositories ⇒ Credentials ⇒ Add
を選択し、ユーザー名jenkinsを作成します。
Repository URLにはGitLabプロジェクトのSSHを入力して下さい。
なお、ここでは[DOCKER_HOST]を書いているため、エラーを出力していますが、正しいGitLabプロジェクトのSSHを入力することで、このエラーは出力されなくなります。
最後に
ビルド・トリガ ⇒ SCMをポーリング にチェック
ビルド ⇒ シェルの実行
BASEURL='tcp://[DOCKER_HOST_B]:4243'
VERSION='1.12'
PATH=`pwd`
REGISTRY='[DOCKER_HOST_A]:5000'
for f in *; do
if test $f = "README.md" ; then
continue
fi
WORKPATH=$PATH/$f
echo $WORKPATH
TAG='jenkins/'$f
echo $TAG
/usr/bin/python /var/workspace/dockerclient.py $WORKPATH $TAG $REGISTRY $BASEURL $VERSION
done
通知の設定
このままではビルド失敗時に何も通知されません。
今回はGmailを利用した通知の設定を行います。
Jenkinsの管理 ⇒ システムの設定 ⇒ Jenkinsの位置 ⇒ システム管理者のメールアドレス
- システム管理者のメールアドレス: xxx@gmail.com
Jenkinsの管理 ⇒ システムの設定 ⇒ E-mail 通知
- SMTPサーバー: smtp.gmail.com
- SMTP認証にチェック
- ユーザー名: xxx@gmail.com
- パスワード: xxxxxx
- SSLにチェック
- SMTPポート: 465
- 文字セット: UTF-8
上記を設定し、保存します。続いて、
ジョブを選択 ⇒ 設定 ⇒ ビルド後の処理 ⇒ E-mail通知
これで設定は全て終了です。
CIの流れ(例)
- ローカルでDockerfileを修正する
- GitLabへpushする
- Jenkinsでビルド結果の確認
- private docker registryにpushされているか確認
build失敗時は次のようになる。
補足
Web Hookの部分はJenkinsのビルド実行をそのまま叩いていますが、下記のような設定方法もあります。
http://[JENKINS_ON_DOCKER_HOST]:[DOCKER_HOST_PORT_MAPPED_JENKINS_PORT_8080]/gitlab/build_now
元々こちらを使用するつもりでしたが、ポートの指定が異なるためか、うまくWebHookが通らないので、今回は避けました。
今後の課題
今回の実装では、confファイルなどを考慮していません。
そのため、Dockerfileと同階層に別のファイルがあった場合、おそらくエラーになります。(未確認)
解決策はdockerclient.py内へ設定ファイル込みのbuildを記述することと、Jenkinsシェルの設定を追記することですが、そちらはまだ未実装です。
おわりに
少し長くなってしまいましたが、最後までお読み頂き、ありがとうございました。