Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
丸一日以上ハマって Graphite が動く Dockerfile を作って気付いたこととかメモ

丸一日以上ハマって Graphite が動く Dockerfile を作って気付いたこととかメモ

はじめに

  • Graphite の勉強のつもりで Dockerfile を作ってみた
  • 単にコマンドを並べるだけではもちろん上手く動作しなくて試行錯誤しながら周辺の技術とか勉強になったのでメモしておく
  • 結局は Dockerfile では上手く動かせていない

出来たもの


何が上手く動いてなかったのか?

  • ビルドは成功するし起動は成功する
  • ログインされるものの肝心のダッシュボードが表示されない

ダッシュボードが表示されていない状況

/var/log/httpd/graphite-web-access.log に以下のようなログが出てる。

bash-4.1# tail -f graphite-web-access.log
10.0.2.2 - - [25/May/2014:18:18:34 -0500] "GET /composer/? HTTP/1.1" 200 1622
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/browser.js HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/composer.js HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/completer.js HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/img/carbon-fiber.png HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/ext/ext-all.js HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/composer_widgets.js HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/ext/resources/css/ext-all.css HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:35 -0500] "GET /content/js/ext/adapter/ext/ext-base.js HTTP/1.1" 500 632
10.0.2.2 - - [25/May/2014:18:18:36 -0500] "GET /favicon.ico HTTP/1.1" 200 542

なんで?

原因解った

/etc/graphite-web/local_settings.py に設定が不足していた。

# 以下足りてなかった部分
GRAPHITE_ROOT = '/usr/share/graphite'
CONF_DIR = '/etc/graphite-web'
STORAGE_DIR = '/var/lib/graphite-web'
CONTENT_DIR = '/usr/share/graphite/webapp/content'
WHISPER_DIR = '/var/lib/carbon/whisper/'
RRD_DIR = '/var/lib/carbon/rrd'
LOG_DIR = '/var/log/graphite-web/'
# 以下して設定してなかった...
DATABASES = {
  'default': {
    'NAME': 'graphite',
    'ENGINE': 'django.db.backends.mysql',
    'USER': 'graphite',
    'PASSWORD': 'xxxxxxx',
    'HOST': 'localhost',
    'PORT': '3306',
  }
}

うう、どっか山ごもりしたい...


とは言え、色々と勉強になった...Django で利用する manage.py について

manage.py ってなにやってるのか?

  • django-admin.py という Django を管理する為のコマンドラインユーティリティのラッパ
  • 詳細はこちら

manage.py syncdb をどうやって Dockerfile 内で実現するか?

graphite-web も漏れ無く Django で実装されているの manage.py のお世話になるのだが、graphite-web の初期セットアップ時に manage.py syncdb を実行してデータベースのテーブル作ったり、管理ユーザーを作成しなければならない。

この管理ユーザーを作成する際に普通だと以下のようなインタラクティブな状態になる。

この状態をどのように実現するかで約半日悩んだ...試行錯誤の内容は以下の「manage.py syncdb をどうやって Dockerfile 内で実現するか?(詳細)」に譲るとして manage.py syncdb に --noinput` というオプションがあるのでそちらを利用した。

--noinput については以下の通り。

ユーザプロンプトでの "Are you sure?" のような確認メッセージの出力の抑制には --noinput オプションを使います。対話を必要とせずに django-admin.py を実行する自動化されたスクリプトで役に立ちます。

一旦、正常に稼働する環境を構築して以下のようなオプションでデータベースの内容を JSON 形式でダンプして上述の「自動化されたスクリプト」を生成した。

/usr/lib/python2.6/site-packages/graphite/manage.py dumpdata --indent=2 --format=json auth.user

上記を実行すると以下のような JSON ファイルが出力される。

[
  {
    "pk": 1,
    "model": "auth.user",
    "fields": {
      "username": "admin",
      "first_name": "",
      "last_name": "",
      "is_active": true,
      "is_superuser": true,
      "is_staff": true,
      "last_login": "2014-05-25T18:57:01",
      "groups": [],
      "user_permissions": [],
      "password": "pbkdf2_sha256$10000$IxdLbQaUHl9O$gjMsDbAijARfk0HEZQuDpTSd9EzUrn3B2hzeqUwa0N4=",
      "email": "admin@example.com",
      "date_joined": "2014-05-25T18:57:01"
    }
  }
]

この JSON ファイルを docker build 時に ADD しておいて mange.py syncdb --noinput する。尚、ファイル名は initial_data.json というファイル名で保存しておくと良さそう(他の名前でイケるかは試していない)。

ADD initial_data.json /path/to/initial_data.json
RUN cd /path/to/ && /usr/lib/python2.6/site-packages/graphite/manage.py syncdb --noinput

また、initial_data.json ファイルが存在するディレクトリで manage.py syncdb を実行する必要がある。

Django のパスワード文字列について

上記の JSON ファイルにも定義されているが password の文字列としては以下のようなルールが設けられている

hashtype$salt$hash

ハッシュ方式 (hashtype)、ハッシュソルト (salt)、そしてハッシュ値 (hash) をドル記号 ($) で分割した文字列となる。


Dockerfile

#
FROM centos
#
MAINTAINER YOHEI KAWAHARA inokappa
#
RUN echo "NETWORKING=yes" >/etc/sysconfig/network
#
RUN yum -y update
RUN rpm --import http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/RPM-GPG-KEY-EPEL-6
RUN cd /tmp/ && wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
RUN cd /tmp/ && rpm -Uvh epel-release-6-8.noarch.rpm
#
RUN yum -y install graphite-web mysql mysql-server MySQL-python python-carbon monit vim telnet expect
#
ADD graphite/local_settings.py /etc/graphite-web/local_settings.py
ADD graphite/initial_data.json /etc/graphite-web/initial_data.json
#
RUN /etc/init.d/mysqld start && \
  mysql -e "CREATE USER 'graphite'@'localhost' IDENTIFIED BY 'passw0rd';" -u root && \
  mysql -e "GRANT ALL PRIVILEGES ON graphite.* TO 'graphite'@'localhost';" -u root && \
  mysql -e "CREATE DATABASE graphite;" -u root && \
  mysql -e 'FLUSH PRIVILEGES;' -u root && \
  export LANG="en_US.UTF-8" && \
  cd /etc/graphite-web && \
  /usr/lib/python2.6/site-packages/graphite/manage.py syncdb --noinput && \
  sleep 1
#
ADD monit/monit.conf /etc/monit.conf
RUN chown root:root /etc/monit.conf && chmod 600 /etc/monit.conf
ADD monit/httpd /etc/monit.d/
ADD monit/mysqld /etc/monit.d/
ADD monit/carbon-cache /etc/monit.d/
RUN chown root:root /etc/monit.d/* && chmod 600 /etc/monit.d/*
#
EXPOSE 3306 2003 2004 7002 80 2812
CMD ["/usr/bin/monit", "-I", "-c", "/etc/monit.conf"]

おまけ

manage.py syncdb をどうやって Dockerfile 内で実現するか?(詳細)

まずは expect を利用する例。

#!/usr/bin/env expect

set timeout -1
spawn python /usr/lib/python2.6/site-packages/graphite/manage.py syncdb

expect "Would you like to create one now" {
  send "yes\r"
}

expect "Username *:" {
  send "admin\r"
}

expect "E-mail address:" {
  send "admim@example.com\r"
}

expect "Password:" {
  send "admin\r"
}

expect "Password *:" {
  send "admin\r"
}

interact

expect "Superuser created successfully"

Ubuntu 環境では動作したが boot2dockerMacOS X 環境だと The system has no more ptys.Ask your system administrator to create more. というエラーが出てしまい却下。

/usr/lib/python2.6/site-packages/graphite/manage.py dumpdata でフルダンプしてレストア(syncdb --noinput)案。

/usr/lib/python2.6/site-packages/graphite/manage.py dumpdata

認証情報以外にもセッション情報等も出力されるのでホストを移行したりする際には使えるような気がするが中身をちゃんと把握出来ておらず、思わぬ挙動でハマるのも面倒だったので却下。

monit でのプロセス監視

例によって今回も monit で各種プロセスを監視。


まとめ

  • 色々とハマってしまったが振り返ってみると得られたことって少ないような気がして残念
  • python 周りの知識が殆ど 0 なのでトラブった時にキツイ
  • ただ、ハマることで内部のことを知るきっかけになって良かった
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment