share facebook facebook2 twitter menu hatena pocket slack

2015.06.19 FRI

Docker × git で複数サイトを管理

小谷松 丈樹

WRITTEN BY小谷松 丈樹

Docker触ろうぜ

Docker_container_engine_logo
Dockerについて調べてみると、どこも同じようにWordPressを構築するぞ!という内容の技術ブログに当たります。
説明のしやすさや見栄えの良さ、ハンズオンのしやすさ、相性の良さなど様々な理由があるものと思いますが、
Dockerに関する情報がどれもWordPressを構築する方法ばかりでは、うーん。

そこで、gitで複数のシステムを共通化して管理できる、 git subtree という仕組みを取り入れて、
Dockerの開発設計について検証してみたいと思います。
subtreeについても丸パクリでは面白くないので、 一つのシステムで異なるCSSリポジトリを使う ようにしてみます。

目標

Dockerで管理する複数サイトにおいて、
git subtreeを利用して同システムで違うCSS設定を使う

事前準備

  • Amazon EC2起動(suz-lab AMI5.6)
  • Amazon ELB 作成
  • ELBに向けたドメインを2つ設定
  • ELBとEC2の紐付け

Docker設定

Dockerのインストール

[root@docker ~]# yum install docker-io
[root@docker ~]# service docker start
Starting cgconfig service:                                 [  OK  ]
Starting docker:                                       [  OK  ]
[root@docker ~]# docker search centos6
NAME                                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
sergeyzh/centos6-btsync                                                                  2                    [OK]
sktelecom/centos6-hdw                                                                    2                    [OK]
urelx/centos6-epel                       CentOS 6 with EPEL repository.                  2                    [OK]
sergeyzh/centos6-nginx                                                                   1                    [OK]
treasureboat/centos6                     CentOS 6.6 updated version                      1                    [OK]
lemonbar/centos6-ssh                     Installed openssh-server on centos6, defau...   1                    [OK]
miko2u/centos6                           CentOS 6 JP locale                              0                    [OK]

urelx/centos6-epel を選択して、特権モード(–privileged)で起動
するとSSHログイン状態に

[root@docker ~]# docker run --privileged -t -i urelx/centos6-epel /bin/bash
Unable to find image 'urelx/centos6-epel:latest' locally
Pulling repository urelx/centos6-epel
7871f0e862fd: Download complete
511136ea3c5a: Download complete
5b12ef8fd570: Download complete
a30bc9f3097e: Download complete
e82bf4a08352: Download complete
71de305bc72d: Download complete
Status: Downloaded newer image for urelx/centos6-epel:latest
[root@e999117c75eb /]#

Dockerで1台目が立ち上がる

各コンテナの基本設定

初期設定

とりあえず、rootのパス変更だけしておいて

[root@e999117c75eb /]# yum install passwd initscripts vim -y
[root@e999117c75eb /]# passwd

以下必要なものをインストールしていく

必要なもの
  • ssh系インストール+設定

後々面倒にならないようにPAMを必要としないよう設定

[root@e999117c75eb /]# yum install openssh openssh-clients openssh-server -y
[root@e999117c75eb /]# vi /etc/ssh/sshd_config
UsePAM yes
→UsePAM no  # noに変更
#PermitRootLogin yes
→PermitRootLogin yes

[root@e999117c75eb /]# service sshd start
Generating SSH2 RSA host key:                              [  OK  ]
Generating SSH1 RSA host key:                              [  OK  ]
Generating SSH2 DSA host key:                              [  OK  ]
Starting sshd:                                             [  OK  ]
  • apache系インストール+設定
[root@e999117c75eb /]# yum install httpd -y

httpd基本設定は今回必要ないので割愛
htmlさえ表示できればOKなのでPHPインストールも割愛

  • gitインストール
[root@e999117c75eb /]# yum install git -y
コンテナのコミット

DockerコンテナのSSH接続を抜けてホストOSからコンテナリストを確認

[root@e999117c75eb /]# exit
exit
[root@docker ~]# docker ps -a
CONTAINER ID      IMAGE                       COMMAND           CREATED           STATUS                           PORTS           NAMES
e999117c75eb      urelx/centos6-epel:latest   "/bin/bash"       9 hours ago       Exited (0) About a minute ago                    hopeful_banach

コンテナIDを取得

[root@docker ~]# docker commit e999117c75eb docker1/centos
ed7595df338d2bb21920141ea6487bdc110573107167b5714b1a70f8ed75f6b2

docker1/centos と名前をつけてコミット。

[root@docker ~]# docker run --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
  -d, --detach=false         Detached mode: run the container in the background and print the new container ID
~~~
  -p, --publish=[]           Publish a container's port to the host
                               format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
                               (use 'docker port' to see the actual mapping)

[root@docker ~]# docker run -d -p 22 docker1/centos /usr/sbin/sshd -D e00b90eef6e33b1d069bb263fea1fe687e921366b1795b75e6e43b41a70ca980

docker1/centos コンテナの22番ポートにSSH接続を可能にするデーモンを立ち上げる感じ?

コンテナリストをを再度確認すると

[root@docker ~]# docker ps -a
CONTAINER ID        IMAGE                       COMMAND               CREATED             STATUS                     PORTS                   NAMES
e00b90eef6e3        docker1/centos:latest       "/usr/sbin/sshd -D"   21 seconds ago      Up 19 seconds              0.0.0.0:49153->22/tcp   fervent_colden
e999117c75eb        urelx/centos6-epel:latest   "/bin/bash"           9 hours ago         Exited (0) 4 minutes ago                           hopeful_banach

PORTSを見ると、 0.0.0.0:49153->22/tcp となっているので、
docker仮想PC?の49153番ポートから、コンテナ内の22番ポートにポートフォワーディングされいます。
docker1/centos にSSH接続するなら、49153番ポートに接続すれば良さそう。

[root@docker ~]# ifconfig
docker0   Link encap:Ethernet  HWaddr 0E:02:32:B8:15:77
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8641 errors:0 dropped:0 overruns:0 frame:0
          TX packets:49345 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:467161 (456.2 KiB)  TX bytes:74065641 (70.6 MiB)

ifconfig するとdockerのインターフェースのIPは 172.17.42.1 である事が分かるので、
この 49153 番ポートにSSH接続してみます。

[root@docker ~]# ssh root@172.17.42.1 -p 49153
The authenticity of host '[172.17.42.1]:49153 ([172.17.42.1]:49153)' can't be established.
RSA key fingerprint is ec:2d:11:43:0c:2f:af:24:7f:de:2f:78:75:b9:53:b5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[172.17.42.1]:49153' (RSA) to the list of known hosts.
root@172.17.42.1's password:
[root@e00b90eef6e3 ~]#

試行錯誤の末やっと成功したSSH接続。。。

普通に # docker search centos とすると、centos7のイメージが検索されます。
これで起動すると、コンテナのOSがCentOS7、ホスト側のOSがCentOS6となり、
ホスト側カーネルが古いため systemctl コマンドが使えない状況に陥る可能性があります。参考
バージョンの確認は大事だなぁと思いました。(小並感

コンテナ内apacheの表示確認

ホストOSからコンテナの再起動し、80番ポートを開けます。

[root@docker ~]# docker run -d -p 22 -p 80 docker1/centos /usr/sbin/sshd -D
c1ef47156013c696a531c2c1d70837567f6b2b2356406680bc6668158f25ad97
[root@docker ~]# docker ps -a
CONTAINER ID        IMAGE                       COMMAND               CREATED             STATUS                         PORTS                                          NAMES
c1ef47156013        docker1/centos:latest       "/usr/sbin/sshd -D"   9 seconds ago       Up 9 seconds                   0.0.0.0:49154->22/tcp, 0.0.0.0:49155->80/tcp   jovial_goldstine
e00b90eef6e3        docker1/centos:latest       "/usr/sbin/sshd -D"   57 minutes ago      Exited (137) 58 seconds ago                                                   fervent_colden
e999117c75eb        urelx/centos6-epel:latest   "/bin/bash"           10 hours ago        Exited (0) About an hour ago                                                  hopeful_banach

0.0.0.0:49154->22/tcp, 0.0.0.0:49155->80/tcp 22と80のポートフォワーディングが設定されました。
コンテナID c1ef47156013 で、httpdを起動する必要が有ります。

[root@docker ~]# ssh root@172.17.42.1 -p 49154
The authenticity of host '[172.17.42.1]:49154 ([172.17.42.1]:49154)' can't be established.
RSA key fingerprint is ec:2d:11:43:0c:2f:af:24:7f:de:2f:78:75:b9:53:b5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[172.17.42.1]:49154' (RSA) to the list of known hosts.
root@172.17.42.1's password:
[root@c1ef47156013 ~]# echo 'Hello, docker1!' >> /var/www/html/index.html
[root@c1ef47156013 ~]# chown apache:apache /var/www/html/index.html
[root@c1ef47156013 ~]# chmod 644 /var/www/html/index.html
[root@c1ef47156013 ~]# service httpd start
Starting httpd: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.4 for ServerName
                                                           [  OK  ]
[root@c1ef47156013 ~]# exit
[root@docker ~]# curl http://172.17.42.1:49155/
Hello, docker1!

OK, HTML取得できました。

予め用意しておいたものがこちらです
[root@docker ~]# docker ps -a
CONTAINER ID        IMAGE                       COMMAND               CREATED             STATUS                      PORTS                                          NAMES
1343039778f1        docker2/centos:latest       "/usr/sbin/sshd -D"   4 seconds ago       Up 3 seconds                0.0.0.0:49156->22/tcp, 0.0.0.0:49157->80/tcp   silly_lovelace
c1ef47156013        docker1/centos:latest       "/usr/sbin/sshd -D"   14 hours ago        Up 14 hours                 0.0.0.0:49154->22/tcp, 0.0.0.0:49155->80/tcp   jovial_goldstine
e00b90eef6e3        docker1/centos:latest       "/usr/sbin/sshd -D"   15 hours ago        Exited (137) 14 hours ago                                                  fervent_colden
e999117c75eb        urelx/centos6-epel:latest   "/bin/bash"           24 hours ago        Exited (0) 15 hours ago                                                    hopeful_banach

docker2/centos を立てました。
0.0.0.0:49156->22/tcp, 0.0.0.0:49157->80/tcp で設定されています。

プロキシ設定

ホストOSのapacheから、
docker1.mekachan.netの場合、 docker1/centos49155 番ポートに
docker2.mekachan.netの場合、 docker2/centos49157 番ポートに
プロキシを通す。

[root@docker ~]# vi /etc/httpd/conf/httpd.conf
#NameVirtualHost *:80
→NameVirtualHost *:80 #コメントアウト解除
#末尾に追加

<VirtualHost *:80> # ELBのhealthcheckがホストOSに来るため、面倒なので全許可
    ServerName any
    <Location />
        Order allow,deny
        Allow from all
    </Location>
</VirtualHost>
<VirtualHost *:80>
    ServerName docker1.mekachan.net
    ProxyPass / http://172.17.42.1:49155/
    ProxyPassReverse / http://172.17.42.1:49155/
</VirtualHost>
<VirtualHost *:80>
    ServerName docker2.mekachan.net
    ProxyPass / http://172.17.42.1:49157/
    ProxyPassReverse / http://172.17.42.1:49157/
</VirtualHost>

で、apacheを再起動すると・・・

スクリーンショット-2015-04-23-13.01.23
スクリーンショット 2015-04-23 13.01.23

docker1,docker2ともに表示できる事が確認できました。

git設計

共通利用するhtdocs下を管理するbareリポジトリをホストOSに置き、各コンテナからpullします。

[root@docker ~]# vi /var/www/html/index.html
<html>
<head>
<link rel="stylesheet" type="text/css" href="/css/layout.css" />
</head>
<body>
<h1>Hello, docker x git!</h1>
<p>CSSが無いとどっちのコンテナか分からない</p>
</body>
</html>

こんなHTMLを置いて

[appadmin@docker ~]$ mkdir bare.git
[appadmin@docker ~]$ cd bare.git/
[appadmin@docker bare.git]$ git --bare init
Initialized empty Git repository in /home/appadmin/bare.git/

bareリポジトリを作って

[appadmin@docker bare.git]$ cd /var/www/html/
[appadmin@docker html]$ git init
Initialized empty Git repository in /var/www/html/.git/
[appadmin@docker html]$ git add .
[appadmin@docker html]$ git commit -m "initial commit"
[master (root-commit) d71c29d] initial commit
 Committer: appadmin <appadmin@docker.mekachan.net>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

git config --global user.name "Your Name"
git config --global user.email you@example.com

If the identity used for this commit is wrong, you can fix it with:

`git commit --amend --author='Your Name &lt;you@example.com&gt;'`

 files changed, 10 insertions(+), 0 deletions(-)
 create mode 100755 healthcheck.txt
 create mode 100755 index.html
[appadmin@docker html]$ git remote add origin /home/appadmin/bare.git
[appadmin@docker html]$ git push -u origin master
Counting objects: 4, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 441 bytes, done.
Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4/4), done.
To /home/appadmin/bare.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

gitのユーザ名とアドレス設定し忘れてるけどリモートリポジトリにpush。

コンテナからこれをclone。

[appadmin@docker html]$ ssh root@172.17.42.1 -p 49154
The authenticity of host '[172.17.42.1]:49154 ([172.17.42.1]:49154)' can't be established.
RSA key fingerprint is ec:2d:11:43:0c:2f:af:24:7f:de:2f:78:75:b9:53:b5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[172.17.42.1]:49154' (RSA) to the list of known hosts.
root@172.17.42.1's password:
Last login: Thu Apr 23 03:48:18 2015 from ip-172-17-42-1.ap-northeast-1.compute.internal
[root@c1ef47156013 ~]#
[root@c1ef47156013 ~]# cd /var/www/html/
[root@c1ef47156013 html]# git clone ssh://appadmin@52.68.147.248:22/home/appadmin/bare.git
Initialized empty Git repository in /root/bare/.git/
ssh: connect to host 52.68.147.248 port 22: Connection timed out
fatal: The remote end hung up unexpectedly

コンテナからホストOSにSSHするのに一旦ネットワークの外に出るから、
EC2のSecurityGroup設定で穴を開けておかなきゃいけなかった。
コンテナから出て行くIPはEC2のIPなので、自サーバのIPに穴を開けて再度clone

[root@c1ef47156013 html]# git clone ssh://appadmin@52.68.147.248:22/home/appadmin/bare.git
Initialized empty Git repository in /var/www/html/bare/.git/ATTEMPT!
appadmin@52.68.147.248's password:
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (4/4), done.

html/bare/ 下にできちゃった。

スクリーンショット-2015-04-23-17.25.10
いい感じ。コンテンツは同じにできました。
CSSを分けるsubtreeを設定してみましょう。

CSSリポジトリ

CSSのみを管理するgitリポジトリを2つ作成(hoge/fuga)

[appadmin@docker ~]$ mkdir hoge
[appadmin@docker ~]$ mkdir hoge/css.git
[appadmin@docker ~]$ cd hoge/css.git/
[appadmin@docker css.git]$ git --bare init
Initialized empty Git repository in /home/appadmin/hoge/css.git/
[appadmin@docker css.git]$ cd
[appadmin@docker ~]$ mkdir fuga
[appadmin@docker ~]$ mkdir fuga/css.git
[appadmin@docker ~]$ cd fuga/css.git/
[appadmin@docker css.git]$ git --bare init
Initialized empty Git repository in /home/appadmin/fuga/css.git/
[appadmin@docker css.git]$ cd
[appadmin@docker ~]$ tree -L 2
.
├── bare.git
├── fuga
│   └── css.git
└── hoge
    └── css.git

で、こんな感じ。
leyout.css をそれぞれのリポジトリに設置します。

hogeのlayout.css

[appadmin@docker ~]$ mkdir hogecss
[appadmin@docker ~]$ vi hogecss/layout.css

body { background-color: rgb(225, 255, 225); /* 薄い緑 fugaは薄い青に設定 */ } [appadmin@docker ~]$ cd hogecss/ [appadmin@docker hogecss]$ git init Initialized empty Git repository in /home/appadmin/hogecss/.git/ [appadmin@docker hogecss]$ git add . [appadmin@docker hogecss]$ git commit -m "initial commit" [master (root-commit) e455b7d] initial commit [appadmin@docker hogecss]$ git remote add origin /home/appadmin/hoge/css.git [appadmin@docker hogecss]$ git push -u origin master Counting objects: 3, done. Writing objects: 100% (3/3), 259 bytes, done. Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. To /home/appadmin/hoge/css.git * [new branch] master -> master Branch master set up to track remote branch master from origin.

CSSの読込先を に変更し、
コンテナのリポジトリ( htdocs/bare/ の下)にCSSリポジトリをくっつけてみます。

サブツリーマージ

docker1/centoshoge を、 docker2/centosfuga を、それぞれくっつけます

[root@c1ef47156013 ~]# cd /var/www/html/bare/
[root@c1ef47156013 bare]# git remote add cssrepo ssh://appadmin@52.68.147.248:22/home/appadmin/hoge/css.git
[root@c1ef47156013 bare]# git subtree add --prefix=css --squash cssrepo master
git: 'subtree' is not a git command. See 'git --help'.
[root@c1ef47156013 bare]# git --version
git version 1.7.1
デフォルトのgitバージョン低すぎ問題

subtree機能は、1.8以上で利用可能です。
ということで CentOS に Git 1.8 をインストールする

[root@c1ef47156013 git-1.9.0]# /usr/local/bin/git --version
git version 1.9.0 #アプデして

[root@c1ef47156013 ~]# cd git-1.9.0/contrib/subtree/
[root@c1ef47156013 subtree]# make
cp git-subtree.sh git-subtree && chmod +x git-subtree
[root@c1ef47156013 subtree]# make install
install -d -m 755 /usr/local/libexec/git-core
install -m 755 git-subtree /usr/local/libexec/git-core # subtreeをインストール

[root@c1ef47156013 ~]# git subtree
usage: git subtree add   --prefix=<prefix> <commit>
   or: git subtree add   --prefix=<prefix> <repository> <ref>
   or: git subtree merge --prefix=<prefix> <commit>
   or: git subtree pull  --prefix=<prefix> <repository> <ref>
   or: git subtree push  --prefix=<prefix> <repository> <ref>
   or: git subtree split --prefix=<prefix> <commit...>
-h, --help            show the help
-q                    quiet
-d                    show debug messages
-P, --prefix ...      the name of the subdir to split out
-m, --message ...     use the given message as the commit message for the merge commit

options for 'split'
    --annotate ...        add a prefix to commit message of new commits
    -b, --branch ...      create a new branch from the split subtree
    --ignore-joins        ignore prior --rejoin commits
    --onto ...            try connecting new tree to an existing one
    --rejoin              merge the new branch back into HEAD

options for 'add', 'merge', 'pull' and 'push' --squash merge subtree changes as a single commit #きた!

仕切り直し

[root@c1ef47156013 ~]# cd /var/www/html/bare/
[root@c1ef47156013 bare]# git subtree add --prefix=css --squash cssrepo master
git fetch cssrepo master
Address 52.68.147.248 maps to ec2-52-68-147-248.ap-northeast-1.compute.amazonaws.com, but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT!
appadmin@52.68.147.248's password:
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ssh://52.68.147.248:22/home/appadmin/hoge/css
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> cssrepo/master

スクリーンショット-2015-04-24-10.21.31
CSSが反映されました。この勢いで docker2/centosfuga を設定して・・・

スクリーンショット-2015-04-24-10.49.21
きた!システムを統一してCSSディレクトリだけを異なるリポジトリにすることができました。

まとめ

  • Docker面白い
    • Dockerfileでプログラマブルサーバ構築(むしろこっちがDockerのメイン?
  • git subtree を使うには
    • yumでのインストールではバージョンが低い
    • しかもデフォルトでは有効になってない
    • サーバ周りの知識がボロクソだと判明

さあ、勉強勉強。

元記事はこちら

Docker × git で複数サイトを管理

小谷松 丈樹

小谷松 丈樹

アイレット第一事業部のWebアプリ開発者。PHP、JavaScriptの案件がメイン。モノづくりは常に楽しみながらがモットー。面白いものを生み出して、管理までできるようになるのが目標。