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

11,719 views
11,433 views

Published on

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

Published in: Technology
0 Comments
78 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,719
On SlideShare
0
From Embeds
0
Number of Embeds
867
Actions
Shares
0
Downloads
117
Comments
0
Likes
78
Embeds 0
No embeds

No notes for slide

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

  1. 1. Docker と継続的インテグレーション 14/02/12 Docker Meetup in Tokyo #1
  2. 2. Kazuki Suda ! @superbrothers " github.com/superbrothers
  3. 3. # 本日のお話 Docker での ビルド -> テスト -> プッシュの自動化
  4. 4. # アジェンダ - CI ワークフロー 構成編 - Dockerfile のテスト - ベースとなるイメージの実装 - テストの準備と実行 - CI ワークフロー ジョブスクリプト編 - デモ - まとめ
  5. 5. # デモコードあります https://github.com/ydnjp/ docker-continuous-integration-workflow
  6. 6. # CI ワークフロー 登場人物編 ! ビルド -> テスト -> プッシュの自動化
  7. 7. ## 登場人物 Jenkins Docker レジストリ # $ Git リポジトリ Docker 入りスレーブ
  8. 8. ## ワークフロー ビルド テスト プッシュ docker build serverspec docker push
  9. 9. # Dockerfile のテスト
  10. 10. ## ディレクトリ構造 ├──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
  11. 11. ## Dockerfile の配置 ├──Gemfile dockerfiles/<image-name> で ├──Gemfile.lock Dockerfile を配置する ├──Rakefile ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub base イメージ │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh └──spec ├──base jenkins イメージ │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb
  12. 12. ## spec の配置 ├──Gemfile spec/<image-name> で ├──Gemfile.lock ├──Rakefile スペックを配置する ├──dockerfiles │ ├──base │ │ ├──Dockerfile │ │ └──keys │ │ ├──id_rsa │ │ └──id_rsa.pub │ └──jenkins │ ├──Dockerfile │ └──start-jenkins.sh dockerfiles 以下に └──spec ├──base 対応する形です │ └──sshd_spec.rb ├──jenkins │ └──jenkins_spec.rb └──spec_helper.rb
  13. 13. serverspec は ssh を通して コンテナとやりとりするので sshd 入りのベースとする イメージを用意します (base イメージ) ├──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 ssh ログインに使う ノーパスキーです
  14. 14. dockerfiles/base/Dockerfile FROM ubuntu:13.10 ! ENV DEBIAN_FRONTEND noninteractive ! RUN apt-get -q update && apt-get -y upgrade ! # Install openssh-server for serverspec sshd をインストール 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
  15. 15. ## ベースイメージのビルドとコンテナの起動 % docker build -t base dockerfiles/base ! % docker run -d -p 22 base /usr/sbin/sshd -D 22番ポートが bind されたポートを指定して ノーパスキーの秘密鍵を使うとログインできる
  16. 16. ## ベースイメージのポイント - ノーパスキーを利用しよう - root にパスワードを設定しちゃダメ!
  17. 17. # serverspec を使ったテストの準備と実行
  18. 18. ## serverspec を使ったテスト実行の流れ 1. イメージからコンテナを起動する - CMD /usr/sbin/sshd -D - 22番ポートを bind する 2. bind されたポートに対して SSH を使って spec を流し込む - ノーパスの秘密鍵を使います - bind されたポートは inspect で取得 - 1 -> 2 を最後まで繰り返す 3. 利用したコンテナを殺して削除する
  19. 19. spec/spec_helper.rb (前編) c.before :all do (略)… host = File.basename(Pathname.new(file).dirname) ! if c.host != host Docker イメージごとにコンテナを起動 ## Start container and retrieve port number of sshd container = Docker::Container.create( docker-api 使ってます :Image => "#{host}", :Entrypoint => ['/usr/sbin/sshd'], :Cmd => ['-D'], sshd を起動させる :ExposedPorts => {'22/tcp' => {}}, :User => 'root' ).start( :PortBindings => { コンテナの22番ポートを 親のホストに bind '22/tcp' => [{:HostIp =>‘127.0.0.1’}] } ) 使ったコンテナはあとで sleep 1 停止、削除するのでとっておく containers << container
  20. 20. spec/spec_helper.rb (後編) c.ssh.close if c.ssh base イメージに追加した公開鍵と c.host = host 対の秘密鍵を使う options = { :keys => [File.expand_path('../../dockerfiles/base/keys/id_rsa', __FILE__)], :port => container.json['HostConfig']['PortBindings']['22/tcp'][0] ['HostPort'] HostConfig から bind されたポートを } 取得する c.ssh = Net::SSH.start('0.0.0.0', 'root', options) end 接続先はローカルホストで root ユーザ end ! c.after(:suite) do 利用したコンテナを ## Kill and delete containers 殺して削除する containers.each {|container| container.kill.delete } end
  21. 21. spec/base/sshd_spec.rb 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 の記述については serverspec 公式の ドキュメントを確認してください
  22. 22. ## テストの実行 $ 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
  23. 23. ベースとなるイメージの実装が終わったので 本来必要なイメージを 実装する準備が整いました(長い) 例として jenkins イメージを作ります
 (ここからは早送り
  24. 24. ## jenkins イメージ ├──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 Dockerfile はここ spec はこちら
  25. 25. dockerfiles/jenkins/Dockerfile FROM base base をベースとするので、sshd 入り ! RUN apt-get -q -y install openjdk-7-jre-headless && apt-get clean ! # Install Jenkins jenkins のセットアップ(略) RUN mkdir /opt/jenkins … FROM base としているので、そのままで sshd を起動したコンテナを起動させることができます ! あとは spec を実装したら完了です (spec を先に実装することで TDD もできちゃう) spec の実装は省略します
  26. 26. # docker build, push の Rake タスク化 ! 繰り返し行うことはタスクにまとめましょう
  27. 27. ## docker build イメージが base に依存しているので、 base から順番にビルドする % bundle exec rake docker:build
 docker build -t base dockerfiles/base (略)... ## docker push docker tag でプライベートレジストリの情報を付けたのち、 順番に push する % bundle exec rake docker:push docker tag base 0.0.0.0:5000/base docker push 0.0.0.0:5000/base (略)... 実装はデモコードの Rakefile を参照してください!
  28. 28. # CI ワークフロー ジョブスクリプト編 ! ビルド -> テスト -> プッシュの自動化
  29. 29. ## ジョブスクリプト ベースは出来ているのでこれだけです。
  30. 30. デモ
  31. 31. ## まとめ - ビルド、テスト、プッシュの自動化ができました - 毎日自動でまわすことで常に最新のセキュリティ アップデートを当て続けることもできます ! 次は継続的デリバリーに向けて?
  32. 32. # デモコードあります (再掲) https://github.com/ydnjp/ docker-continuous-integration-workflow
  33. 33. ありがとうございました

×