nginxを使ってアクセスログを追う

やりたいこと

  • ある検索項目(URLのパラメータ)がどのくらい使われているのか調べたい

やったこと

1.nginxのアクセスログの置き場所を確認

$ cat /etc/nginx/nginx.conf

~
    access_log  /var/log/nginx/access.log  main; // ここにある
~


2.アクセスログから特定の文字が含まれている回数を出力してみる

// とりあえずログが存在するか確認
$ tail -f /var/log/nginx/access.log

ログが流れてくる


// 特定の文字が含まれている行数を出力
$ cat /var/log/nginx/access.log | grep {検索したい文字列} | wc -l
934

コマンド解説

wc -l

wcコマンドは、自邸されたファイル内の行数、単語数、バイト数をカウントできる

オプション

-c バイト数のみを集計して表示
-w 単語数のみを集計して表示
-c 行数のみを集計して表示
file 集計するファイルを指定する


3.数日前の複数のアクセスログファイルを含めて回数を出力

// 数日前のアクセスログは圧縮されているため解凍する
$ gunzip /var/log/nginx/20190720.gz

// 行数の出力
$ find /var/log/nginx/ -type f -name "access.log-2019*" | xargs sudo grep jobTypes | wc -l
7388

// 解凍したファイルを圧縮し直しておく
$ gzip /var/log/nginx/20190720.gz

コマンド解説

xargs

xargsコマンドは、標準入力やファイルを引数として、別のコマンドを実行することができる

Migrations are pending. To resolve this issue, run: bin/rails db:migrate RAILS_ENV=development

問題

エラーログさんに言われたように実行

rails db:migrate RAILS_ENV=development

再度起動してもなんもかわらない。。



解決

migrate実行してもなんでエラーが続くのかという根本は解決されてません。

rails g scaffoldもしくはrails g modelで作った時にmigrateファイルも自動生成されるが、
そもそも既存のDB使っていたためmigrateファイル必要なくない?ってことで、
自動生成されたmigrateファイルを削除。解決。

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>

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