dockerと継続的インテグレーション

35
Docker と継続的インテグレーション 14/02/12 Docker Meetup in Tokyo #1

Upload: yahoo

Post on 15-Jan-2015

9.244 views

Category:

Technology


4 download

DESCRIPTION

2014/02/12 Docker Meetup in Tokyo #1 での発表内容です。 デモコード: https://github.com/ydnjp/docker-continuous-integration-workflow

TRANSCRIPT

Page 1: Dockerと継続的インテグレーション

Docker と継続的インテグレーション

14/02/12 Docker Meetup in Tokyo #1

Page 2: Dockerと継続的インテグレーション

Kazuki Suda! @superbrothers

" github.com/superbrothers

Page 3: Dockerと継続的インテグレーション
Page 4: Dockerと継続的インテグレーション

Docker での ビルド -> テスト -> プッシュの自動化

# 本日のお話

Page 5: Dockerと継続的インテグレーション

# アジェンダ

- CI ワークフロー 構成編

- Dockerfile のテスト

- ベースとなるイメージの実装

- テストの準備と実行

- CI ワークフロー ジョブスクリプト編

- デモ

- まとめ

Page 6: Dockerと継続的インテグレーション

# デモコードあります

https://github.com/ydnjp/ docker-continuous-integration-workflow

Page 7: Dockerと継続的インテグレーション

# CI ワークフロー 登場人物編 !

ビルド -> テスト -> プッシュの自動化

Page 8: Dockerと継続的インテグレーション

## 登場人物

#

$Git リポジトリ

Jenkins

Docker 入りスレーブ

Docker レジストリ

Page 9: Dockerと継続的インテグレーション

## ワークフロー

ビルド テスト プッシュ

docker build serverspec docker push

Page 10: Dockerと継続的インテグレーション

# Dockerfile のテスト

Page 11: Dockerと継続的インテグレーション
Page 12: Dockerと継続的インテグレーション

├──Gemfile ├──Gemfile.lock ├──Rakefile ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh └──spec ├──base │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb

## ディレクトリ構造

Page 13: Dockerと継続的インテグレーション

├──Gemfile ├──Gemfile.lock ├──Rakefile ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh └──spec ├──base │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb

dockerfiles/<image-name> で Dockerfile を配置する

base イメージ

jenkins イメージ

## Dockerfile の配置

Page 14: Dockerと継続的インテグレーション

├──Gemfile ├──Gemfile.lock ├──Rakefile ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh └──spec ├──base │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb

spec/<image-name> で スペックを配置する

dockerfiles 以下に 対応する形です

## spec の配置

Page 15: Dockerと継続的インテグレーション

├──Gemfile ├──Gemfile.lock ├──Rakefile ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh └──spec ├──base │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb

serverspec は ssh を通して コンテナとやりとりするので

sshd 入りのベースとする イメージを用意します

(base イメージ)

ssh ログインに使う ノーパスキーです

Page 16: Dockerと継続的インテグレーション

FROM ubuntu:13.10 !ENV DEBIAN_FRONTEND noninteractive !RUN apt-get -q update && apt-get -y upgrade !# Install openssh-server for serverspec RUN apt-get -q -y install openssh-server && apt-get clean RUN mkdir /var/run/sshd RUN mkdir /root/.ssh && chmod 600 /root/.ssh ADD keys/id_rsa.pub /root/.ssh/authorized_keys RUN chown root:root /root/.ssh/authorized_keys !# Ubuntu 13.10 additional steps for SSHD Service RUN sed -i 's/.*session.*required.*pam_loginuid.so.*/session optional pam_loginuid.so/g' /etc/pam.d/sshd RUN echo LANG="en_US.UTF-8" > /etc/default/locale

dockerfiles/base/Dockerfile

ノーパスの 公開鍵を追加

sshd をインストール

Page 17: Dockerと継続的インテグレーション

## ベースイメージのビルドとコンテナの起動

% docker build -t base dockerfiles/base !% docker run -d -p 22 base /usr/sbin/sshd -D

22番ポートが bind されたポートを指定して ノーパスキーの秘密鍵を使うとログインできる

Page 18: Dockerと継続的インテグレーション

- ノーパスキーを利用しよう

- root にパスワードを設定しちゃダメ!

## ベースイメージのポイント

Page 19: Dockerと継続的インテグレーション

# serverspec を使ったテストの準備と実行

Page 20: Dockerと継続的インテグレーション

## serverspec を使ったテスト実行の流れ

1. イメージからコンテナを起動する

- CMD /usr/sbin/sshd -D

- 22番ポートを bind する

2. bind されたポートに対して SSH を使って spec を流し込む

- ノーパスの秘密鍵を使います

- bind されたポートは inspect で取得

- 1 -> 2 を最後まで繰り返す

3. 利用したコンテナを殺して削除する

Page 21: Dockerと継続的インテグレーション

c.before :all do (略)… host = File.basename(Pathname.new(file).dirname) ! if c.host != host ## Start container and retrieve port number of sshd container = Docker::Container.create( :Image => "#{host}", :Entrypoint => ['/usr/sbin/sshd'], :Cmd => ['-D'], :ExposedPorts => {'22/tcp' => {}}, :User => 'root' ).start( :PortBindings => { '22/tcp' => [{:HostIp =>‘127.0.0.1’}] } ) sleep 1 containers << container

spec/spec_helper.rb (前編)

Docker イメージごとにコンテナを起動

sshd を起動させる

使ったコンテナはあとで 停止、削除するのでとっておく

コンテナの22番ポートを 親のホストに bind

docker-api 使ってます

Page 22: Dockerと継続的インテグレーション

c.ssh.close if c.ssh c.host = host options = { :keys => [File.expand_path('../../dockerfiles/base/keys/id_rsa', __FILE__)], :port => container.json['HostConfig']['PortBindings']['22/tcp'][0]['HostPort'] } c.ssh = Net::SSH.start('0.0.0.0', 'root', options) end end ! c.after(:suite) do ## Kill and delete containers containers.each {|container| container.kill.delete } end

spec/spec_helper.rb (後編)

base イメージに追加した公開鍵と 対の秘密鍵を使う

利用したコンテナを 殺して削除する

HostConfig から bind されたポートを 取得する

接続先はローカルホストで root ユーザ

Page 23: Dockerと継続的インテグレーション

require 'spec_helper' !describe package('openssh-server') do it { should be_installed } end !describe file('/var/run/sshd') do it { should be_directory } end !describe file('/root/.ssh') do it { should be_directory } it { should be_mode 600 } end

spec/base/sshd_spec.rb

ディレクトリが存在するか

パッケージが正しく インストールされているか

ディレクトリが存在するかパーミッションが正しいか

spec の記述については serverspec 公式の ドキュメントを確認してください

Page 24: Dockerと継続的インテグレーション

## テストの実行

$ bundle exec rake spec /usr/bin/ruby1.9.1 -S rspec spec/base/sshd_spec.rb ......... !Finished in 2.21 seconds 9 examples, 0 failures

Page 25: Dockerと継続的インテグレーション

ベースとなるイメージの実装が終わったので 本来必要なイメージを

実装する準備が整いました(長い)

例として jenkins イメージを作ります(ここからは早送り

Page 26: Dockerと継続的インテグレーション

├──Gemfile ├──Gemfile.lock ├──Rakefile ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh └──spec ├──base │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb

## jenkins イメージ

Dockerfile はここ

spec はこちら

Page 27: Dockerと継続的インテグレーション

FROM base !RUN apt-get -q -y install openjdk-7-jre-headless && apt-get clean !# Install Jenkins RUN mkdir /opt/jenkins …

dockerfiles/jenkins/Dockerfile

jenkins のセットアップ(略)

base をベースとするので、sshd 入り

spec の実装は省略します

FROM base としているので、そのままで sshd を起動したコンテナを起動させることができます

!あとは spec を実装したら完了です

(spec を先に実装することで TDD もできちゃう)

Page 28: Dockerと継続的インテグレーション

# docker build, push の Rake タスク化 !

繰り返し行うことはタスクにまとめましょう

Page 29: Dockerと継続的インテグレーション

## docker build

% bundle exec rake docker:builddocker build -t base dockerfiles/base (略)...

## docker push

イメージが base に依存しているので、 base から順番にビルドする

% bundle exec rake docker:push docker tag base 0.0.0.0:5000/base docker push 0.0.0.0:5000/base (略)...

docker tag でプライベートレジストリの情報を付けたのち、 順番に push する

実装はデモコードの Rakefile を参照してください!

Page 30: Dockerと継続的インテグレーション

# CI ワークフロー ジョブスクリプト編 !

ビルド -> テスト -> プッシュの自動化

Page 31: Dockerと継続的インテグレーション

## ジョブスクリプト

ベースは出来ているのでこれだけです。

Page 32: Dockerと継続的インテグレーション

デモ

Page 33: Dockerと継続的インテグレーション

## まとめ

- ビルド、テスト、プッシュの自動化ができました

- 毎日自動でまわすことで常に最新のセキュリティアップデートを当て続けることもできます

!

次は継続的デリバリーに向けて?

Page 34: Dockerと継続的インテグレーション

# デモコードあります (再掲)

https://github.com/ydnjp/ docker-continuous-integration-workflow

Page 35: Dockerと継続的インテグレーション

ありがとうございました