【rails5.2 + mysql5.7】docker上にrailsアプリケーションを立ててリモートDBと繋ぐ
先週くらいからようやくdockerに入門しました!(遅い・・)
本とか自分のPC上では軽く触ったことあったのですが、業務でがっつりdockerで環境構築をしたことはなかったです。
そして今回業務で環境構築する際に、
「どうせならdockerでやろう」
と思って作業してみたもののちょびっと詰まったところがあったのでこれから入門する人の参考になればと思いログとして残しておきます!
構成
rails5.2、mysql5.7で作ろうと思っていました。
dockerの公式のチュートリアルでもありますが、結構docker上にアプリケーションとDBの両方置いちゃうケースがあると思います。
なので僕も最初これで環境作ろうと思っていました。
ただ今回の環境構築では新規DBを作成ではなく既存のDBを使いたい!!
既存のDBをダンプしてそれを新規DBでリストアするか〜とも思いましたが、データ量かなり大きそうで断念。。。。
ということで結局この構成にしました。
初めての構成だったので本当にできるのか不安だったのでまずはローカルからリモートのDBに繋げられるかを確認。
リモートDBサーバーのホスト名(xxx:xxx:xxx:xxx)
ユーザー名(hoge)
データベース名(database_name)
$ mysql -h xxx:xxx:xxx:xxx database_name --port=3306 -u hoge -p
結果は
bash: mysql: command not found
それ以前の問題でしたwww
brewを入れているのでmysqlの5.7をインストールした後にもう一度実行しました
$ brew install mysql@5.7
$ mysql -h xxx:xxx:xxx:xxx database_name --port=3306 -u hoge -p bash: mysql: command not found
結果は変わらず・・
$ which mysql
と打っても何も出ないので、パスを通すことにしました。 (なぜこうなるのかは後で調べるつもりです) 僕は.bash_profileにいつも書くのでそこに追記します。
$ echo export PATH=/usr/local/opt/mysql@5.7/bin:$PATH > .bash_profile $ source .bash_profile $ which mysql /usr/bin/mysql
準備できた。
$ mysql -h xxx:xxx:xxx:xxx database_name --port=3306 -u hoge -p Access denied for user
おっふ、、、弾かれましたな。
インフラチームに聞いたところローカルからは直接繋げられないよ、とのことでした。
なので踏み台を利用して繋ぐ方針に変更。
トンネル掘って繋げれるようにしました。
(「sshポートフォワーディング」とかでググると出てくると思います)
僕の場合、ローカルから踏み台サーバーへは
ssh 踏み台サーバーのホスト名
でログインできていたので以下になりました。
$ ssh -NL 3307:db_host:3306 ssh_host $ db_hostはデータベースのホスト名 ssh_hostは踏み台のホスト名
接続確認
$ mysql -h 127.0.0.1 -P 3307 -u db_user -p > これでmysqlにログインできるはずです db_userはデータベースログインのユーザ名
やめたかったら
$ ps aux | grep ssh
とやると、フォワーディングしているプロセスが出てくるのでkillすればokです!
ここまできてようやく今回の構成が決まりました汗。
dockerからローカル経由してフォワーディング先のリモートDBに繋げそうですね。
コード
あとはdockerからローカルのところを実装すればうまくいきそうです!
なのでコードを書いていきましょう。チュートリアルと同じなので迷うこともないかなと思います。
まず作業するディレクトリを作り、その上でDockerfileとdocker-compose.ymlとGemfile、Gemfile.lockを作ります。
$ mkdir work $ cd work $ touch Dockerfile $ touch docker-compose.yml $ touch Gemfile $ touch Gemfile.lock
そして各々コードを記述していきます。
Dockerfileの中身 FROM ruby:2.5 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /myapp WORKDIR /myapp COPY Gemfile /myapp/Gemfile COPY Gemfile.lock /myapp/Gemfile.lock RUN bundle install COPY . /myapp
Gemfileの中身 source 'https://rubygems.org' gem 'rails', '5.2.0'
Gemfile.lockは空。
docker-compose.ymlの中身 version: '3' services: web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp ports: - "3000:3000"
コンテナ上でrails newします。
$ docker-compose run web rails new . --force --database=mysql
新しいファイルができたらconfig/database.ymlを修正します。 ここ最初どう書けば良いのか迷いましたが最終的にこれでいけました!
default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: リモートDBのユーザー名 password: リモートDBのパスワード host: docker.for.mac.localhost port: 3307 development: <<: *default database:リモートDBのデータベース名
dockerからローカルのMacを見るときはdocker.for.mac.localhost
で見てくれるそうです!
あと今回、フォワーディングのポートを3307にしているのでport: 3307
にしています。
ここも適宜変更してください!
ここまでできたらあとは起動するだけです!
$ docker-compose up --build
localhost:3000にアクセスするとお馴染みの画面が表示されるはずです。
全然関係ない話。
今回初めて知ったのですが、Active Recordって使えるmysqlのバージョンがあったんですね笑。 ORマッパーもあるし、よくよく考えると当たり前なんですが意識したことが一度もなかったです!
というのも今回既存のDBのmysqlが5.0.9という状態で・・・アクセスしたら
Your version of MySQL (5.0.9) is too old. Active Record supports MySQL >= 5.1.10.
という見たことないエラー出てちょっと感動しましたw こういうところもしっかりみておきたいですね!
終わり。。
awsサービス cloudformationが想像以上に良い!!
以前サーバー移行の話をちらっとだけ書きました。
デプロイ方式はBlueGreenでやっています。
この時、環境構築するのにcloudformationを使用していました。
テンプレートに記述するだけで新規・既存問わずに自由に設定できます。
僕の時は「既存のVPCの中の既存のセキュリティグループにインスタンス2台(web機とapplication機)を構築する」という感じで作っていました。
でロードバランサーにALBを使いたかったので、2台立てることになりました。
ALBはpublicにしかアタッチできないとか聞いてなかったです笑
本当はこうしたかった でもこうなった
publicにweb機(nginx)、privateにapplication機(unicorn)をおくことにしました。で、この時cloudformationでここの関係性も定義しました。こういうのを用意しておいてくれるのは本当に助かりました。
良かったところ①
インスタンス構築時にこういうプロパティ宣言ができるようになっています。
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#! /bin/bash -v\n",
"yum update -y\n",
"yum install -y nginx\n"
]]}}
なのでnginxインストール済みのインスタンス作成できちゃいます。
しかもこれ結構よくてnginxの/etc/nginx/test.confファイルに
こう書いておく
location / {
proxy_pass http://private_ip_address:8080;
}
cloudformatationのnginxのインスタンスのUserData
にこう書く
"sudo sed -i \"s/private_ip_address/",
{
"Fn::GetAtt": [
"Ec2Instance",
"PrivateIp"
]
},
"/g\" /etc/nginx/test.conf \n",
]]}}
そうするとnginxインストール済みインスタンスとunicornを設定済みインスタンスの繋ぎこみ完了している状態で作成されます笑。これできた時は少し感動でした。
良かったところ②
lambdaが使えるところww
インスタンス立ち上げ終わったあとに、lambdaキックさせてターゲットグループの入れ替えというのをやりたかったんですけど、この辺もカバーしてくれて助かりました笑。
それを実現するためにカスタムリソースってのが用意されてます。
"CustomResource" : {
"Type" : "AWS::CloudFormation::CustomResource",
"Properties" : {
"ServiceToken": "lambdaのARN",
"Test1": {"Ref": "InstanceName"},
"Test2": {"Ref": "TargetGroupName"}
}
}
ServiceTokenってのにlambdaのARN入れるだけで構築し終わった後そのlambdaを叩きにいってくれます。しかもTest1といった任意の文字列もeventの一部として渡せます!便利なんですけど、ここで詰まったポイントがあります。
詰まりポイント
lambdaにある記述を書かないとcloudformationのタスクがプログレスのまま終わらない・・・そして一時間後くらいにfailedとなってしまう。
なんか cfn-response モジュールなるものが必要らしいです。
cfn-response
モジュールは、ZipFile
プロパティを使用してソースコードを作成した場合にのみ使用できます。S3 バケットに保存されたソースコードには使用できません。S3 バケットのコードでは、独自の関数を作成してレスポンスを送信する必要があります。
とあります。これURL見てもらえらば良いのですが、
"ZipFile": { "Fn::Join": ["", [
"var response = require('cfn-response');",
"exports.handler = function(event, context) {",
" var input = parseInt(event.ResourceProperties.Input);",
" var responseData = {Value: input * 5};",
" response.send(event, context, response.SUCCESS, responseData);",
"};"
上記のようにcloudformationの中に直接コードを書きましょということです。
・・・・・いや、さすがにそれはいやだよ?w
ってことでマネジメントコンソールの方に記述したいからこの方法とったのに・・・と思ったんですがgithubみるとこんな感じ。
結局、cloudformation側にレスポンス返せばいいだけだったので自分で実装してしおうと思いました。(まあコピペですな)lambda側に以下を書いてあげれば良い。
var SUCCESS = "SUCCESS";
var FAILED = "FAILED";
var cfnResponse = function(event, context, responseStatus, responseData, physicalResourceId) {
var responseBody = JSON.stringify({
Status: responseStatus,
Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
PhysicalResourceId: physicalResourceId || context.logStreamName,
StackId: event.StackId,
RequestId: event.RequestId,
LogicalResourceId: event.LogicalResourceId,
Data: responseData
});
console.log("Response body:\n", responseBody);
var https = require("https");
var url = require("url");
var parsedUrl = url.parse(event.ResponseURL);
var options = {
hostname: parsedUrl.hostname,
port: 443,
path: parsedUrl.path,
method: "PUT",
headers: {
"content-type": "",
"content-length": responseBody.length
}
};
var request = https.request(options, function(response) {
console.log("Status code: " + response.statusCode);
console.log("Status message: " + response.statusMessage);
context.done();
});
request.on("error", function(error) {
console.log("send(..) failed executing https.request(..): " + error);
context.done();
});
request.write(responseBody);
request.end();
}
exports.handler = (event, context, callback) => {
// TODO implement
if(event['RequestType'] == 'Delete'){
cfnResponse(event, context, SUCCESS, {});
}
console.log(event);
cfnResponse(event, context, SUCCESS, {});
};
これで無事lambdaにキックさせ、かつタスクもちゃんと終わってくれます。
まとめ
さすがAWSって感じですね!
ちゃんと手を届かせてくれるあたりがユーザーとしては満足度高いです。
もっと知ればいろんなことができそうなので他のサービス含め触り倒していきたいなって思います。
あっGoogle I/O見ないと・・・・
終わり。
データベース入門②
もうすぐGWに突入にします。。。
結婚式の余興動画も作り終えたのでまた書いていきたいと思います。
まああとせっかくGWでまとまった時間取れるのでサイトの速度改善やら新しい技術入れたり何やらをやりたいのでね。。
とりあえずデータベース入門はとっとと読み終えて他のことしたいなと思ったので急ピッチで進めてます笑。
さて、久しぶりのデータベース入門です。
前回から読み進めましたが、8章くらいまでは論理値の説明と正規化の必要性とどうやったら正しくDB設計できるのかという説明でした。ここに関して個人的には「知っている人多いし、軽く流し読みする程度でいいかな」という感想です。それくらいで理解できる内容だと思います。
ってことで8章〜9章くらいからの内容に触れていきます。その内容とは以下です。
select文の使い方
まずはSQLの基本ですね、select文です。こいつは何をするやつなのか・・データ取得できる唯一の存在です!
書き方はこんな感じ、説明するまでもないですね。
SELECT カラムのリスト
FROM テーブルのリスト
WHERE 検索条件
これにいろいろ条件を付け加えることができます。集計結果を出したいなら
SELECT count(カラムのリスト)
FROM テーブルのリスト
WHERE 検索条件
重複省いた集計結果なら
SELECT count(distinct カラムのリスト)
FROM テーブルのリスト
WHERE 検索条件
集計結果に制限をつけたい時は
SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) <= 30
とcountで取得したものに<=30といったような制限をかけることで取得することができます。今回だと30以下という制限をかけました
ここで人数少ない順にしたいときはサブクエリ使っても良いのですが、せっかくなのでorder byを使ってみます
SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) <= 30
ORDER BY COUNT(*) ASC
ちなみにこれ順番大事です笑。group byしてからhavingしてorder byしないとエラリますので気をつけましょ。上から順に読んでいくので今回だと「グループに分けて、それぞれを集計した結果を制限して最後、集計結果順に並べてみる」になります。イメージはつきやすいかなと思います。
サブクエリの説明もあったのですが、結局それはこれらの組み合わせでしかないので割愛しました!
今回はここまでとします。
軽〜い内容でした笑。
データベース入門もあとは
・インデックスの説明
・リファクタの仕方
・実際にアプリケーションを扱うとき
・トランザクションについて
この4つで本は終わりにしようかなと思います。
そのあとにrailsのときのjoinとinner_joinの違いの説明を軽くやってDB周りは一旦終えようかなと思います。(アンチパターンもやるかもですが)
GW前までには終わりそうですね、、よかった。
終わり。
reactをまだマスターしていなかった件
「え?こんな書き方あるのか、知らなかったわ〜」と思ったのでメモる笑
まあまずはこれですな・・・
ループ処理
配列のループ処理!意識していなかったわけではないんですけどね、、反省。。
forEach
連想配列(object)だと使えないんですけどね、ただ指定のarrayを回すときに使う
[1, 2, 3].forEach( (element, index, array) => {
console.log(index + ":" + element);
});
indexとarrayは省略可能ですー!
map
新しい配列を作成したいときに使う感じですな
const elementSquareArray = [1, 2, 3].map( (element, index, array) => {
return element * element;
});
こちらもindexとarrayは省略可能でっす!returnで返してあげましょ!
filter
条件にあうものだけを抽出したいときに使います
const evenNumberArray = [1, 2, 3].filter( (element, index, array) => {
return (element % 2 === 0);
});
reduce
処理をして1つの値を取得。
previousValueは前の値というより、それまでの結果と考えるとわかりやすいかもです
const total = [1,2,3].reduce( (previousValue, currentValue, index, array) => {
return previousValue+currentValue;
});
### total=6になる
every、some
これ使ったことないですけど・・・
everyは条件を全ての値が満たすか、someは条件を満たすものがあるかの判定。
結果はbooleanで返ってくるらしいです
const everyEvenFlag = [2, 4, 6].every( (element, index, array) => {
return (element % 2 === 0);
});
const someEvenFlag = [1, 2, 3].some( (element, index, array) => {
return (element % 2 === 0);
});
render
なにを返すのか問題ですね、返す型はそろえましょ!
はい、すみません。僕は適当にやってました・・・
何も描画したくないときにnullまたはfalseを返すことでそれを実現することができます。実際には裏で<noscript>タグを描画します。 なんでそういうときは
return <noscript/>
とするとよいかもですね
JSXのif文
jsx内のrender部分でif文書くとき即時間数を使って書くことが多いと思いますが、いかんせん括弧が多くて見にくくなってしまいます。
{(() => {
if (this.props.count >= 3) {
return (componentとかviewを返す);
}
})()}
こんなときに使える書き方があります、それがrenderのときの理論です。falseやnullのときはなにも表示されないのでそれを使うと以下になります。
{(this.props.count >= 3) && (
return (
componentとかviewを返す
)
)}
見やすい!!
わかると思いますが、最初のif文でtrueのときの処理しか使えません。なので最初からif~elseで分けるものに対しては即時間数で書くしかありません。
react使って3ヶ月くらいですが、まだまだ知らないことがありそうなので詰めていきたいものです。
終わり。
railsとrubyの相性
rubyとrailsのバージョンを上げることになったが、一つ疑問に思いました。
適当にどっちも手間なくあげれるとこまで上げれば良いのかな・・・??
ビルド時にどのくらい速度に差があるのか気になったので調べてみました。
準備
ruby 2.2.0、2.3.0、2.4.0をrbenvでインストールしておく
コード
RUBY=("2.2.0" "2.3.0" "2.4.0")
for ruby in ${RUBY[@]}; do
export PATH=$RBENV_ROOT/shims:$PATH
rbenv global $ruby >/dev/null 2>&1
RAILS_VER=("4.0.13" "4.2.8")
for rails_ver in ${RAILS_VER[@]}; do
gem install rails -v $rails_ver >/dev/null 2>&1
if test $rails_ver = '4.0.13' ; then
gem uninstall rails -v "4.2.8" >/dev/null 2>&1
gem uninstall railties -v "4.2.8" >/dev/null 2>&1
else
gem uninstall rails -v "4.0.13" >/dev/null 2>&1
gem uninstall railties -v "4.0.13" >/dev/null 2>&1
fi
rbenv rehash
ruby -v
rails -v
rails new rails_${rails_ver}_speedtest -d mysql >/dev/null 2>&1
echo "gem 'spring'" >> ./rails_${rails_ver}_speedtest/Gemfile
cd ./rails_${rails_ver}_speedtest
bundle install --path vendor/bundle >/dev/null 2>&1
bundle exec spring rails g scaffold blog title:string description:string >/dev/null 2>&1
echo spring
for i in {1..10};do
bundle exec time spring rake routes | grep real
done 2> routes.txt
awk -f ../ave.awk routes.txt
cd ..
rm -rf ./rails_${rails_ver}_speedtest
done
done
結果
何度もやってもこのくらいに落ち着くのでやはりビルドに差があると言ってもいいのではないでしょうか。。。ちょっと今回はしょりすぎてrake routeでやったのがセンスなかったですね笑
あと追加でrails5もやったっていうのがruby2.2.0を使っているところからバレバレですねw
まとめ
ただ今回rake routeでやってしまったので差があまり明確にならず。
またバージョンのどこに差があるのかというところまで調べていない。
DBの本を読み終わった後、ここについてもう一度追加調査していたいと思います。
終わり。
データーベース入門①
さて、宣言通り技術についてアウトプットしていこうかなと思います。
題材は「DBについて」です!
Webアプリケーションをずっと作ってきたのでアプリケーション周りは結構強いのですが、DB周りについてはまだまだ穴があるので今回はそこについて「理論から学ぶデーターベース実践入門」を読んで抑えていきたい思います。
理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)
- 作者: 奥野幹也
- 出版社/メーカー: 技術評論社
- 発売日: 2015/03/10
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (18件) を見る
まずは第一回ということでそもそものところから書いていこうと思います。
- データベースとは
ここからやらなくてもいいんじゃない?と思いますが、一応やっておきます笑。
wikipediaさんに聞いてみると
データベース(英: database, DB)とは、検索や蓄積が容易にできるよう整理された情報の集まり。 通常はコンピュータによって実現されたものを指すが、紙の住所録などをデータベースと呼ぶ場合もある。 狭義には、データベース管理システム (Database Management System, DBMS) またはそれが扱う対象のことをいう。
つまり特定のテーマに沿ったデータを集めて効率的に管理し、使いやすくしたものと考えてもらって良いと思います。ちなみにもう少し調べてみたら実は・・・・
データベースという名称は米軍からきているらしいです。第二次大戦後の米軍が、そこにアクセスすればすべての情報が得られるように、点在していた膨大な量の資料をひとつの基地に集約して効率化を図ったらしいです。この際にデータベースという言葉が誕生したと言われているらしい・・
そしてそんなデータベースですが種類があります!大きく分けると以下4つに分けることができます。
「階層型」「ネットワーク型」「関係型」「NoSQL」
一つずつ説明していってもよいのですが、ちょっとそれをしちゃうと肝心の話まで届かないで終わってしまう気がするので割愛します笑
参考リンクを貼っておきますので興味のある方はこちらをどうぞ!!
ざっくり説明が書いてあります↓
図がわかりやすいかもです↓
NoSQLについての説明あります↓
業務ではSQLを使用しているのでRDBについて書いていきますー
( ´ ▽ ` )ノ あっ「関係型」のことです。
- SQLとは
SQLとは、リレーショナルデータベース(以下RDB)に対して問い合わせを行うための言語のことです。そしてSQL はリレーショナルモデルをベース設計されておりリレーショナルモデルに沿った演算が得意です。なのでSQLを理解するにはRDBについて理解しなければならないということになります。逆にいうとRDBを理解しないとSQLについて理解できたとは言えずそれは単になんとなく書けるというレベルでしかありません。
- リレーショナルモデル
現実世界のデータを「リレーション」と呼ばれる概念を用いて表現するデータモデルのこと。ここで注意したいのがあくまでも、リレーショナルモデルが表すデータモデルは 設計という意味ではなく、データをどのように表現するか、という概念の話だということ。「○○という概念を使ってデータを表現してください」という決まりごとがデータモデルであり、リレーショナルモデルはその中の一つにすぎないということになります!
- リレーションとは
最もよくある間違いとしてあげられていたのが、「テ ーブル同士の関係」というものです。概念にすぎないという説明をしたと思うので理解されていると思いますが、テーブル同士の関係を(ER 図などを使って)デザインするのはリレーショナルモデルではありません。SQLにおいてリレーションに相当するものは、テーブルです!
言葉だとだとわけわからないと思うのでずを載せておきます。
説明書きとしては以下でした。
リレーショナルモデルにおけるリレーションの定義は次のようなもので す。リレーションは見出し(Heading)と本体(Body)のペアで構成されます。 見出しは、0でないn 個 の属性(Attribute)の集合です。この属性は、名前とデー タ型のペアになっています。本体は、属性値の集合である組、あるいは英 語で言うとタプル(tuple)の集合です。
タプルに含まれる属性値は、名称とデータ型が見出しで指定されたものと、それぞれ一致していなければなりません。
見出しで定義されていない属性が存在したり、逆に見出しに含まれる属性がタプルに存在していない場合は、ルール違反です。
つまりリレーションとはタプ ルの集合であり、タプルはすべて同じ n 個の属性値の集合という同じデー タ構造を持っています。図 1.1 は、リレーションをイメージ化したもの。
今回はここまでにしておこうかな・・・ここまで理解するとわかりますが、結局集合体でしかありません。だからもっと理解を深めるにはその集合体の話を知っておく必要があります。なので次はそこから始めれればなと思います。
終わり。
サーバー移行時のざっくりとした手順と考えるべきこと
ちょっとした記憶の整理。
2016年の10月くらいから2ヶ月間かけて事業の全サーバーをGMOクラウドからAWSへサーバーを移行したのでそのときの手順。本当は終わった直後に書けば記憶が鮮明なので詳細に書けたのに・・・それを言っても仕方ないのでとりあえず思い出せるだけ思い出します。
と話に入るまえにこういった大きなことをするときのポイントを述べておきます。それは
既存の環境(GMOクラウドの環境)をなるべくそのまま新規の環境へ(AWS)へ移す
これ結構大事です!移行しようとして色々調べたりすると「あれ?これいらなくね?」とか「え?これこのバージョンなの?あげたほうがよくね?」といったものが結構多く出てきます。しかしここはぐっとこらえて一旦、目を閉じましょう。もしリファクタリングみたいなことを同時にしてしまうとエラーになったときに、問題の原因特定が極めて困難になります。
ちなみに僕はアプリケーション側のサーバー設定のときに設定ファイル含めリファクタリングしながらやってしまい、結構困りました。エラーになったとき「新規のサーバーの設定ミスなのか?それともリファクタリングしたときのミスなのか?」と原因推測の範囲が分散してしまいわけわからなくなりました。もしこれをリファクタリングしないで進めていたとすると、既存の環境では動いていたのは事実なのでサーバーの設定ミスっぽいなと、ある程度明確に当たりをつけられます。もし古いものを新しくするときはこのことを覚えておくと結構早く物事を進められるかもしれません。
話を戻して以下が手順です。
- 既存のネットワーク、サーバー構成の確認
新規で0→1のサービスを作るならこんなこと考えなくて調べて洗い出してみたいなことをやらなくていいし、やるとしてもおそらく今だとgithubとかでどういう設計にしたのかを残しておくと思うのですが。。うちの事業は10年くらい前からやっていてそのときの記録が一切ないので現状を把握することから始めました。
- 既存で使われているライブラリやツールの確認
うちはnginx→unicornでサーバーが構成されていました。各々のサーバーでどんなミドルウェアが使われいるのかを確認します。
**ここまでが現状の理解になります**
- 新規のネットワーク・サーバー構成の考案
ここは全体設計の話なのでかなり楽しかった記憶があります笑。サーバーの移行なんてそうそう行うものではないので「自分の考えた構成が残っていくのかぁぁぁ」と深く感動したものです。ただこの頃インフラなんて触ったことなかったので設計と言われてもなにがなんだか・・という感じでした。
なのでキャッチアップしながら進めました。以下が流れです。
1:とりあえず「サーバー移行」と適当にググったりインフラの本読んだりする。
Amazon Web Services 基礎からのネットワーク&サーバー構築
- 作者: 玉川憲,片山暁雄,今井雄太
- 出版社/メーカー: 日経BP社
- 発売日: 2014/07/16
- メディア: 単行本
- この商品を含むブログ (4件) を見る
2:それらを見て・読んでなんとなくの全体像を把握。名前すら知らなかったのもあったのでここでは本当に「こんな感じなのかー」という感覚をつかむ程度。
3:(自分の環境を作ってまずは遊んでみるのもあり)
4:設計の本を読んだり、他社さんのを参考にしたりする。以下を読みましたね。あとはAWSのブログとか見てたような気がします。
Amazon Web Services パターン別構築・運用ガイド
- 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2015/03/25
- メディア: 単行本
- この商品を含むブログ (2件) を見る
Amazon Web Servicesクラウドデザインパターン設計ガイド 改訂版(日経BP Next ICT選書)
- 作者: 玉川憲,片山暁雄,鈴木宏康,野上忍,瀬戸島敏宏,坂西隆之
- 出版社/メーカー: 日経BP社
- 発売日: 2015/07/21
- メディア: Kindle版
- この商品を含むブログを見る
5:4まででなんとなく設計に必要そうな技術がわかるのでとりあえずそれらを知っておく、また似たようなことができるのもあるのでそれらの違いを理解する。僕の中では「elastic beanstalk / opsworks / cloudformation」の違いがよくわからなかったのでそれを結構調べましたww
6:以上のことを踏まえて設計を考える。真似でも良いと思います。その候補が上がったら、各々の候補同士でメリットデメリットを考える
7:デメリットを考えるときは「一番最悪のことが起こったときどう対処できるのか」という基準を持つとすっきりします。
全体の話に戻します。この先は言わずもがなですね。
- 実際に構築
実際に作る前に部分部分で小さく作って問題ないのかの検証して、できなさそうならもう一度考えて作って検証するというのの繰り返しをやって「できる!」となった時点で実際の全体構築に入りました。
- 全体のテスト
アクセステストやらDBがちゃんと動いているのかといったテストをしました。
- 本番環境にする
というのが僕がやった時の流れです。実際に作るときには、「これできるのか?」みたいな検証に時間がかかってたような気がします。そんな時はAWSのサポートに問い合わせてみると答えが返ってくるかもしれません。最終こんな感じになりました。
こだわったポイントは以下ですかね笑
・この図だとわかりませんがcapistrano deployからblue green deploy方式に変えた
・この図だとわからないかもしれませんが、セキュリティ面強化のためにweb機をpublicにapplication機をprivateにおいた
・AMIを主体にcloudformaiton一発でこの環境ができるようにした
最後に・・・・
最近は、そろそろGCPを触る時が来たかなと思っているのでAWSからGCPに移行してみたというのもやってみようと思っています。
終わり。