フロッピーディスクの残骸

フロッピーディスクを分解するのって楽しいよね

EC2インスタンス(開発環境)を夜間停止し、さらに祝日にも対応させる

EC2インスタンスを利用しない夜間と祝日は停止させて、平日の朝に起動する
というのをやりたくていろいろググってました。

どっかでcron的なものを回さなければならないんだけど、
どうやらみなさんLambdaを利用しているらしい。

EC2の起動・終了

dev.classmethod.jp

これだけやれば、夜間停止と朝の起動はできそうだ。

後は祝日対応なんだけど、このスクリプトに付け足していろいろ頑張ってみようと思う。

祝日判定

これ利用すれば良さそう。

qiita.com

DebugMessageをSlackに流したい

これを利用すると良い

www.npmjs.com

最終的なソース

function slack_post(message) {
  var Slack = require('slack-node');
  webhookUri = "__WebHookURL__";

  slack = new Slack();
  slack.setWebhook(webhookUri);

  slack.webhook({
    channel: "#general",
    username: "LambdaNotification",
    text: message,
  }, function(err, response) {
    console.log(response);
  });
};

function holiday_check() {
  var JapaneseHolidays = require('japanese-holidays');
  var today = new Date();
  var holiday = JapaneseHolidays.isHoliday(today);
  if(holiday) {
    return true;
  } else {
    return false;
  }
};



function ec2_start() {
var AWS = require('aws-sdk');
AWS.config.update({region: 'ap-northeast-1'});

var ec2 = new AWS.EC2();

var params = {
  InstanceIds: [
    'INSTANCE_ID',
    'INSTANCE_ID'
  ]
};
ec2.startInstances(params, function(err, data) {
  if (!!err) {
      console.log(err, err.stack);
      slack_post(err);
  } else {
      console.log(JSON.stringify(data));
      slack_post(JSON.stringify(data));
  }
});
};


exports.handler = function(event, context) {
  var holiday = holiday_check();
  var message = "";

  if (holiday) {
      message = "今日は祝日のため、サーバーの起動は行いません。"
      console.log(message);
      slack_post(message)
    return ;
  } else {
      message = "今日は平日です。サーバーの起動を行います。"
      console.log(message);
      slack_post(message)
      ec2_start();
  }
}

停止する場合は、ec2.startInstancesec2.stopInstancesに変更するだけで停止処理にできます。
functionの名前も変えて利用してくださいね。


おまけ

沖縄は6/23に慰霊の日というものがあって、その日は祝日になったりします。
(企業さんによっては仕事なんだけど)

japanese-holiday-jsでは、日本の祝日は網羅してあるんだけど、
地方で定められた祝日は対応できないので、どうにかしてがんばってみる。

ソフトウェア/javascript/japanese-holidays - 武内@筑波大

japanese-holiday-jsの開発者さんのページに山の日を追加したときの対応が書かれてて
これなら楽にメンテできそうだったので、uchina-holidays-jsを作成して公開しました。

www.npmjs.com

作成後に気づいたけど、
慰霊の日は普通に仕事だった...(ToT)

レビューをアサインするhubot-reviewer-lottoを使ってみた

レビューを回したいという要望があり、指名スクリプト的なものほしいよねってことでhubot-reviewer-lottoを入れてみました。

HUBOT_GITHUB_TOKEN
HUBOT_GITHUB_ORG
HUBOT_GITHUB_REVIEWER_TEAM
HUBOT_GITHUB_WITH_AVATAR

上記を環境変数に登録するのだけれど、HUBOT_GITHUB_REVIEWER_TEAMはTEAM IDを入れる。 (ドキュメントちゃんと読んでなくて、チーム名入れてたよ^^;)

環境構築

  • hubotのインストール
$ npm install -g yo generator-hubot
$ yo hubot
$ ? Owner --> 328
? Bot name --> test
? Description --> test bot
? Bot adapter campfire --> 何も入力せずEnter
  • 動作テスト
$ bin/hubot
test> test ping
test> PONG  #botから返ってきたらOK
  • hubot-reviewer-lottoを入れる
$ npm i --save hubot-reviewer-lotto
$ vim external-scripts.json
-> "hubot-reviewer-lotto"を追記
$ vim ~/.zshrc
export HUBOT_GITHUB_TOKEN=hogehogehoge
export HUBOT_GITHUB_ORG=hoge
export HUBOT_GITHUB_REVIEWER_TEAM=111111
export HUBOT_GITHUB_WITH_AVATAR=0
$ exec $SHELL

Githubのtokenは事前に作成しておいてくださいね。 Githubのページから Settings -> Personal access tokens で作成できます。

  • チームIDがわからない場合
$ curl -u 自分のアカウント:TOKEN https://api.github.com/orgs/ORGANIZATION/teams

上記コマンドを発行後、 ORGANIZATION内のチームに関する情報がjsonで返ってきますので、 レビューを行うチームのIDを控えて、HUBOT_GITHUB_REVIEWER_TEAMに登録してください。

  • 動作テスト
$ bin/hubot
hubot> hubot reviwer for REPO PULLREQUESTID
例) hubot review for helloworld 1

これで、GITHUB_REVIEWER_TEAM内の誰かにアサインしてくれます。

Slackとの連携

Slackとの連携部分は結構簡単で、
事前にhubotのインテグレーションを設定してtokenを発行し、zshrcに書くだけ

export HUBOT_GITHUB_TOKEN=xxxxxxx

んで、

$ npm install hubot-slack
$ bin/hubot --adapter slack

とやるだけでOKです。

問題点

SlackとGithubのアカウント名が違う場合、ちょっと厄介です。
どこかでマッピング作業をやる必要があります。

とこんな感じでしょうか。

おまけ

slackでコマンドを発行した場合、
自分宛にメンションがつくのでここは不要かなと思い、
forkして自分仕様にカスタマイズしました(^o^)

GitHub - 328--/hubot-reviewer-lotto: A reviewer lottery script for Hubot

Amazon LinuxでDockerコンテナの自動起動設定

どうやるんだろう?とググってたら公式に書いてあった。
- Linux インスタンスでの起動時のコマンドの実行

どうやら/var/lib/cloud/scripts/per-boot/スクリプトを配置すると良いらしい。

手順は、

  1. あらかじめdocker serviceを自動起動にする
  2. 指定ディレクトリにスクリプトを配置する

下記をstart_container.shという名前で保存し、実行権限を与える。

#!/bin/sh
export DOCKER_HOST=tcp://127.0.0.1:7000
docker start CONTAINER_NAME

うまくいかないときは/var/log/cloud-init-output.logにログが残ってるので見てみると良いかも。

参考

GoLang勉強会に参加してきた

土曜日のこと。

なんとなくGoLang勉強会に参加してきた。2回目の実施らしい。
今回は、もくもく勉強会ということで
Githubのissueにやること書いてそれをやるという感じでした。

最初、hugoのソースでも読もうかと思ったけど、
最初からソース読みに行くのは敷居が高いかなということで
A Tour of Goをやってました。

少し読んだ後に、今まで作ったスクリプトをGoで作ってみようかなという気になったので
ここを見ながら
GoでZabbixのアラート通知をSlackに流すスクリプト作成してみました。(写経ですが...)

package main

import (
        "fmt"
        "os"
        "encoding/json"
        "io/ioutil"
        "net/http"
        "net/url"
)

var (
  IncomingWebhookUrl string = ""#Webhook URL
)

type Slack struct {
        Text       string `json:"text"`
        Username   string `json:"username"`
        Icon_emoji string `json:"icon_emoji"`
        Icon_url   string `json:"icon_url"`
        Channel    string `json:"channel"`
}

func main() {
        params, _ := json.Marshal(Slack{
                string(os.Args[1]),
                "bot君",
                ":ghost:",
                "",
                "#general"})

        resp, _ := http.PostForm(
                IncomingWebhookUrl,
                url.Values{"payload": {string(params)}},
        )

        body, _ := ioutil.ReadAll(resp.Body)
        defer resp.Body.Close()

        println(string(body))
}

こんな感じでしょうか。
Zabbixの設定は割愛します。

次回も参加できたら
何か書いてみようかな。

おしま。

HubotのSlackインテグレーションをDockerでやる

n番煎じになっちゃいますが、
Slackと連携するHubotをDocker上で動かします。

いろんな人のDockerfileを見てると - centos6をベースに作成 - nodeをベースにして作成 しているようです。 nodeをベースに作成してもいいんですが、
それだとvimとか入ってないので、開発しづらいかなあ。
centos6も7もそんな変わらん気がするけど、
centos7をベースにDockerfileを書いてみます。

Dockerfile

FROM centos:7
RUN yum update -y
RUN yum install -y vim
RUN yum install -y epel-release
RUN yum install -y nodejs npm

RUN npm install -g yo generator-hubot coffee-script hubot-slack

RUN useradd -d /home/hubot -m -s /bin/bash -U hubot
USER hubot
WORKDIR /home/hubot
RUN yo hubot --owner "328" --name "bot name" --description "Hubot Slack" --adapter slack

CMD cd /home/hubot; bin/hubot --adapter slack

docker-compose.yml

docker-compose書いておくと、環境変数増えた時に楽になるので、一応書いてます。

hubot-slack:
  build: ./
  volumes:
    - /etc/localtime:/etc/localtime:ro
  environment:
    - HUBOT_SLACK_TOKEN=hogehoge
    - HUBOT_SLACK_TEAM=teams.slack.com
    - HUBOT_SLACK_BOTNAME=botname

コンテナの時刻をホスト側と合わせるために、/etc/localtimeをread onlyでmountしてます。

ソースはGithubに置いてます。

github.com

動作チェック

$docker-compose build
$docker-compose up -d

slackのhubotにpingを送るとpongと返ってくるはずです。

参考

Arukas触ってみた

Arukas

さくらクラウドのDockerホスティングサービス こんな資料もあった

Beta期間中は無料で利用できるようなので遊んでみる。 Githubアカウントでログインできるので、そちらを利用しました。

Docker Hubにあるイメージ(今回はnginx)を画面からぽちぽちーと選択してRUN後、 ENDPOINTを開いたらnginxが上がってる。

そいや、データの永続性とかコンテナ同士のリンクってどうなっているんだろうか。 と、FAQを見たら対応してない模様。今後に期待ですね。

Arukas CLI

ArukasはCLI版もあるっぽい API Key Createからキー拾って.envに書いたらすぐ使える。 docker psとかと同じ感じでarukas psって使えるので便利です。

イメージを起動するときは、下記のような感じ

$ arukas run --instances 1 --mem 512 -p 80:tcp httpd

今更始めるDockerの勉強

Docker

KVMやらESXiばっか触ってたせいか、
Dockerは食わず嫌いみたいな感じで触ってなかったんだけど、
そうも言ってられない時代になったし、DockerのInvitation Codeも届いたので
そろそろ本腰入れて勉強を始めようかなと思う。
一昔前だと、boot2dockerやらdocker-machineやら入れなくて
「いろいろめんどくせえなあー」と思ってたけど
資料見返したらそんなこともなかったのね。

Fork爆弾投下

まずやってみたくなるのが、Fork爆弾。

$ docker pull centos:latest
$ docker run -t -i centos:latest /bin/bash
# :(){ :|:& };:

やってみたら、実行したコンテナはフリーズしたけど、ホストには影響が無かった。
すばらしい。仮想環境で動作させてるから当たり前っちゃ当たり前なんだけど。

Dockerfileを書く

大抵のものはDocker Hubにあるんで、そっからpullしてきて利用したらよろしい。
んだけど、勉強だと思って簡単なものを書いてみる。

vimを入れる

Dockerfileはこんな感じ

FROM centos:7
RUN yum update -y
RUN yum install -y vim

下記でビルドを行う

docker build -t yuya/vim ./

イメージを起動

docker run -t -i yuya/vim /bin/bash

ここでvimコマンドが使えるようになっているはず。
こんな感じで書けばいいのね。

WordpressをDockerで動かす

こんなんでいけます。

$ docker pull wordpress
$ docker pull mysql
$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=bakabakaahoaho -d mysql
$ docker run --name wordpress --link mysql:mysql -p 80:80 -d wordpress

mysqlwordpressをpullしておいて、最初にmysqlのコンテナを起動します。
WordpressはDBに接続できて初めて使えるので、最初にDBを起動させないとダメですよん。
オプションのおさらい

-e 環境変数を設定
--link コンテナ同士の連携
-p ポートマッピング
-d バックグラウンドで動作させる

書いた記事が消えないかとかその辺りは少し心配ですが、
docker imageを消さなければデータは残りますんで安心してください。
とは言っても、アプリケーションが動作するコンテナ内にはデータを置かないスタンスなので、
データはどこか別の場所に配置したいですね。

wordpressなら/var/www/html mysqlなら/var/lib/mysqlかな?
この辺りのディレクトリをどっかからマウントしておいて利用できればOKなはず。
と調べてたらDocker Volumeなるものがあった。

Docker Volume

基本的にはアプリケーションが動作するコンテナ内にデータを置かないのがDockerらしい。
なので、データを配置するためのVolumeを作成してそれをマウントするか、ホストのディレクトリをマウントして利用するかのどちらかになる。

今回は、Volume作ってそれをマウントしようと思う。
Docker beta for Macだと、xhyve上で動作するので、マウントするディレクトリの実体が探せなかったので・・・^^;

/var/lib/mysqlの配置先を変更

まずはvolumeを作成

$ docker volume create --name mysql_volume

-v オプションつけてコンテナ起動

$ docker run -d --name mysql -v mysql_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql
動作チェックのためwordpressも
$ docker run --name wp-test --link mysql:mysql -p 80:80 -d wordpress

一応、Wordpressが動作していることを確認する。

mysql_volumeにDB入ってるの?

mysql_volumeを作ったけど、ここに実際にDBの実体があるかどうか確認したい。
なので、mysql_volumeを他のコンテナにマウントして実体を確認する。 centos7のコンテナを起動

$ docker run --name datavolume3 -i -v mysql_volume:/hogehoge -t centos:7 /bin/bash
# cd /hogehoge

お、いろいろ入ってる。
じゃあ、これがちゃんと共有されてるのか確認しましょう!

# rm /hogehoge/*

消えた。
そしてwordpressも表示されなくなった。
ちゃんと共有できてるじゃん。

といろいろ試してたんだけど、両方のコンテナにマウントできているかはdocker inspectで確認できる。
sourceが一緒ですね。

$ docker inspect mysql | jq ".[0].Mounts"
[
  {
    "Name": "mysql_data",
    "Source": "/var/lib/docker/volumes/mysql_volume/_data",
    "Destination": "/var/lib/mysql",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": "rprivate"
  }
]

----
$ docker inspect datavolume3 | jq ".[0].Mounts"
[
  {
    "Name": "mysql_data",
    "Source": "/var/lib/docker/volumes/mysql_volume/_data",
    "Destination": "/hogehoge",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": "rprivate"
  }
]

と、wordpressも同じようにvolumeをマウントして使えばいけるはず。

docker-compose

mysqlのROOTのパスワードは環境変数で持っている。
今は環境変数が1つだからいいけど、今後増えたらコマンドラインから実行する時が面倒になる。
そこで利用するのがdocker-composeだ。
docker-composeを使えば、複数のコンテナから構成されるサービスを簡単に管理できる。
例えば、下記のdocker-compose.ymlを準備する。

mysql:
  image: mysql
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: password

wordpress:
  image: wordpress
  links:
    - mysql:mysql
  ports:
    - "80:80"
  environment:
    WORDPRESS_DB_PASSWORD: password

そして

$ docker-compose up -d  # コンテナの起動

コマンド1つでらくらくちん。便利だな〜。
停止・削除もまとめてできる。

$ docker-compose stop # コンテナの停止
$ docker-compose rm # コンテナの削除

1回目はこの辺で終わり。
もう少しDockerで遊んでみるかな。

参考