RailsでBasic認証・Dockerで環境変数を設定

Basic認証の処理を書く

class ApplicationController < ActionController::Base

  before_action :basic_auth
  protect_from_forgery with: :exception

  private
  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV.fetch('BASIC_AUTH_USER') && password == ENV.fetch('BASIC_AUTH_PASSWORD')
    end
  end
end

ENV.fetch('BASIC_AUTH_USER') ENV.fetch('BASIC_AUTH_PASSWORD')環境変数で設定しているものを参照する



環境変数の設定

環境変数とは

パスワードや秘密鍵など、Githubに載せて行きたくない・漏らしてはいけない情報を、サーバーなどのOSに保存しておき、 それをアプリケーションに渡す仕組み

dockerで環境変数を設定する方法

設定したい環境変数をまとめたファイルを作成

BASIC_AUTH_USER=user
BASIC_AUTH_PASSWORD=password

docker composeファイルに設定を追記

version: '3'
services:
  app:
    container_name: "app"
    build:
      context: .
      dockerfile: Dockerfile
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - 3000:3000
    external_links:
      - db
    volumes:
      - .:/app

    # 追記
    env_file:
      - .env

Railsアプリケーションを本番環境に構築するためのAWSでやったこと

ECRにrailsアプリケーションをプッシュ

  1. ECRでリポジトリを作成

  2. dockerイメージをプッシュ

// docker-compose.ymlまで移動しておく

// awsコマンドでログイン
$(aws ecr get-login --no-include-email --region ap-northeast-1)

// ビルド
$ docker build -t new/repository .

// イメージにタグをつける
$ docker tag new/repository:latest xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/new/repository:latest

// ERCのリポジトリにイメージをプッシュ
docker push xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/new/repository:latest

AWSでサーバーの準備

すでに準備されていたもの

Route53

  1. レコードセットを作成
  2. エイリアス先を既存ロードバランサーに向ける

Certificate Managerで証明書を発行

ハマりポイント:CNAMEレコードを追加しないといつまで経っても検証されない

EC2 > ロードバランシング

ターゲットグループを作成

  • 今回はポートを3001に設定
  • ターゲットを編集で使いたいインスタンスを登録
  • そのインスタンスに紐づいているセキュリティグループのインバウンドを編集
    ポート範囲:3001
    ソース:ロードバランサーのセキュリティグループIDを指定
    こいつをせっていしないと、504 Gatewaytimeoutになる

参考:AWSのロードバランサーはセキュリティグループに自分のグループIDが追加されてないと504 Gatewaytimeoutになる - YoshinoriN's Memento

ロードバランサー

  • SSL証明書:リスナーのHTTPS:443に先ほど発行した証明書を追加する
  • ルールを編集
    ホストをRoute53で設定したもの
    転送先をさっき作ったターゲットグループに指定

RDS

  • RDSのセキュリティグループでrailsアプリケーションからのアクセスを許可する

cronでawsコマンドが実行されない問題

問題

22時にインスタンス停止コマンドを打つように設定

0 22 * * * aws ec2 stop-instances --region=ap-northeast-1 --instance-ids=i-xxxx

時間が過ぎた後にawsコンソールから確認してもインスタンスが起動したまま。。



確認

普通に上記のコマンドを打った時にインスタンスが停止するか確認

$ aws ec2 stop-instances --region=ap-northeast-1 --instance-ids=i-xxxx
{
    "StoppingInstances": [
        {
            "InstanceId": "i-xxxx",
            "CurrentState": {
                "Code": 64,
                "Name": "stopping"
            },
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}

結果:awsコンソールを確認するとインスタンスが停止している


cronのログを確認

$ tail -f /var/log/cron
Jul 11 00:01:22 ip-10-0-0-11 CROND[18896]: (centos) CMD (aws ec2 stop-instances --region=ap-northeast-1 --instance-ids=i-xxxx)

結果:cronさんはコマンドを叩いてくれてはいる
でも、/var/log/cronには実行ログしか書き込まれず、エラーがあってもここには出てこないらしい


エラーログを吐き出してみる

$ crontab -e
0 22 * * * aws ec2 stop-instances --region=ap-northeast-1 --instance-ids=xxxx > cron-error.log 2>&1

$ cat cron-error.log
/bin/sh: aws: command not found

結果:どうやらコマンドのパスが合ってなくてこけてるらしい



解決

awsコマンドのパスを確認する

$ which aws
~/.local/bin/aws

コマンドのフルパスを指定する

$ crontab -e
0 22 * * * ~/.local/bin/aws ec2 stop-instances --region=ap-northeast-1 --instance-ids=xxxx

インスタンスを確認すると停止してる!

cronで時間指定してec2インスタンスを自動起動・停止する

cronとは

時間とその時間に実行したいプログラムを指定しておけば、 設定した時間にそのプログラムが実行される

cronコマンド

// cronに設定されているものを確認
crontab -l

// cronの設定を編集
crontab -e

// cronを削除(まるっと消える)
crontab -r

時間指定の書式

// 分・時・日・月・曜日
* * * * * {command}

その他諸々の書き方:https://www.server-memo.net/tips/crontab.html

ec2インスタンス起動・停止

// 起動
aws ec2 start-instances  --region=ap-northeast-1 --instance-ids=i-XXXXXXXX

// 停止
aws ec2 stop-instances  --region=ap-northeast-1 --instance-ids=i-XXXXXXXX

まとめると

// 毎朝9時に起動して
0 9 * * * aws ec2 start-instances  --region=ap-northeast-1 --instance-ids=i-XXXXXXXX

// 毎晩22時に停止する
0 22 * * * aws ec2 stop-instances  --region=ap-northeast-1 --instance-ids=i-XXXXXXXX

docker上のrailsアプリケーションからローカル上のmysqlに接続できない問題

環境

  • dockerでrailsを起動
  • ローカルサーバーでmysqlを起動

問題

すでにrailsはdockerで起動済み

railsアプリケーションにアクセスしようとするとdbの接続エラーが出てくる

$ curl 0.0.0.0:3000/index
Puma caught this error: Can't connect to MySQL server on 'xx.xx.xx.xx' (110 "Connection timed out") (Mysql2::Error::ConnectionError)

mysqlコマンドで外部からアクセスできるか確認

# mysql -h xx.xx.xx.xx -uroot -p
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on 'xx.xx.xx.xx' (110)

できないぽ

解決策

全てを受け入れるようにしてみる(セキュリティ的にやばい)
参照:MySQLをiptablesで安全に外部公開する設定 | システムガーディアン株式会社

1. bind-addressで許可する

$ vim /etc/my.cnf

bind-address = 0.0.0.0
# bind-address = 127.0.0.1 //コメントアウトしておく
# bind-address = 10.x.x.xxx 

// 停止
sudo mysqladmin -uroot -p shutdown

// 起動
sudo mysqld_safe &

確認

# mysql -h xx.xx.xx.xx -uroot -p
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on 'xx.xx.xx.xx' (110)

できないぽ
んんー?

2. 初心にもどりAWSのセキュリティグループ

空いているポートを確認

$ nmap xx.xx.xx.xx

Starting Nmap 6.40 ( http://nmap.org ) at 2019-07-10 11:16 JST
Nmap scan report for mail.xxx.jp (xx.xx.xx.xx)
Host is up (0.00050s latency).
Not shown: 996 filtered ports
PORT     STATE  SERVICE
22/tcp   open   ssh
80/tcp   closed http
443/tcp  open   https
8002/tcp closed teradataordbms

Nmap done: 1 IP address (1 host up) scanned in 4.46 seconds

お?3306が空いてないぞ

AWSのセキュリティグループで3006を全てに解放(セキュリティやば過ぎ)

$ nmap xx.xx.xx.xx

Starting Nmap 6.40 ( http://nmap.org ) at 2019-07-10 11:16 JST
Nmap scan report for mail.xxx.jp (xx.xx.xx.xx)
Host is up (0.00050s latency).
Not shown: 996 filtered ports
PORT     STATE  SERVICE
22/tcp   open   ssh
80/tcp   closed http
443/tcp  open   https
3306/tcp open   mysql
8002/tcp closed teradataordbms

Nmap done: 1 IP address (1 host up) scanned in 4.46 seconds

確認

# mysql -h xx.xx.xx.xx -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.5.56-MariaDB MariaDB Server

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

とりあえずいけたから、次はセキュリティ面を解決してかないと。

【技術勉強】オブジェクト指向でなぜつくるのか

三大要素

クラス(カプセル化

「クラス」とは種類
インスタンス」とは具体的なモノ


クラスの仕組み

クラスの特徴には、「まとめる」「隠す」「たくさん作る」がある

まとめる

そのままの意味

隠す

クラスに定義した変数とメソッドを、他のクラスから隠すことができる

たくさん作る

一度クラスとして定義すると、実行時にそこから幾つでもインスタンスを作ることができる


それぞれの変数の特徴

インスタンス変数の特徴

  1. 別のクラスのメソッドからアクセスできないように隠すことができる

  2. 一旦インスタンスが作られた後は、必要がなくなるまでメモリ上に残される

グローバル変数の特徴

  1. プログラムのどこからでもアクセスできてしまう

  2. プログラムの最初から最後まで存在しているため、メソッドの実行範囲を超えて管理したい情報を保持することができる

ローカル変数の特徴

  1. 特定のメソッドからしかアクセスできない

  2. メソッドの実行期間中にだけ存在する一時的な情報しか時保持できない

インスタンス変数は、影響範囲を局所化できるローカル変数と、存在期間の長いグローバル変数のいいとこどりをしたもの



ポリモーフィズム

ポリモーフィズムとは「いろいろな形に変わる」という意味
相手が具体的にそのクラスのインスタンスであるかを意識せずにメッセージを送れる仕組み
(メソッドを呼び出す側のロジッックを一本化する仕組み)



継承

モノの種類の共通点と相違点を体系的に整理する仕組み
クラスの共通部分を別クラスにまとめて、それによってコードの重複を排除する仕組み



メモリの仕組み

CPUはマルチスレッド?

CPUが一時点で実行できる処理は1つだけ
CPUは複数のスレッドの処理を少しずつ順繰りに実行していて、
あるスレッドの処理を実行するとき、決められた非常に短い時間だけ実行する
その時間が来たら、中途半端で会っても一旦中断して、次のスレッドに移る仕組みになっている

CPUは処理速度が非常に速いため、人間からすると複数の仕事を同時に行なっているように感じる



メモリ領域は3つに分けて管理

静的領域

プログラム開始時に確保され、行こうプログラムが終了するまで配置が固定される領域
ex. グローバル領域、コード情報


ヒープ領域

プログラムの実行時にどう時に確保するためのメモリ領域
プログラム実行中にアプリケーションから必要なサイズを要求することで割り当てを行い、不要になれば元に戻す


スタック領域

スレッドの制御のために使うメモリ領域
ヒープ領域は複数のスレッドから共有されるが、スタック領域はスレッドに1つずつ用意される
メソッド呼び出し制御のために使われるメモリ領域で、メソッドの引数やローカル変数、戻り先などの情報を格納する



OOPのメモリの使い方

メソッドに書かれたコード情報は1クラスに1つだけロードされる
インスタンスを生成するたびにヒープ領域が使われる

OOPで書いたプログラムは有限のメモリ領域であるヒープ領域を大量に使って動く

変数にはインスタンスの「ポインタ」が格納される
ポインタとは、メモリ領域の場所を示す情報



再利用

クラスライブラリ

汎用的な機能を持つクラスをたくさん集めたもの


フレームワーク

包括的なアプリケーション基盤


コンポーネント

  • OOPのクラスよりも粒度が大きい
  • ソースコード形式ではなく、バイナリ形式で提供される
  • コンポーネントの定義情報を含めて提供される
  • 昨日の独立性が高く、内部詳細を知らなくても利用できる


デザインパターン

設計パターン



UML(ユーエムエル)

1. OOPのプログラム構造や動作を表現する

  • クラス図で構造を表現する
  • シーケンス図・コミュニケーション図で動きを表現する


2. 汎用の整理術としての成果物を表現する


3. オブジェクト指向では表現できない情報を表現する

ユースケース図でコンピュータに任せる仕事を表現



オブジェクト指向設計の基本

1. 重複を排除する


2. 部品の独立性を高める

凝集度]

それぞれの部品の機能のまとまり度合い
「強い」方がいい設計


結合度

部品間の結びつき度合い
「弱い」方がいい設計


凝集度を強くするコツ

  • 一言で表現できる名前をつける
  • クラスやメソッドを小さく作る


3. 依存関係を循環させない

【読書感想】イシューからはじめよ

仕事のできる人ってどうやって仕事を進めているのかわからず、とりあえず手にとってみたほんです。

 

まず、心にグサリと来たのは、「考える」ことと、「悩む」ことの違いについてです。

・「考える」=答えが出る

・「悩む」=答えが出ない=考えているフリをしている

 

これは以前社長に、「自分が成長できてるのかわからない」と伝えたところ、

「暇なんだね」「悩むって丁度いいんだよね」と言われてしまいました。

この本でもそれと同じことを言われているなと感じました。

自分は仕事をしているように見せかけて、それは前に進むことのない物事だと気付かされました。

 

この本では、「仕事をしている上では、10分真剣に考えて答えが出なければ、一旦それをやめるべきで、それは「悩み」になってる可能性が高い」との事。

 

「悩む」と「考える」は別物であるとキチンと心に留めておかないとですね。

 

 

「生産性」とは、

インプットをアウトプットで割ったもので、インプットの量ではなく、多くのアウトプット=意味のある仕事と認識される。

 

では、「意味のある仕事」とは、

「イシュー度(問題に対して答えを出す必要性)」×「解の質(イシューに対してどこまで明確に答えを出せているか)」

イシュー度が低くいと、解の質が高くても、側から見ると意味がないものになるそう。

 

「イシュー度」が、高いか低いか判断できるようにならないといけないんですね。

 

 

他にも色々書いてあったのですが、私の脳の処理が追いつかなくて、よくわかりませんでした、、情けない、、