Androidはワンツーパンチ 三歩進んで二歩下がる

プログラミングやどうでもいい話

【3】GCEのVMインスタンスにDockerとDocker Composeをインストールする。他設定(スワップ領域追加、タイムゾーン設定)

これはHerokuからGCP無料枠にRailsアプリを引越ししたときにやったことシリーズの【2】の続きです。
GCE に 作成した VM インスタンス上に環境設定するところのメモです。

1. 公式サイト

2. 目標

  • スワップ領域を追加する
  • 時刻の設定をアジア(東京)に設定する
  • Docker をインストールする
  • Docker Compose をインストールする
  • おまけ  SELinux の無効化?

3. 参考サイト様

本当に参考になりました。ありがとうございます!

4. スワップ領域を追加する

RAM が 0.6GB と少ないこともあり、重い処理を行うとOut of Memoryでエラーとなることがあります。
これを防ぐためにスワップファイルを作成することにします。

私もdocker-compose buildコマンドで Docker イメージをビルド中に OOM が発生して処理が中断してしまいましたが、スワップファイルを作成後は一度も OOM が発生していません。

↓ これはエラーが発生した時のログです。

Installing mini_portile2 2.4.0
Fetching nokogiri 1.10.1
Installing nokogiri 1.10.1 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
    current directory: /usr/local/bundle/gems/nokogiri-1.10.1/ext/nokogiri
/usr/local/bin/ruby -I /usr/local/lib/ruby/site_ruby/2.5.0 -r
./siteconf20190222-30-1ixnrwg.rb extconf.rb --use-system-libraries
extconf failedOut of memory - /usr/local/bin/ruby
Gem files will remain installed in /usr/local/bundle/gems/nokogiri-1.10.1 for
inspection.
Results logged to
/usr/local/bundle/extensions/x86_64-linux/2.5.0/nokogiri-1.10.1/gem_make.out
An error occurred while installing nokogiri (1.10.1), and Bundler cannot
continue.
Make sure that `gem install nokogiri -v '1.10.1' --source
'https://rubygems.org/'` succeeds before bundling.
In Gemfile:
  rails was resolved to 5.2.2, which depends on
    actioncable was resolved to 5.2.2, which depends on
      actionpack was resolved to 5.2.2, which depends on
        actionview was resolved to 5.2.2, which depends on
          rails-dom-testing was resolved to 2.0.3, which depends on
            nokogiri
ERROR: Service 'web' failed to build: The command '/bin/sh -c set -x &&   apk add --update --no-cache $RUNTIME_PACKAGES &&  apk add --update  --virtual build-dependencies  --no-cache  $DEV_PACKAGES &&  gem install bundler --no-document &&  bundle config build.nokogiri --use-system-libraries &&  bundle install &&  apk del build-dependencies &&   cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime &&   apk del tzdata &&   rm -rf /var/cache/apk/*' returned a non-zero code: 5

分かりづらいので該当箇所のスクリーンショットも貼っておきます。

f:id:sakura_bird1:20190306014153p:plain:w400

それでは、スワップファイルの設定をします。
コマンドは次のように実行していきます。

$sudo fallocate -l 4G /swapfile
$sudo chmod 600 /swapfile
$sudo mkswap /swapfile
$sudo swapon /swapfile
$echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

このような感じで出来ました。
f:id:sakura_bird1:20190306015327p:plain:w600

5. Docker をインストールする

公式サイトを見ながら Docker をインストールしていきます。
これは Debian へのインストール方法ですので他のディストリビューションをお使いの方は対応した公式サイトをご覧ください。
Get Docker CE for Debian | Docker Documentation

5.1. Docker インストールのためのセットアップ

次のように実行していきます。

5.1.1. リポジトリのセットアップ

$sudo apt-get update

$sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common

5.1.2. Docker 公式の gpg キーを登録する

$curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

鍵の fingerprint(フィンガープリント)が9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 と表示されるのを確認します。

$sudo apt-key fingerprint 0EBFCD88

このような感じで表示されれば OK です。

$sudo apt-key fingerprint 0EBFCD88
 pub 4096R/0EBFCD88 2017-02-22  
 Key fingerprint = 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88  
 uid Docker Release (CE deb) <docker@docker.com>  
 sub 4096R/F273FCD8 2017-02-22

5.1.3. stable (安定版)リポジトリをセットアップする

$sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"

5.2. Docker CE のインストール

5.2.1. apt パッケージ・インデックスを更新する

$sudo apt-get update

5.2.2. 最新バージョンの Docker CE をインストールする

$sudo apt-get install docker-ce docker-ce-cli containerd.io

5.2.3. hello-world イメージを実行する

正しくインストールされているか確認のためhello-worldを実行します。

$sudo docker run hello-world

このように「Hello from Docker!」と表示されれば OK です。

f:id:sakura_bird1:20190306024624p:plain:w400

5.2.4. 特権のないユーザで Docker コマンドを実行できるようにする

現時点では Docker コマンドを実行する時はsudoが必要ですが、「docker」グループにユーザーを加えることで sudo なしで Docker コマンドを使用できるようになります。

※これはそのユーザーに Docker ホストにおける root 権限を付与することになるので信頼できるユーザーにのみ付与してください。

↓your-userをユーザー名に書き換えてください

$sudo usermod -aG docker your-user

このコマンドを実行後、一旦ログアウトして再ログインしてください。
次のコマンドでグループの設定を確認出来ます。

$cat /etc/group | grep docker

docker:x:999:sakuraのように表示されます。

先程のhello-worldsudoなしで実行できれば OK です。

6. Docker Compose をインストールする

引き続き公式サイトを見ながら Docker Compose をインストールしていきます。
Install Docker Compose | Docker Documentation

6.1. 最新バージョンの Docker Compose をインストールする

6.1.1. GitHub のリリースページをチェックする

Releases · docker/compose · GitHub
https://github.com/docker/compose/releases

Latest となっているバージョンをインストールします。

f:id:sakura_bird1:20190306030717p:plain:w300

6.1.2. インストールコマンドを実行する

「1.23.2」となっている箇所を最新のバージョンに書き換えてください。

$sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

6.1.3. コマンドを実行できるパーミッションを与える

$sudo chmod +x /usr/local/bin/docker-compose

$ docker-compose -vと実行してみて正常に結果が表示されれば OK です。

f:id:sakura_bird1:20190306031513p:plain:w400

7. 時刻の設定をアジア(東京)に設定する

f:id:sakura_bird1:20190304032933p:plain:w200

現在は時刻の設定が UTC となっていて9時間ずれています。
これを JST に変更します。

以下のコマンドを実行し、dbus パッケージをインストール

$sudo apt-get install dbus

アジア(東京)に設定します。

$sudo timedatectl set-timezone Asia/Tokyo

dateコマンドを打つと日付が JST になっていると思います。

8. おまけ  SELinux の無効化?

色々な参考サイト様を拝見しましたが SELinux の無効化をしているところが多いようでした。

How to enable SELinux on Debian “Stretch” 9 – Davide Giunchi
https://giunchi.net/how-to-enable-selinux-on-debian-stretch-9

上記の参考サイト様によると、Debian9 では SELinux のサポートはされているがデフォルトではインストールされていないとのことです。
なので特に何もしませんでした。

今回はこれで終わりです。
次回はVMインスタンスにファイルを転送する方法を書いてみたいと思います。

9. 関連リンク

【2】GCP(GCE)で無料のVMインスタンスを作る(Always Free無料枠、外部IPアドレス取得、SSH接続、22番ポート対応)

これはHerokuからGCP無料枠にRailsアプリを引越ししたときにやったことシリーズの【1】の続きです。
GCE に VM インスタンスを作成するところのメモです。

1. 公式サイト

2. 目標

  • Google Compute Engine に無料のインスタンスを作成する
  • 外部に公開する静的 IP アドレスを取得する
  • SSH 接続できるようにする
  • 22 番ポートを閉じて他のポートを開ける

3. 注意点

  • 無料枠を活用しているといっても完全に無料ではありません。ネットワーク流量や SSH ポートに攻撃されることでも課金されます。
  • この先インスタンスを停止・削除した場合、静的 IP を使用していると課金されるので必ず開放しておくのを忘れないようにしましょう。
  • アカウントを有料アカウントにアップグレードしたあと、Google から$0 ~ 1 のトランザクションが発生する場合があります。
  • 無料条件は公式サイトのAlways Freeを見ておくとよいです。https://cloud.google.com/free/docs/gcp-free-tier?hl=ja

4. 参考サイト様

本当に参考になりました。ありがとうございます!

5. 作業手順

  • 事前準備の内容を済ます
  • VM インスタンスを作成する
  • ディスクの設定をする
  • 22 番ポートを閉じて他のポートを開ける
  • SSH 接続できることを確認する
  • その他の設定を行う

5.1. 事前準備

参考サイト様の記事を参考に設定していきます。ここでは割愛させていただきます。

  1. GCP にアクセスする
    https://cloud.google.com/
  2. GCP でアカウントを作成
  3. プロジェクトを作成
  4. アップグレードした請求先アカウントを登録する
    https://cloud.google.com/free/docs/frequently-asked-questions#how-to-upgrade
  5. 課金アラートを設定しておく

5.2. VM インスタンスを作成する

Compute Engine を左側のペインからクリックし、VM インスタンスをクリックします。

f:id:sakura_bird1:20190303160747p:plain:w400

課金を有効にします。

f:id:sakura_bird1:20190303160901p:plain:w400

「アカウントを設定」をクリックします。

f:id:sakura_bird1:20190303161156p:plain:w400

課金情報とプロジェクトを結びつけると GCE が使えるようになります。
VM インスタンスを作成します。

f:id:sakura_bird1:20190303161331p:plain:w400

5.3. ディスクの設定をする

次の項目を設定します。間違えると課金対象になってしまうので慎重にやります。

作業項目 内容
名前 インスタンスの名前を入力する
リージョンとゾーン us-west1, us-central1, us-east1の中から選択する
マシンタイプ micro(共有 vCPU x 1 メモリ 0.6 GB f1-micro)を選択する
ディスクサイズ 10GB となっているので 30GB に変更する
ブートディスクの種類 標準の永続ディスクを選択する
OS イメージの選択 どれか OS を選択する
ファイアウォールルール HTTP, HTTPSトラフィックを許可するの両方にチェックを入れる
ネットワーキング 外部 IP のIPアドレスを作成新しい静的IPアドレスの予約の画面で名前を入力して予約ボタンをクリックする

自分のインスタンスを作ったときのスクリーンショットです。
f:id:sakura_bird1:20190303184819p:plain:w500

5.3.1. リージョンとゾーン

無料対象のリージョンは次の3つです。米国でもこれ以外は有料になります。

5.3.2. OS イメージ

公式サイトを参考に選択します。
イメージ  |  Compute Engine ドキュメント  |  Google Cloud

私は OS はデフォルトの Debian 9 stretch にしました。
今のところ特に困ったことは起きていません。

Docker をガッツリ使うのに適したContainer-Optimized OS なども用意されています。
しかし実は一度 OOM で Docker のビルドが失敗した時に swap 領域を設定して事なきを得たのですが、Container-Optimized OS ではやり方がわからなかったので避けときました。私がわかっていないだけかもしれませんが。
docker - How to enable Google Container Optimized OS swap limit support - Stack Overflow

5.3.3. ファイアウォールルール

f:id:sakura_bird1:20190303185016p:plain:w400

HTTP, HTTPS トラフィックを許可するの両方にチェックを入れます。
80 番と 443 番のポートが開きます。
SSL の設定のところで 80 番と 443 番が公開されている必要があります。

5.3.4. 静的 IP アドレスの予約

f:id:sakura_bird1:20190303185751p:plain:w400

ネットワーキングというタブをクリックしてネットワークインターフェース外部IP
のドロップダウンメニューの中からIPアドレスを作成を選択します。

f:id:sakura_bird1:20190303185859p:plain:w400

新しい静的IPアドレスの予約の画面で名前を入力して予約ボタンをクリックします。
グローバル IP アドレスが取得できます。

入力を終えたら作成ボタンを押します。
インスタンスが作成されます。

f:id:sakura_bird1:20190303190851p:plain:w400

外部 IP のところに取得した固定 IP アドレスが表示されます。
これを使って SSH 接続したり、DNS サーバーの設定をしたりします。
注意点として、VM インスタンスが起動していないと外部 IP アドレスが課金されてしまいます
使っていない IP アドレスは開放するようにしましょう。
ネットワーキング外部IPアドレス→ アドレスを選択 →静的アドレスを開放をクリックで開放出来ます。


6. SSH 接続できるようにする

仮想マシンインスタンス作成後、インスタンスに接続する方法は次のようになります。

ここでは主に 3 番目の公開 SSH 認証鍵をインスタンスに渡して SSH コマンドで接続する方法について書いてみたいと思います。
1 番目と 2 番めも軽く触れますと、

ブラウザからインスタンスを表示して、接続 SSHと書いてあるところをクリックするとブラウザウィンドウで開くとあるのでクリックするとターミナルが起動します。
簡単に接続できました。

f:id:sakura_bird1:20190303233114p:plain:w400

f:id:sakura_bird1:20190303233232p:plain:w400

2 番めの gcloud コマンドライン ツールを使用する場合は Cloud SDK をインストールして使用します。
詳しくは公式サイトをご覧ください。

gcloud compute  |  Compute Engine ドキュメント  |  Google Cloud


それでは、公開 SSH 認証鍵をインスタンスに渡してSSHコマンドで接続する方法について書いてみたいと思います。
なお接続の際にIPアドレスを指定するので、外部IPアドレスを取得している必要があります。

6.1. SSH 認証鍵を新規作成する

Linux / MacOS でコマンドを説明させていただきます。Windows をお使いの方は別途検索等で調べてください。

ssh-keygen コマンドを使用して新しい認証鍵を生成します。ユーザー名をコメントに追加するには、-C フラグを指定します。

$ssh-keygen -t rsa -f ~/.ssh/[KEY_FILENAME] -C [USERNAME]

秘密鍵へのアクセスを制限し、鍵の管理者だけが読み取れ、他の誰も書き込めないようにします。

$chmod 400 ~/.ssh/[KEY_FILENAME]

公開認証鍵を表示します

$cat ~/.ssh/[KEY_FILENAME].pub

6.2. SSH 公開鍵を登録する

メニューからCompute Engineメタデータを選択します。

f:id:sakura_bird1:20190304001055p:plain:w400

SSH認証鍵のタブを開いて認証鍵全体を入力という欄の中に先程表示した公開認証鍵の内容をコピペします。

f:id:sakura_bird1:20190304001832p:plain:w400

保存後次のようなコマンドで SSH 接続できるようになります。

$ssh [外部IPアドレス] -i ~/.ssh/[KEY_FILENAME]

7. 22 番ポートを閉じて他のポートを開ける

参考サイト様によると、SSH ポートに攻撃されることで数円課金が発生するようです。
これを防ぎたいので参考サイト様の手順に従って 22 番ポートを閉じて他のポートを開けることにします。

7.1. ファイアウォールルールの作成(新ポート)

ナビゲーションメニューから「ネットワーク詳細の表示」を選択します。

f:id:sakura_bird1:20190304004632p:plain:w400

ファイアウォールルール」→「ファイアウォールルールを作成」をクリックします。

f:id:sakura_bird1:20190304005102p:plain:w400

次の項目を設定します。
開けるポート番号は任意の数字です。

入力項目 内容
名前 デフォルトのルールにならって、 allow-XXXX (XXXX はポート番号)にするとよい
ターゲットタグ デフォルトのルールにならって、 allowXXXX-server (XXXX はポート番号)にするとよい
ソース IP の範囲 0.0.0.0/0
プロトコルとポート 指定したプロトコルとポートをクリックし tcp のところにポート番号を入力する

f:id:sakura_bird1:20190304005709p:plain:w500

f:id:sakura_bird1:20190304005728p:plain:w500

入力し終えたら「保存」を押して追加されたのを確認します。 ここで入力したターゲットタグをインスタンスのネットワークタグに追加します。

VM インスタンスの詳細」→「編集」画面でターゲットタグを追加します。

f:id:sakura_bird1:20190304010109p:plain:w400

7.2. sshd_config のポート番号の設定を変更する

以下のコマンドを実行し、設定ファイルをバックアップする

$cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org

エディタを起動して設定ファイルを書き換える

$sudo vi /etc/ssh/sshd_config

#Port 22 となっているので Port 40022 のように、先程開けたポート番号に書き換えます。

f:id:sakura_bird1:20190304011635p:plain:w500

保存したら SSH を再起動します。

$sudo service ssh restart

今までデフォルトの 22 番で接続していましたが、新しく開けたポート番号で接続するようになります。

$ssh [外部IPアドレス] -i ~/.ssh/[KEY_FILENAME] -p [ポート番号]

f:id:sakura_bird1:20190304022447p:plain:w500

gcloud コマンドでログインする時も-p [ポート番号]を付けることになります。
ブラウザからログインする時は「ブラウザウィンドウでカスタムポートを開く」を選択してポート番号を入力する必要があります。

ログイン出来たら 22 番のポートを閉じる作業に入ります。

7.3. ファイアウォールルールの作成(22 番ポート)

先程と同じく「ファイアウォールルールを作成」を開きます。
次の項目を設定します。

入力項目 内容
名前 デフォルトのルールにならって、 disallow-22 にするとよい
一致した時のアクション 拒否
ターゲットタグ デフォルトのルールにならって、 disallow22-server にするとよい
ソース IP の範囲 0.0.0.0/0
プロトコルとポート 指定したプロトコルとポートをクリックし tcp のところに 22 を入力する

f:id:sakura_bird1:20190304023921p:plain:w500

f:id:sakura_bird1:20190304023934p:plain:w500

入力し終えたら「保存」を押して追加されたのを確認します。
ここで入力したターゲットタグをインスタンスのネットワークタグに追加します。

VM インスタンスの詳細」→「編集」画面で先程作成した 22 番ポートを閉じるためのターゲットタグを追加します。

f:id:sakura_bird1:20190304024145p:plain:w400

22 番でアクセス出来なくなったと思います。

これで今回の記録は終わりです。

次回は作成したインスタンススワップ領域追加、タイムゾーン設定を行い、DockerとDocker Composeをインストールします。

8. 関連リンク

【1】HerokuからGCP無料枠にRailsアプリを引越ししたときにやったこと(GCE+Docker+Rails+Puma+PostgreSQL+Nginx+Let's Encrypt)

こんにちは。さくらです。

ポケット糖質量という Rails アプリを GCP(Google Cloud Platform)のサービスの一つであるGCE(Google Compute Engine)無料枠を使って公開しました。
以前から Heroku のサーバーで公開していたのですが、この度お引越ししました。
そこで色々な手順を踏んだわけですが、知識不足で大変でしたので忘れてしまわないようにメモしておきます。

www.pockettoushituryou.com

1. 前提

  • Rails5.2 で作った web サイトを作成済み
  • Heroku で公開済み(2017/4〜2019/2 まで)
  • SSL 対応済
  • 個人開発

2. 移転前(Heroku)の仕様

主な仕様 内容
サーバー OS heroku-16(Ubuntu 16.04)
作業ステージ production(Heroku), staging(Heroku), development(local)の3つ
DB の種類 production と staging は Heroku の PostgreSQL、development は SQLite3
Web サーバー よくわからない(Heroku がうまいことやってくれていた)
DNS サーバー Heroku
SSL 対応 Automated Certificate Management という Heroku の機能で簡単 SSL&証明書自動更新
デプロイ方法 Heroku Git を使ってソースコード push ですぐデプロイ
料金 Hobby プラン $7/Month

3. 移転後(Google Compute Engine)の仕様

主な仕様 内容
サーバー OS GCE(Google Compute Engine) + Debian9 + Docker
作業ステージ production(GCE), development(local)の2つ
DB の種類 PostgreSQL のみ
Web サーバー Nginx
DNS サーバー お名前.com
SSL 対応 Let's Encrypt の証明書取得&自動更新出来るコンテナを使う
デプロイ方法 Github からコードを pull した後手作業で Docker Compose のコマンドでデプロイ
料金 無料(〜数円)

4. 移転の目的

Heroku のサーバー代が月$7 は別に高くないっちゃないんですが、他にもっと安い VPS もあるし GCP の無料枠なら安心感があるし、自分のサイトはリソースを必要とするようなものではないのでコストダウンすることを決めました。

無料で動的サイトをホスティングするのに GCP の他にArukasもありましたが、Docker Hub 上に保管されているパブリックリポジトリにのみ対応だったので候補から外しました。
その他の候補としてはWebARENA の VPS クラウド が月額 360 円~で良さそうでした。
人気のようで、契約したくても在庫切れの時があるらしいです。

その他に Docker を触ってみたいという欲求があり、いい機会だから始めることにしました。
これは純粋に興味本位です。Heroku のような運用でも困ったりはしていませんでした。
Dockerが必要になることもなかったですし。

5. 移転の感想

移転のためのあれこれを経験して一番良かったことは、これから他のサーバーを利用する時があっても自分でも利用できそうだという感覚がつかめたことです。
用語や手順など、Herokuではあまり考えてなかった部分も雰囲気がつかめたのではないでしょうか。

今後自分がサーバーをいじるとしたらコスパの良いVPSサーバーを借りる可能性が高いと思います。
それなら今回の引越しで行った工程は全て役に立つと思います。
一つ可能性が拓けたと考えてもよいのかなと思っています。

大変だったことは、既存のプロジェクトを Docker 化することです。
Dockerファイルの記述などはサンプルみたいに短いのに、書いて動くまでに時間がかかりました。
学習はそれなりに時間がかかり今も勉強中です。

でもサーバー移転をしようと決めたことがよいプレッシャーとなり、投げ出さなくてすみました。
Docker はまだ使いこなせているというレベルではないものの、サブ PC のSurface Goという 10 インチの Windows 機で MacBook と同じようにコンテナを起動出来た時は感動しました。
ローカルに Ruby さえインストールしなくても動くというか、OS レベルから同一の環境を用意出来ますもんね 。

それとVM インスタンス上にアプリを動かせるまで持っていくのにも、わからないことだらけで時間がかかりました。
途中もっと簡単に出来る方法は無いのか?と思ったりしましたが、それって Heroku じゃんと結局 Heroku の優しさが身にしみたりしました。
今も Heroku で Web を始めて本当によかったと思っています。

初めてアプリを作るのでも大変なのに、サーバー環境の構築なんて力尽きていたかもしれません。
Rails の勉強中に Heroku が良いと勧めてくれたRails チュートリアルに感謝してます。
もちろん Heroku にもすごく感謝してます!

f:id:sakura_bird1:20190307012823p:plain:w500

6. 注意点

  • この記事は初心者が初めて VPS サーバーを構築した記録のため冗長気味に書いてあります。わざわざ書くほどでもない当たり前のコマンドなども書いてあります。
  • DockerでのDBの扱いに注意が必要です。
    ポケット糖質量のデータは csv ファイルから投入すれば出来上がり、しかも ReadOnly なデータです。
    ほとんどソースコードの一部のようなものなので、DB をコンテナの外に設定していません。
    コンテナを消せば DB もすべて消えてしまいます。
    ポケット糖質量独自の仕様によりこのような環境になっておりますので、参考にする時はご注意ください。
  • GCPの無料枠を使っていますが、完全に無料にならないことがあります。下りのネットワーク1G以上だったりSSHポートへの攻撃で課金が発生したりすることがあります。

7. 作業手順

下記の関連リンクの順番に作業していきます。
大雑把な内容はこのようになります。

  1. インスタンス作成
  2. VMの各種設定
  3. httpアクセスを可能にする
  4. httpsアクセスを可能にする

8. 関連リンク