ハトネコエ Web がくしゅうちょう

プログラミングやサーバー・Web制作、チームマネジメントなど得た技術のまとめ

ConoHa ちゃんを裏切って DigitalOcean に移行した話

1. ConoHa とは

VPS(仮想個人サーバー)を提供するサービスをやっているのが ConoHa
美雲このは ちゃんがマスコットキャラクターで、なんとキャラクターサイトまであります!。

f:id:nekonenene:20190205230925p:plain
追う、美雲このはちゃん ( https://conoha.mikumo.com/wallpaper )

こちらを約2年に渡って使ってきたのだけれど、
ひょんなことから ConoHa を捨てて DigitalOcean へ移行しました。

どうして移行したのか。今日はそんなお話。

2. 移行する気はなかった

最初は特に移行する気はなく、
海外のベンチャーがよく使っているという話を聞いて
なんとなく DigitalOcean のアカウントを作ったまま放置していました。

最近、Ansible レシピをいちから作り直す際に、(昔のがメンテ出来ないレベルで汚かった)
せっかくだから使ってみるか〜と試しに使ってみたら、便利な側面にいろいろ気付かされてしまった……。

↑ Ansible をいちから作り直していたときに出来たブログです

3. メトリクスが取れる!

これがなにげにすごい!

いや、CPU程度であれば ConoHa などでも普通に取れるんだけど、
DigitalOcean のすごいところはサーバー(Droplet)作成時に「Monitoring」のチェックを入れることで、
CPU使用率だけでなく メモリ使用率やディスク使用量などを取ってくれて 、しかもそれを最長30日のグラフとして見られること!

f:id:nekonenene:20190205051600p:plain
Monitoring にチェックを入れる

f:id:nekonenene:20190205051634p:plain
グラフはこんな感じ。processes は精度が悪いから廃止されるらしい、残念

さらに気が狂っていることにアラートまで設定できて
ディスク使用量が一定を超えてしまったらメールもしくはSlackで通知を飛ばすことができる!!

このサービスがなんと無料で付いてくる!!!

Datadog にお金を払う余裕のないベンチャーにとっては、
これは最高にありがたい機能ですよ。

なお、Droplet 作成時に「Monitoring」へのチェックを忘れてしまった場合は、
サーバー内で curl -sSL https://repos.insights.digitalocean.com/install.sh | sudo bash と実行することで
データ取得を行う do-agent がインストールできるようになっています。
参考 : https://www.digitalocean.com/docs/monitoring/quickstart/

4. DNS もちゃんと付いてくる

上のモニタリング機能は、料金ページの『Tools & Services』タブの『Included Services』で触れられているんだけど、
同じページに DNSサービスも無料 で付いてくることが触れられています。

これは ConoHa にもあった無料サービスなので優位性ってほどではないのだけれど、
トップドメインのNSレコードを編集できるのは、ConoHa よりも柔軟な点。
DNSサーバーを別のサーバーへお引っ越しする際にはありがたい要素となるはず。

5. あと安い

安いとは聞いていたけど、改めて ConoHa と比べてみると安かった。

5-1. ConoHa の料金(2019年2月時点)

価格表: https://www.conoha.jp/vps/pricing/

メモリ CPU SSD 月額
512MB 1 Core 20GB 630円
1GB 1 Core 50GB 900円
2GB 3 Core 50GB 1,750円

普通に安い!

参考にさくらのVPSと比べてもらうとその安さがわかるかと……。
(さくらのVPSは月額料金だけでなく初期費用が取られるのがポイント・・・)

5-2. DigitalOcean の料金(2019年2月時点)

価格表: https://www.digitalocean.com/pricing/

最近は 1 ドル 110 円前後なのだけれど、
クレカ引き落としの為替はそれよりいくらか上乗せされるので、112 円として計算しました。

メモリ CPU SSD 月額
1GB 1 Core 25GB 560円 ($5)
2GB 1 Core 50GB 1,120円 ($10)
2GB 2 Core 60GB 1,680円 ($15)

さらに安かった!

CPUのコア数で負けているけど、だいたい個人使用だと、欲しいのは CPU のコア数よりも
メモリの容量だったりするので、
ConoHa の 512MB プランの料金 630 円よりも安い 560 円で、メモリ 1GB プランが使えちゃうのは良心的!!

さらには 3. で触れたモニタリング機能が無料で付いてくることを考えると、マジで安いな! と思います。

5-3. ちなみに AWS

なお、DigitalOcean で 月額 1,680 円 ($15) のメモリ 2GB, CPU 2 Core, SSD 60GB を
AWS で契約したらいくらなのか、ついでに計算してみました。

メモリ 2GB, CPU 2 Core はちょうど t3.small にあたるので、
0.0272 USD * 24 * 30 = 19.584 USD。
それに加えて EBS 汎用 SSD 60GB 分の月額料金は 0.12 USD * 60 = 7.2 USD。
合わせて 26.784 USD。月額 2999.808 円ですね。

月額 3,000 円か……2倍くらいしちゃうのか。
AWSの料金、まともに計算すると普通に高くてビビるな。

5-4. ついでに Vultr

そういえば最近名前を聞くなと思い出し、こちらの価格も確認。
価格表: https://www.vultr.com/pricing/

メモリ CPU SSD 月額
512MB 1 Core 20GB 280円 ($2.5)
1GB 1 Core 25GB 560円 ($5)
2GB 1 Core 40GB 1,120円 ($10)

おおむね DigitalOcean と同じ価格帯で、若干ストレージが負けてるくらいの様子。
これなら、わざわざ使ってみることもないかな。

5-5. 安さでは ServersMan

使ったことはないのですが、安さなら ServersMan@VPS がこれらよりもう少しお得。
ただしSSDでなくHDDなのと、安定性はわからないので、どなたか使ったことある人いたら教えてください。
価格表: https://dream.jp/vps/charge.html

メモリ CPU HDD 月額
1GB 不明 50GB 504円
2GB 不明 100GB 1,008円

6. 欠点は?

話を DigitalOcean に戻して、欠点を挙げるとするなら東京リージョンがないこと……?
と言っても、シンガポールリージョンで使っているけれど
SSHもWebの表示も全くもたつきを感じないので、これは欠点と言えるほどのものではなさそうです。

Swap file は ConoHa と違ってあらかじめ用意されてないので、作成する工程をちゃんと用意するのが注意点かな。

というわけで、DigitalOcean はいいぞ、っていう話でした。
このはちゃんごめんな……ごめんな……ごめんな……。

Docker の ARG の宣言箇所に注意

元はこういう Dockerfile を書いていました。

ARG RUBY_VER="latest"
ARG ENV_FILE_DIR="."

FROM ruby:${RUBY_VER}

WORKDIR /home/repository/src

ADD src /home/repository/src
ADD ${ENV_FILE_DIR}/.env .
RUN bundle install

CMD bundle exec foreman start

こうすれば、docker build 時に

docker build ./ \
  --build-arg RUBY_VER=2.6.1 \
  --build-arg ENV_FILE_DIR=/data/sample_app
  -t sample_app:latest

と指定して、任意のディレクトリの .env ファイルを置けるかと思ってました。

しかしそんなことはなく、2 つの誤りがありました。

1. ARG は FROM の後に宣言する

ARG を FROM の前に書いていいのは、FROM のタグ指定などの時のみで、
基本的に ARG は FROM のあとで宣言 します。

そうしないと、この ARG 宣言は無効化され、
${ENV_FILE_DIR} の値は空文字となります

つまり、以下の順序で書くのが正解でした。

ARG RUBY_VER="latest"
FROM ruby:${RUBY_VER}

ARG ENV_FILE_DIR="."

WORKDIR /home/repository/src

ADD src /home/repository/src
ADD ${ENV_FILE_DIR}/.env .
RUN bundle install

CMD bundle exec foreman start

Dockerfile において ADD のソース指定が ./.env/.env のとき実質同じファイルを指すために、
エラーが出ることもなかったので、このバグを作ってしまっていることになかなか気付けず苦労しました。

あまりにわからなくて RUN echo ${ENV_FILE_DIR} を挟んでみたら出力がなかったので気付けました……。

2. ADD や COPY で使えるソースは特定ディレクトリ以下

この stack overflow での回答で触れられているように、
docker build 実行時のPATH以下のディレクトリにあるファイルしか参照できません。

docker build の help に

Usage: docker build [OPTIONS] PATH | URL | -

とありますが、 このPATHディレクトリが、ADDやCOPYでのルートディレクト として扱われます。

先ほどの 1. で

ADD のソース指定が ./.env/.env のとき実質同じファイルを指す

と書いたのはそういうことです。

たいていの場合、Dockerfile のあるディレクトリで docker build をおこなうでしょうから、
大雑把な表現をするなら、Dockerfile のあるディレクトリ以下のファイルのみがソース対象になりえるとも言えます。

なお、この話は公式ドキュメント上でも

The <src> path must be inside the context of the build; you cannot ADD ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

と触れられていますので、build’s context の話と合わせて読むと良いかと思います。

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

コンテナ・ベース・オーケストレーション Docker/Kubernetesで作るクラウド時代のシステム基盤

Makefile の = と := と ?= (makeの基礎)

問題です!

以下のような Makefile があったとして、
それぞれの make test の出力結果は何になるでしょう?

Q1. =

x = foo
y = $(x) bar
x = later

.PHONY: test
test:
   @echo $(x)
   @echo $(y)

Q2. :=

x := foo
y := $(x) bar
x := later

.PHONY: test
test:
   @echo $(x)
   @echo $(y)

Q3. ?=

x ?= foo
y ?= $(x) bar
x ?= later

.PHONY: test
test:
   @echo $(x)
   @echo $(y)

ヒント!

ドキュメントです!

GNU make - How to Use Variables

答え

というわけで、上のドキュメントがわかりにくかったので
自分なりにまとめたかったための、この記事でした。

= (equal) , := (colon equal) , ?= (question mark equal) の挙動はすべて異なります。
特に = がよくあるプログラミング言語とは異なる挙動を示すので注意です。

A1. =

x = foo
y = $(x) bar
x = later

.PHONY: test
test:
   @echo $(x)
   @echo $(y)

答えは

later
later bar

です。注意すべきは、y の中身が「later bar」になっていることですね。

make において = は recursive expansion再帰的な展開)がなされます。

y = $(x) bar と定義したとき、 x の値が更新されるたびに y の値は更新されるのです。
なので、 x = later と再定義されたことで最初の x = foo はもはや関係なく、 y の値は「later bar」となっているのです。

A2. :=

x := foo
y := $(x) bar
x := later

.PHONY: test
test:
   @echo $(x)
   @echo $(y)

これの出力は

later
foo bar

です。一番わかりやすいのではないでしょうか。

ドキュメント上でも

Simply expanded variables generally make complicated makefile programming more predictable because they work like variables in most programming languages.

意訳すると『このシンプルな変数の展開は、多くのプログラミング言語での変数と同様の挙動をするので、複雑な Makefile をわかりやすくできます』といったことが書かれています。
Makefile での変数定義で := が使われることの多い理由がよくわかりました。

なお、もし1行目がない場合、つまり

y := $(x) bar
x := later

となっていた場合、未定義の x は空文字として処理されます。ですので y の値は「bar」の文字列になります。

A3. ?=

x ?= foo
y ?= $(x) bar
x ?= later

.PHONY: test
test:
   @echo $(x)
   @echo $(y)

最後のこちらの答えは

foo
foo bar

です。x が「foo」のままなのがポイントですね!

?=変数がまだ未定義のときのみ代入をおこなう演算子です。
最近のプログラミング言語ではこのような機能の演算子を実装されているものが多いですね。

なお、make のドキュメント上では conditional variable assignment operator条件付き代入演算子)と呼ぶそうです。

おわりに

make は昔からあるツールながら、ほとんどの環境にビルドインされているぶん、
Docker や AWS コマンドなど長いコマンドを呼び出すことの多い昨今においても、
ビルドツール以外の使われ方として好まれて使われます。

一方で、私のような若輩者にとって Makefile の書き方は正直わからず、
今回の変数定義の話になりました。 := がよく使われる理由がわかってスッキリです。

冒頭のクイズ、周囲のプログラマー仲間に出題してみると面白いかもしれませんよ!


Vue.js、完全に理解した(い)!【プログラミング実況・はじめての Vue.js編 #2】

最近はこんなのもやってます!