SlideShare a Scribd company logo
Dockerイメージ構築
実践テクニック
Haruka Iwao
Storage Solution Architect, Red Hat K.K.
February 12, 2015
自己紹介
•  岩尾 はるか (@Yuryu)
•  所属: レッドハット株式会社
– ストレージソリューションアーキテクト
– 大手家電メーカー、ソーシャルゲーム会社、
Web広告ベンチャーを経て現職
•  大学・大学院で高性能計算(HPC)、分散
ファイルシステムを研究
•  ゲーマーです(主に某国産MMORPG)
Dockerイメージの構造
RHEL
nginx
Webサーバー
OSの基本
ファイル
OSの基本
ファイル
OSの基本
ファイル
nginx
nginx
HTML
ファイル
追加
追加
nginxイメージを元に作成
RHELイメージを元に作成
実体は共有
新規
Dockerイメージの作成手順
•  2ステップで作成できます
•  Dockerfile の作成
•  $ docker build -t <tag> Dockerfileの場所
– 例) $ docker build -t yuryu/test .
Dockerfileとは
•  イメージ作成の手順を書いたもの
•  例)
FROM	
  registry.access.redhat.com/rhel	
  
	
  
RUN	
  yum	
  -­‐y	
  install	
  httpd	
  
ADD	
  index.html	
  /var/www/html/index.html	
  
	
  
EXPOSE	
  80	
  
	
  
CMD	
  ["/usr/sbin/httpd",	
  "-­‐DFOREGROUND"]	
  
Dockerfile 文法
•  FROM - ベースとなるイメージ
•  RUN - イメージ構築で実行するコマンド
•  ADD - イメージ内にファイルを追加
•  EXPOSE - ポートを外に見せる
•  CMD - デフォルトで実行されるコマンド
FROM	
  registry.access.redhat.com/rhel	
  
	
  
RUN	
  yum	
  -­‐y	
  install	
  httpd	
  
ADD	
  index.html	
  /var/www/html/index.html	
  
	
  
EXPOSE	
  80	
  
	
  
CMD	
  ["/usr/sbin/httpd",	
  "-­‐DFOREGROUND"]	
  
Dockerfile 文法(2)
•  MAINTAINER - メンテナを書く
•  USER - コンテナ内で実行するユーザー
•  WORKDIR - 基準ディレクトリの変更
•  COPY - ホストからファイルのコピー
– ADD が大きすぎるので分割
•  その他リファレンスは下記
– https://docs.docker.com/reference/
builder/	
  
作って動かす
•  $ docker run で実行
– -d バックグラウンドで実行
– -P EXPOSE したポートを割り当て
$	
  mkdir	
  demo-­‐apache	
  
$	
  cd	
  demo-­‐apache	
  
$	
  curl	
  -­‐L	
  -­‐o	
  Dockerfile	
  bit.ly/1FA902p	
  
$	
  echo	
  “Hello,	
  Docker!”	
  >	
  index.html	
  
$	
  build	
  -­‐t	
  demo-­‐apache	
  .	
  
	
  
$	
  docker	
  run	
  -­‐dP	
  demo-­‐apache	
  
docker build 実行例
[yuryu@rhel7	
  docker-­‐apache]$	
  docker	
  build	
  -­‐t	
  demo-­‐apache	
  .	
  
Sending	
  build	
  context	
  to	
  Docker	
  daemon	
  3.584	
  kB	
  
Sending	
  build	
  context	
  to	
  Docker	
  daemon	
  	
  
Step	
  0	
  :	
  FROM	
  registry.access.redhat.com/rhel	
  
	
  -­‐-­‐-­‐>	
  e1f5733f050b	
  
Step	
  1	
  :	
  RUN	
  yum	
  -­‐y	
  install	
  httpd	
  
	
  -­‐-­‐-­‐>	
  Using	
  cache	
  
	
  -­‐-­‐-­‐>	
  3679b20fa9ba	
  
Step	
  2	
  :	
  ADD	
  index.html	
  /var/www/html/index.html	
  
	
  -­‐-­‐-­‐>	
  Using	
  cache	
  
	
  -­‐-­‐-­‐>	
  db91c285d5ad	
  
Step	
  3	
  :	
  EXPOSE	
  80	
  
	
  -­‐-­‐-­‐>	
  Using	
  cache	
  
	
  -­‐-­‐-­‐>	
  c9ceb17b169f	
  
Step	
  4	
  :	
  CMD	
  /usr/sbin/httpd	
  -­‐DFOREGROUND	
  
	
  -­‐-­‐-­‐>	
  Using	
  cache	
  
	
  -­‐-­‐-­‐>	
  4e99155706f6	
  
Successfully	
  built	
  4e99155706f6	
  
docker run 実行例
•  ランダムなポートと、コンテナID、コン
テナ名が割り当てられる
[yuryu@rhel7	
  docker-­‐apache]$	
  docker	
  run	
  -­‐dP	
  demo-­‐apache	
  
8d6b20a1e23427ad575bed1aee9cbea5406e5ed648a645e955cd6c6c6a
34ea0a	
  
[yuryu@rhel7	
  docker-­‐apache]$	
  docker	
  ps	
  
CONTAINER	
  ID	
  	
  	
  	
  	
  	
  	
  	
  IMAGE	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  COMMAND	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
CREATED	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  STATUS	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  PORTS	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
NAMES	
  
8d6b20a1e234	
  	
  	
  	
  	
  	
  	
  	
  demo-­‐apache:latest	
  	
  	
  "/usr/sbin/httpd	
  
-­‐DF	
  	
  	
  4	
  seconds	
  ago	
  	
  	
  	
  	
  	
  	
  Up	
  4	
  seconds	
  	
  	
  	
  	
  	
  	
  	
  
0.0.0.0:49247-­‐>80/tcp	
  	
  	
  	
  jovial_jones	
  	
  	
  	
  	
  	
  	
  	
  	
  
いくつかの応用パターン
•  固定ポートの割り当て
•  コンテナのリンク
•  コンテナ内のボリュームを共有
•  コンテナ外とボリュームを共有
固定ポートの割り当て
•  $ docker run -p <host port>:<guest port>
•  $ docker port コマンドでもポートの割り
当てを確認できる
[yuryu@rhel7	
  docker-­‐apache]$	
  docker	
  run	
  -­‐dp	
  80:80	
  demo-­‐
apache	
  
b027be3d09ace7c8cac594c14d07d3ddda5c32f15e14f8a28297714a69
723c54	
  
[yuryu@rhel7	
  docker-­‐apache]$	
  docker	
  port	
  b027be3d09ac	
  
80/tcp	
  -­‐>	
  0.0.0.0:80	
  
コンテナのリンク
•  --link <コンテナ名>:alias
•  EXPOSEしたポートを環境変数に入れる
#	
  docker	
  run	
  -­‐d	
  -­‐e	
  MYSQL_ROOT_PASSWORD=root	
  -­‐-­‐name	
  mysql	
  
mysql	
  
#	
  docker	
  run	
  -­‐it	
  -­‐-­‐link	
  mysql:mysql	
  mysql	
  /bin/bash	
  
#	
  env	
  |grep	
  MYSQL_PORT	
  
MYSQL_PORT_3306_TCP_PORT=3306	
  
MYSQL_PORT_3306_TCP=tcp://172.17.0.155:3306	
  
MYSQL_PORT_3306_TCP_PROTO=tcp	
  
MYSQL_PORT_3306_TCP_ADDR=172.17.0.155	
  
MYSQL_PORT=tcp://172.17.0.155:3306	
  
#	
  mysql	
  -­‐-­‐host=$MYSQL_PORT_3306_TCP_ADDR	
  -­‐-­‐port=
$MYSQL_PORT_3306_TCP_PORT	
  -­‐-­‐password=root	
  
ALIAS_PORT_XXX
ALIAS_PORT_XXX_TCP
ALIAS_PORT_XXX_TCP_PROTO
ALIAS_PORT_XXX_TCP_ADDR
ALIAS_PORT_XXX_TCP_PORT
コンテナのリンク(図)
提供コンテナ 使うコンテナ
link
aliasEXPOSE
環境変数
コンテナ内のボリューム共有
•  例: VOLUME /var/lib/mysql
•  --volumes-from <コンテナ名> で利用
•  Data-only コンテナをベースに使うと良い
#	
  docker	
  run	
  -­‐d	
  -­‐-­‐name	
  mysql_volume	
  mysql	
  echo	
  MySQL	
  
Volume	
  Container	
  
#	
  docker	
  run	
  -­‐-­‐volumes-­‐from	
  mysql_volume	
  -­‐d	
  -­‐e	
  
MYSQL_ROOT_PASSWORD=root	
  -­‐-­‐name	
  mysql	
  mysql	
  
Docker 1.4以降は docker run の代わりに docker create を利用する
(ボリューム生成のタイミングが変更されている)
コンテナ外とのボリューム共有
•  -v <host path>:<container path>
•  SELinuxの設定が必要
– # chcon -Rt svirt_sandbox_file_t
$	
  mkdir	
  mysql-­‐volume;	
  cd	
  mysql-­‐volume	
  
$	
  sudo	
  chcon	
  -­‐Rt	
  svirt_sandbox_file_t	
  .	
  
$	
  docker	
  run	
  -­‐v	
  $(pwd):/var/lib/mysql	
  -­‐-­‐name	
  mysql	
  -­‐e	
  
MYSQL_ROOT_PASSWORD=root	
  -­‐d	
  mysql	
  
Data-onlyコンテナのバックアップ
•  ホストでボリュームを共有して、tarで固
める
$	
  mkdir	
  mysql-­‐volume;	
  cd	
  mysql-­‐volume	
  
$	
  sudo	
  chcon	
  -­‐Rt	
  svirt_sandbox_file_t	
  .	
  
$	
  sudo	
  docker	
  run	
  -­‐-­‐volumes-­‐from	
  mysql_volume	
  -­‐v	
  $(pwd):/
backup	
  -­‐-­‐name	
  mysql-­‐backup	
  fedora	
  tar	
  cfz	
  /backup/mysql-­‐
backup.tar.gz	
  /var/lib/mysql	
  
$	
  sudo	
  docker	
  run	
  -­‐-­‐volumes-­‐from	
  mysql_volume	
  -­‐v	
  $(pwd):/
backup	
  -­‐-­‐name	
  mysql-­‐restore	
  fedora	
  tar	
  xf	
  /backup/mysql-­‐
backup.tar.gz	
  -­‐C	
  /	
  	
  
ボリューム共有
Data only
コンテナ
使うコンテナ
volumes-from
VOLUME
ホスト
-v <host>:<container>
Dockerで作るCI
開発者A
開発者B
コンテナの定義を共有
変更を通知
自動テストを実施
コンテナを取得して開発
開発者C
クラウドへデプロイを指示
GitHub
テスト済みコンテナイメージを
クラウドサービスへデプロイ
コンテナイメージを作成
今回のデモの定義
•  GitHubで公開中
•  https://github.com/yuryu/docker-­‐
jenkins-­‐demo	
  
Red Hat Enterprise Linux
テストソースコードを取得
生成
起動
JenkinsのDockerfile
FROM	
  registry.access.redhat.com/rhel	
  
MAINTAINER	
  Haruka	
  Iwao	
  
	
  
RUN	
  yum	
  -­‐y	
  upgrade	
  
	
  
RUN	
  curl	
  -­‐o	
  /etc/yum.repos.d/jenkins.repo	
  http://pkg.jenkins-­‐
ci.org/redhat/jenkins.repo	
  
RUN	
  rpm	
  -­‐-­‐import	
  https://jenkins-­‐ci.org/redhat/jenkins-­‐
ci.org.key	
  
RUN	
  yum	
  -­‐y	
  install	
  jenkins	
  java	
  git	
  docker	
  
	
  
ADD	
  run-­‐jenkins.sh	
  /root/run-­‐jenkins.sh	
  
	
  
EXPOSE	
  8080	
  
	
  
CMD	
  /root/run-­‐jenkins.sh	
  
run-jenkins.sh
#!/bin/sh	
  
	
  
JENKINS_HOME="/var/lib/jenkins"	
  
JENKINS_USER="jenkins"	
  
JENKINS_JAVA_OPTIONS="-­‐Djava.awt.headless=true"	
  
JENKINS_PORT="8080"	
  
JENKINS_HANDLER_MAX="100"	
  
JENKINS_HANDLER_IDLE="20"	
  
	
  
JAVA_CMD="/usr/bin/java	
  $JENKINS_JAVA_OPTIONS	
  -­‐DJENKINS_HOME=$JENKINS_HOME	
  -­‐
jar	
  /usr/lib/jenkins/jenkins.war"	
  
OPTIONS="-­‐-­‐httpPort=$JENKINS_PORT	
  -­‐-­‐handlerCountMax=$JENKINS_HANDLER_MAX	
  -­‐-­‐
handlerCountMaxIdle=$JENKINS_HANDLER_IDLE	
  "	
  
	
  
cd	
  "$JENKINS_HOME"	
  
exec	
  runuser	
  -­‐u	
  $JENKINS_USER	
  -­‐-­‐	
  $JAVA_CMD	
  $OPTIONS
SlaveのDockerfile
FROM	
  registry.access.redhat.com/rhel	
  
MAINTAINER	
  Haruka	
  Iwao	
  
	
  
RUN	
  yum	
  -­‐y	
  upgrade	
  
	
  
RUN	
  yum	
  -­‐y	
  swap	
  -­‐-­‐	
  remove	
  fakesystemd	
  -­‐-­‐	
  install	
  systemd	
  systemd-­‐libs	
  
RUN	
  yum	
  -­‐y	
  install	
  openssh-­‐server	
  java-­‐1.7.0-­‐openjdk	
  
	
  
RUN	
  adduser	
  jenkins	
  
RUN	
  echo	
  "jenkins:jenkins"	
  |	
  chpasswd	
  
RUN	
  ssh-­‐keygen	
  -­‐f	
  /etc/ssh/ssh_host_rsa_key	
  -­‐N	
  ''	
  -­‐t	
  rsa	
  
RUN	
  ssh-­‐keygen	
  -­‐f	
  /etc/ssh/ssh_host_dsa_key	
  -­‐N	
  ''	
  -­‐t	
  dsa	
  
RUN	
  ssh-­‐keygen	
  -­‐f	
  /etc/ssh/ssh_host_ecdsa_key	
  -­‐N	
  ''	
  -­‐t	
  ecdsa	
  
	
  
RUN	
  yum	
  -­‐y	
  install	
  gcc	
  gcc-­‐c++	
  automake	
  autoconf	
  make	
  git	
  libtool	
  
	
  
EXPOSE	
  22	
  
	
  
CMD	
  ["/usr/sbin/sshd",	
  "-­‐D"]	
  
Slaveを作るときの注意点
•  RHEL標準のコンテナイメージには
systemdが入っていません
•  fakesystemdが入っている
•  systemdに依存するパッケージを入れる場
合は、本物のsystemdに置き換える
– yum -y swap -- remove fakesystemd -- install
systemd systemd-libs
•  systemdをinitとして実行する必要は無い
Jenkins Docker Plugin
•  JenkinsスレーブをDockerで実行
•  テストごとにコンテナを生成、削除
DockerにTCPをlistenさせる
•  Jenkinsから制御するために必要
•  /etc/sysconfig/dockerを書き換える
•  このままだと認証なしに誰でもアクセス
可能になるので注意!
OPTIONS=-­‐-­‐selinux-­‐enabled	
  -­‐H	
  tcp://172.17.42.1:5555	
  -­‐H	
  fd://	
  
Jenkins実行手順
•  Data-onlyコンテナを起動してから、
Jenkins本体を起動する
$	
  docker	
  run	
  -­‐d	
  -­‐v	
  /var/lib/jenkins	
  -­‐-­‐name	
  
jenkins-­‐home	
  yuryu/demo-­‐jenkins	
  echo	
  Data-­‐only	
  
container	
  for	
  jenkins	
  
$	
  docker	
  run	
  -­‐-­‐volumes-­‐from	
  jenkins-­‐home	
  -­‐d	
  -­‐p	
  
8080:8080	
  yuryu/demo-­‐jenkins	
  
Jenkins本体の設定
•  Manage Jenkins > Configure System
Dockerの状態を確認
•  Manage Jenkins > Docker
プロジェクトの設定
今回デモで使うプロジェクト
•  簡単なautoconf	
  /	
  gtest	
  を使うCのプロジェ
クトを用意しました	
  
•  https://github.com/yuryu/gtest-­‐demo
テスト実行中の様子
•  コンテナ内で configure が走っている
テスト終了後
•  設定すれば、コンテナをイメージに
commitできる
実際にやってみます
cAdvisor
•  Dockerのための監視ツール
– https://github.com/google/cadvisor
cAdvisorの画面
cAdvisor起動方法
#	
  setenforce	
  Permissive	
  
$	
  docker	
  run	
  	
  
	
  	
  -­‐-­‐volume=/:/rootfs:ro	
  	
  
	
  	
  -­‐-­‐volume=/var/run:/var/run:rw	
  	
  
	
  	
  -­‐-­‐volume=/sys:/sys:ro	
  	
  
	
  	
  -­‐-­‐volume=/var/lib/docker/:/var/lib/docker:ro	
  	
  
	
  	
  -­‐-­‐publish=8080:8080	
  	
  
	
  	
  -­‐-­‐detach=true	
  	
  
	
  	
  -­‐-­‐name=cadvisor	
  	
  
	
  	
  -­‐-­‐volume=/cgroup:/cgroup	
  	
  
	
  	
  google/cadvisor:latest
ご清聴ありがとうございました

More Related Content

Dockerイメージ構築 実践テクニック