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

  • 9,110 views
Uploaded on

2014/02/12 Docker Meetup in Tokyo #1 での発表内容です。 …

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
9,110
On Slideshare
0
From Embeds
0
Number of Embeds
9

Actions

Shares
Downloads
103
Comments
0
Likes
72

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Docker と継続的インテグレーション 14/02/12 Docker Meetup in Tokyo #1
  • 2. Kazuki Suda ! @superbrothers " github.com/superbrothers
  • 3. # 本日のお話 Docker での ビルド -> テスト -> プッシュの自動化
  • 4. # アジェンダ - CI ワークフロー 構成編 - Dockerfile のテスト - ベースとなるイメージの実装 - テストの準備と実行 - CI ワークフロー ジョブスクリプト編 - デモ - まとめ
  • 5. # デモコードあります https://github.com/ydnjp/ docker-continuous-integration-workflow
  • 6. # CI ワークフロー 登場人物編 ! ビルド -> テスト -> プッシュの自動化
  • 7. ## 登場人物 Jenkins Docker レジストリ # $ Git リポジトリ Docker 入りスレーブ
  • 8. ## ワークフロー ビルド テスト プッシュ docker build serverspec docker push
  • 9. # Dockerfile のテスト
  • 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. ## 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. ## 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. 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. 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. ## ベースイメージのビルドとコンテナの起動 % docker build -t base dockerfiles/base ! % docker run -d -p 22 base /usr/sbin/sshd -D 22番ポートが bind されたポートを指定して ノーパスキーの秘密鍵を使うとログインできる
  • 16. ## ベースイメージのポイント - ノーパスキーを利用しよう - root にパスワードを設定しちゃダメ!
  • 17. # serverspec を使ったテストの準備と実行
  • 18. ## serverspec を使ったテスト実行の流れ 1. イメージからコンテナを起動する - CMD /usr/sbin/sshd -D - 22番ポートを bind する 2. bind されたポートに対して SSH を使って spec を流し込む - ノーパスの秘密鍵を使います - bind されたポートは inspect で取得 - 1 -> 2 を最後まで繰り返す 3. 利用したコンテナを殺して削除する
  • 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. 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. 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. ## テストの実行 $ 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. ベースとなるイメージの実装が終わったので 本来必要なイメージを 実装する準備が整いました(長い) 例として jenkins イメージを作ります
 (ここからは早送り
  • 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. 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. # docker build, push の Rake タスク化 ! 繰り返し行うことはタスクにまとめましょう
  • 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. # CI ワークフロー ジョブスクリプト編 ! ビルド -> テスト -> プッシュの自動化
  • 29. ## ジョブスクリプト ベースは出来ているのでこれだけです。
  • 30. デモ
  • 31. ## まとめ - ビルド、テスト、プッシュの自動化ができました - 毎日自動でまわすことで常に最新のセキュリティ アップデートを当て続けることもできます ! 次は継続的デリバリーに向けて?
  • 32. # デモコードあります (再掲) https://github.com/ydnjp/ docker-continuous-integration-workflow
  • 33. ありがとうございました