Shred IT!!!!

IT全般について試したこと・勉強したことを綴ったり、趣味について語るブログ

Docker を CentOS 7 にインストールして、Ubuntu を動作させる

概要


Docker を VirtualBox 上にある CentOS 7 にインストールして、 CentOS 7 上で Ubuntu を動作させるところまでを書き残す。
ちなみにこの CentOS 7 は Mac 上の Vagrant で動作している。

Dockerについては下記サイト等で確認するといい。

「いまさら聞けないDocker入門」最新記事一覧 - ITmedia Keywords

Docker のインストール


docker build すると ADD, COPY で no such file or directory になる問題の解決方法 - Shred IT!!!!

前に書いておいた記事が役に立つわけだが、 CentOS 7 にデフォルトで入っている Docker のバージョンが古いので、 yumリポジトリを追加して最新バージョンをインストールするようにする。

# cat >/etc/yum.repos.d/docker.repo <<-EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

リポジトリを追加したので docker をインストール。

# yum install docker

初期状態だと docker を使うには必ず sudo を付ける必要があるため、 docker グループを追加し、sudo なしにしたいユーザをそこに所属させておく。

Dockerコマンドをsudoなしで実行する方法 - Qiita

# sudo groupadd docker
# sudo gpasswd -a vagrant docker

インストールができたら、docker サービスを有効・自動起動 ON にする。
最初なので手動で起動する。

# sudo systemctl enable docker.service
# sudo systemctl start docker.service

起動を確認。

# docker -v
Docker version 1.7.1, build 3043001/1.7.1

Ubuntu を起動してみる


Ubuntu のイメージを落としてくる。

# docker pull ubuntu:latest

落としたイメージを確認する。

# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/ubuntu            latest              a005e6b7dd01        6 days ago          188.3 MB

Ubuntu のイメージからコンテナを作って、実行してみる。
ubuntu イメージから ubuntu_test というコンテナを作るコマンド。

# docker run -it --name ubuntu_test ubuntu /bin/bash

実行すると下記のように Ubuntubash が起動する。

root@dbcba89f0d82:/#

exit と打ってコンテナを終了して、コンテナを確認する。

# docker ps -a
CONTAINER ID        IMAGE            COMMAND                CREATED             STATUS                          PORTS                  NAMES
dbcba89f0d82        ubuntu           "/bin/bash"            2 minutes ago       Exited (0) About a minute ago                          ubuntu_test

作ったコンテナを再実行する際は下記コマンド。

# docker start ubuntu_test

Ubuntubash というかターミナルに入るには下記。

# docker exec -i -t ubuntu1 /bin/bash

まとめ


Docker のインストールから Ubuntu のコンテナを起動するところまでをまとめてみた。
Ubuntu 以外でも、例えば下記のように検索して、イメージを探すこともできる。

# docker search centos
INDEX       NAME                                                  DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/centos                                      The official build of CentOS.                   1478      [OK]
docker.io   docker.io/ansible/centos7-ansible                     Ansible on Centos7                              59  [OK]
docker.io   docker.io/jdeathe/centos-ssh-apache-php               CentOS-6 6.6 x86_64 / Apache / PHP / PHP m...   11  [OK]

VagrantVirtualBox などよりも気軽に環境を使い捨てできるような感じ。
気になるミドルウェアやOSを検索して、試してみるのにもいいと思った。

Twilio を使って Rails から ショートメール(SMS) を送信する

概要


Rails サーバからショートメールを送信する方法。

http://qiita.com/kidach1/items/cd63063fa98aaa5030bd 記事を残してくれている方がいるので、この記事を元にショートメールが送信できるまでを試す。

Twilio アカウント作成


http://twilio.kddi-web.com/ へアクセスする。

右上のサインアップをクリックする。

名前とメールアドレス、パスワードを設定して、ボタンをクリックする。

次の画面で電話番号の入力を求められるので入力して、ボタンをクリックする。

その電話番号にショートメールで認証コードが送信されるので、 認証コードを入力してボタンをクリックする。

認証が通ると Twilio の管理画面へ遷移する。

Twilio SMS用電話番号の取得


SMS を送信するには電話番号を購入する必要がある。
上部のメニュー「電話番号」をクリックし、右側の「電話番号を購入」ボタンをクリック。

日本の番号だと、SMS 送信に対応していないので、SMS 送信に対応した国を探す。
好きなバンドがフィンランド出身なのでフィンランドで検索してみる。

月額 ¥150 で電話番号を維持することができ、 SMS 送信: ¥10、SMS 受信: ¥1 で利用することができる。

厳密にはキャリア毎に価格が異なっているので下記を参照すること。
http://twilio.kddi-web.com/price/

購入ボタンをクリックし、電話番号を抑える。

トライアルアカウントだからか、クレジットカードの入力を求められることはなかった。

Rails 環境構築


Rails の環境を構築し、SMS送信画面を作成する。
予定だったが、コンソールで確認取れるので画面の作成はなし。

Rails のプロジェクトを作る。

# bundle exec rails new sms
# cd sms
# bundle install --path vendor/bundler

※結局、rails console で動作確認するので下記作業は必要なし。
Scaffold でテンプレを作る。

# bundle exec rails g scaffold sms to:integer from:integer body:string
# rake db:migrate

上記で作ると sm の複数形として扱われていたので、名前を付け直すw
scaffold で間違った場合は下記のようにすればまとめて削除できる。

# rake db:rollback
# bundle exec rails destroy "sms"

名前を付け直して再実行。

# bundle exec rails g scaffold short_message to:integer from:integer body:string
# rake db:migrate

Rails を起動して下記へアクセスできることを確認する。

# bundle exec rails s -b 0.0.0.0
http://192.168.33.10:3000/short_messages

ショートメール送信


Twilio はエンジニアがこういったページを利用することを想定しているのか、 わかりやすく API の使い方が記載されている。

さらっと確認できるだけでも、下記のサンプルコードが記載されている。

Ruby においては下記。

require 'rubygems' # not necessary with ruby 1.9 but included for completeness 
require 'twilio-ruby' 
 
# put your own credentials here 
account_sid = 'xxxxxxxxxx' 
auth_token = '[AuthToken]' 
 
# set up a client to talk to the Twilio REST API 
@client = Twilio::REST::Client.new account_sid, auth_token 
 
@client.account.messages.create({
    :from => '+00000000',    
})

scaffold で簡易的な CRUD を備えた画面ができているので、 create されるときに ショートメールを送信するように作成する。

gem の追加

公式の gem があるのでそれをインストールする。

https://github.com/twilio/twilio-ruby

下記を Gemfile へ追記する。

# vim Gemfile
gem 'twilio-ruby', '~> 4.2.1'
サービスの実装

require 'rubygems' # not necessary with ruby 1.9 but included for completeness 
require 'twilio-ruby' 

class ShortMessageService 
  ACCOUNT_SID = 'xxxxxxxxxxxxxx' 
  AUTH_TOKEN = 'yyyyyyyyyyyyy' 
  FROM = '+00000000'

  def self.send_short_message(to, body)
    client = Twilio::REST::Client.new account_sid, auth_token 
    client.account.messages.create({
      from: FROM,
      to: to,
      body: body
    })
  end
end

動作確認


コンソールを立ち上げて、上記のサービスを使ってみる。

# bundle exec rails c
# 送信先の電話番号はダミー
2.1.0 :001 >   ShortMessageService.send_short_message('+819000000000', 'test')
 => <Twilio::REST::Message @path=/2010-04-01/Accounts/ACfaa1a28aaed07a3f9e374269e7e05da2/Messages/SM32a1045276da47ca9342d64da3d40ce1>

日本の携帯にショートメールを送信する場合は 「+81」を先頭につけて、「090-0000-0000」の先頭の0を外したものをつなげる。 つまり、「+81900000-0000」を to に指定する。

実際にショートメールが飛んでくる。
Twilio のトライアルアカウントだと「Sent from your Twilio trial account - 」こんな文字列が付加されてくる。

ActiveAdmin で 編集内容を Ajax を使って反映させる方法

f:id:jetglass:20150902184838j:plain

概要


ActiveAdmin で作った管理機能でフォームの更新内容を Ajax で反映させるときの方法をまとめる。
coffee script でガリガリ書かないといけないこともあるが、単純にデータの保存・上書きであれば下記の方法で大体はいけるはず。

準備


Gemfile の編集。

tylergannon/toastr-rails · GitHub
この gem を使うと javascript でいい感じのトーストを表示できる。

gem 'toastr-rails'

gem のインストールをしたら、JS, CSS で toastr を読み込むようにする。

# vim app/assets/javascripts/active_admin.js.coffee
#= require active_admin/base
#= require toastr
#= require active_admin/user
# app/assets/javascripts/active_admin.css.scss
@import "active_admin/mixins";
@import "active_admin/base";
@import "toastr.css";

仕様


下記のようなテーブルがあるとする。
3つのテーブルで has_and_belongs_to_manyの関係になっている。

users admin_users memos
id id id
name login_id user_id
password admin_user_id
memo

とある AdminUser でログインし、User に対してメモを書き残したいとする。
User 詳細画面にメモのフォームがあり、そこに書き込んでボタンを押下すると画面遷移せずに Message を保存・上書きできること。

実装


ActiveAdmin の Rails 側の実装から。
active_admin_form_for でフォームを生成し、オプションでremote: true を渡すだけで Ajax 対応フォームになる。
既存の Rails と同じように使える。

# vim app/admin/user.rb
...
show do
  row :id
  ...
  # resource は User モデルのインスタンスが入っている(example/admin/user/1 で絞り込まれたもの
  # admin_user_id で絞ったものが取得できればそれを上書きするようにセットしておく
  # 取得できない場合は create で作成してしまって、それを上書きさせる(newだとボタンを押された回数レコードがインサートされる
  memo = resource.memo_by_admin_user_id(current_admin_user.id) || resource.memos.create({admin_user_id: current_admin_user.id})
  # remote: true の指定だけでこのフォームは Ajax 通信される
  active_admin_form_for([:admin, memo], remote: true, html: { id: "admin_memo"}) do |f|
    f.inputs do
      f.input :id, as: :hidden
      f.input :user_id, as: :hidden
      f.input :admin_user_id, input_html: {value: current_admin_user.id}, as: :hidden
      f.input :memo
      f.submit
    end
  end

Ajax での通信を受け取る側、パラメータを受け取ることを許可しておく。
中身の実装はなくても ActiveAdmin が自動で CRUD を実装してくれているので下記だけで基本問題なし。

# vim app/admin/memo.rb
ActiveAdmin.register Memo do
  # メニューを非表示にする
  menu false
  permit_params :id, :user_id, :admin_user_id, :memo
end

モデルの実装は省きます。
仕様で説明した3つのテーブルで has_and_belongs_to_manyの関係になっている。

Javascript 側では Ajax の通信によって、トーストを表示させる。

# vim app/assets/javascripts/active_admin/user.js.coffee
$ ->
  $('#admin_memo')
    .on 'ajax:success', (event, data, status, xhr) ->
      toastr.success "保存しました"
    .on 'ajax:error', (xhr, status, error) ->
      toastr.error "保存できませんでした"

以上。
これだけでそこそこの画面ができてしまう。

tylergannon/toastr-rails · GitHubgithub.com

今回の記事のポイントは↑かもしれない。

docker build すると ADD, COPY で no such file or directory になる問題の解決方法

docker 導入に関する記事を別で書くつもりだが、 今やっているプロジェクトで docker build で大ハマりしたので、 その解決方法をメモしておく。

概要


上記環境だが、特に yumリポジトリを更新することもなく、 下記を実行して Docker 1.6.2 をインストール。

yum install docker docker-selinux

チームで管理している Dockerfile があるので、 それを落として色々インストールした後、 docker build して docker pull する予定だった。

「no such file or directory」のエラーでビルドできない


Dockerfile は他の方が docker build 成功しているので、 俺の環境でもできるはずなのに build がどうやってもうまくいかない。

# vim Dockerfile
...
ADD test.txt /tmp/test.txt
...

上記のような Dockerfile で docker build を実行してみる。

ERRO[0000] Can't exclude whole path, excluding pattern: *
...
Error build: test.txt: no such file or directory

ツリー構造的には Dockerfile と test.txt は同じディレクトリに存在しているのにエラーが出る。

docker build をしたときには context という概念が登場する。
簡単に言うとテンポラリー領域のようなもの。

Dockerfile と同じ階層にあるファイル・ディレクトリを構築する docker 環境にテンポラリー的にコピーして持ち込み、 ADD や COPY で docker 環境にファイルを配置する。

なので、context の意味がわからないうちは下記のようなエラーを起こしてしまう。
Docker: adding a file from a parent directory - Stack Overflow

.dockerignore という存在


今回は context 内のファイルを指定しているので別の原因が存在していた。
.dockerignore というファイルだ。

*
!test.txt

ファイルの中身はこのようになっていた。
意図としては context にいちいちファイル・ディレクトリを全コピーすると重くなるため、 context には test.txt 以外はコピーさせないということだった。

* の記述を消してビルドするとあっさりうまくいった。

そして、実は根本的に他の原因があった。

docker のバージョンアップ


実は docker のイメージをビルドした方の docker バージョン(1.7)と、 自分の docker バージョン(1.6)が異なっていた。

そして、バージョンアップしたら、あっさり問題解決。

# cat >/etc/yum.repos.d/docker.repo <<-EOF
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

yumリポジトリを追加。
↓ docker をアップデートする。

# sudo yum update docker docker-selinux

バージョンが 1.7.1 になったのだが、.dockerignore を解釈できるようになり、

*
!test.txt

これで何もエラーが出ずにビルドすることができた。

まとめ


チームで使うソフトのバージョンはみんな合わせましょう・・・

Vagrant + VirtualBox で構築した環境を他の PC へコピー・移設する方法

f:id:jetglass:20150810182720j:plain

概要


MacBookPro から iMacVagrant + VirtualBox で構築した環境をコピーする。
開発中のソースは GitHub で管理されているのでどちらのマシンでも作業できるようになる。

  • コピー元 = MacBookPro
  • コピー先 = iMac

この仮想環境は CentOS 7 なので、ボックス名は cent7 にしている。

[コピー元作業]package.box を作成・転送する


MacBookPro でまず下記を実行してみる。

# vagrant box list
cent7 (virtualbox, 0)

box として cent7 が取り込まれていることがわかる。

cent7 の Vagrantfile が置いてあるディレクトリへ移動し、下記を実行する。

# vagrant package

実行したディレクトリに cent7 のpackage.boxが作成される。

AirDrop で MacBookPro から iMac へ package.box と Vagrantfile を送信する。

MacBookPro で行う作業はこれで終わり。

[コピー先作業]package.box を受けとって環境構築する


準備

下記サイトより VagrantVirtualBox をダウンロードしてインストールする。
確か両方とも dmg ファイルなのでインストールは簡単。

package.boxを取り込む

受け取った package.box と Vagrantfile を任意のディレクトリへ移動する。

# mv ~/Downloads/package.box ~/WorkSpace/cent7/.
# mv ~/Downloads/Vagrantfile ~/WorkSpace/cent7/.
# cd ~/WorkSpace/cent7/

package.box を取り込む

# vagrant box add cent7 package.box

下記を実行すると cent7 が取り込まれていることがわかる。

# vagrant box list
cent7 (virtualbox, 0)

環境を立ち上げてみる。

# vagrant up
# vagrant ssh

無事に立ち上がって完了。

まとめ


非常に簡単に仮想環境を他PCへコピーして動作させることができた。

当然だけど、仮想環境内の秘密鍵や git, ssh, bashrc, vimrc などの設定もまんまコピーされるので、 チームメンバーへ box ファイルを渡すときは注意が必要。

チームで仮想環境の運用を考えると chef でがんばって書いて管理していくか、 個人設定をしていないまっさらな box ファイルを管理していくのがよさげか。

自分用にコピーや移設する分には何も考える必要がなく快適!!

参考

Vagrantでexportした環境(box)を取り込む方法 - Qiita

vagrant + virtualboxで作ったRuby環境を他のPCに環境移行する方法 - Qiita