とーますメモ

Ruby on Rails / Goなどの学習メモ

【Docker】docker-composeの超基本な使い方

久しぶりにdocker-composeを使おうとすると、
コマンドをよく忘れているので自分用にメモ。

1)docker-compose.ymlファイルの作成

例)WordPress(+MySQL)を稼働させる

wordpress:
  image: wordpress
  links:
    - dbms:mysql
  ports:
    - 8080:80
dbms:
  image: mysql
  environment:
    - MYSQL_ROOT_PASSWORD=password

2)docker-compose.ymlがあるディレクトリへ移動

省略

3)docker-compose.ymlの記述に基づき、コンテナを一度に起動

$ docker-compose up -d

これで、ホストTCP8080ポート(localhost:8080)にアクセスするとWordPressインストールの画面が表示される。

"-d" オプション

デタッチモードを意味し、このオプションを付けずにdocker-compose upすると、別の作業ができないが、-dをつけると、バックグラウンドでコンテナを起動してくれるため、同ターミナルで作業ができる。

4)よく使用するコマンド

サービスのコンテナ一覧を表示

$ docker-compose stop

サービスのコンテナを停止し、そのコンテナとネットワークを削除。
オプションで[--rmi all]をつけることでイメージも削除可能。
またオプションで[-v]をつけることでdata volumeも削除可能。

$ docker-compose down
$ docker-compose down -v
$ docker-compose down --rmi all -v

サービスを停止

$ docker-compose stop

サービスコンテナを強制的に停止

$ docker-compose kill

停止中のコンテナを削除
※[-f]オプションを付けると、確認なしでコンテナを削除

$ docker-compose rm -f

コンテナからの出力(ログ)を表示

$ docker-compose logs

指定したコンテナからの出力(ログ)を表示

$ docker-compose logs mysql

サービスを起動(コンテナが既に存在する前提)

$ docker-compose start

サービスを再起動

$ docker-compose restart

追記

tty:true

tty:tureをymlに入れると、コンテナが通常が正常終了(exited(0))するのを防ぐことができる。

version: "3"
services:
  webserver:
    build: node
    image: node-express-dev:1.0
    tty: true
    volumes:
      - ./node/app:/app
    ports:
      - "9080:3000"

tty:true設定をすることで、コンテナが正常終了するのを防ぐことができます。
例えば最初にGoコンテナを起動したら正常終了しましたが、あれはGoコンテナにフォアグラウンドで実行するプロセスが無いため、そのままDockerがコンテナを終了させています。
そこでttyです、これを設定することでコンテナ側に仮想端末を置いて実行しているプロセスを用意してあげることによってコンテナを持続させることができます。
正常終了してしまうと、コンテナの中に入ってサーバーを立てたりすることができないので、なんらかのフォアグラウンドで実行するプロセスが必要になります。
その役割がDockerのTTYということです。

[参考]
DockerのTTYって何?

docker execとdocker attachの違い。

どちらのコマンドでもコンテナ内の操作が可能になるが、
attachを使用後、exitするとコンテナが停止してしまう。
execの場合は、コンテナを停止させることがないため、
execを使う用に習慣づけるほうが良い。

[参考]
Dockerコンテナ内で操作 attachとexecの違い - Qiita

Dockerfileのベストプラクティス

RUNコマンドでapt-get updateをするときはapt-get install -yも一緒にすることで

キャッシュ問題に巻き込まれることがなくなる。
またこのとき、インストールパッケージには
必要なパッケージの予期しない変更によって引き起こされる問題を避けるために
特定バーションを設定するほうが良い。

[参考]
Dockerfile のベストプラクティス — Docker-docs-ja 1.9.0b ドキュメント

RUNとCMDの違い

RUN:ビルド時にコンテナ内で実行される

CMD:完成したイメージからコンテナを作成するときに実行される

DockerのRUNとCMDの違い - Qiita

なのでnginx, apacheやmysqlの起動などをDockerfileに書く際は、CMDを使用する。

ボリュームとバインドマウントの違い

ボリューム

Dockerが管理する領域にデータ保存領域が作成され、ホスタ側では意識せずに使用することができる。複数の異なるコンテナで同じデータを共有したい場合に便利。データベース等。

【Rails】はてなブログをAtomAPIを使用して作成してみた

Rubyで記事をAtomAPIを使用して更新する方法としては、「atomutil」というgemを使用するのが定番のようだが
いろんな記事を見てみると、新しいRubyのバージョンだと、文字エンコーディングのエラーが発生するため
「atomutil」をforkした「ruby-atomutil」というgemを使用している記事が多い。

[参考]
はてなブログのAPIを使って、記事を投稿するRubyサンプル · GitHub
Ruby | はてなダイアリーAtomPubをRubyから利用してブログ記事を投稿する - Tbpgr Blog

しかし、2018年9月4日で最新版(0.1.5)が更新されて
この文字系のエラーが解消されているので以下のように書けば、記事を作成できる。

インストール

gem 'atomutil', '~> 0.1.5'

コード

def initialize
  @user_id         = ENV['HATENA_USER_ID']
  @password        = ENV['HATENA_API_KEY']
  @create_page_url = "#{ENV['HATENA_BLOG_ROOT_END_POINT']}/entry"
end

def create(title, content)
  auth   = Atompub::Auth::Wsse.new(username: @user_id, password: @password)
  client = Atompub::Client.new(auth: auth)

  entry = Atom::Entry.new({
    title:   title,
    content: content
  })

  client.create_entry(@create_page_url, entry)
end

...
...

title   = 'テストタイトル'
content = <<~'EOS'
  *表題
  - リスト1
  - リスト2
EOS

create(title content)

[他参考]
Rubyのヒアドキュメントの書き方いろいろ - Hack Your Design!
Ruby:はてなブログAPIを使って記事の一覧をJSON形式で取得する - Madogiwa Blog

【Ruby】はてなブログをAtomAPIを使用して作成してみた

Rubyで記事をAtomを使用して更新する方法としては、「atomutil」というgemを使用するのが定番のようだが
いろんな記事を見てみると、新しいRubyのバージョンだと、文字エンコーディングのエラーが発生するため
「atomutil」をforkした「ruby-atomutil」というgemを使用している記事が多い。

[参考]
はてなブログのAPIを使って、記事を投稿するRubyサンプル · GitHub
Ruby | はてなダイアリーAtomPubをRubyから利用してブログ記事を投稿する - Tbpgr Blog

しかし、2018年9月4日で最新版(0.1.5)が更新されて
この文字系のエラーが解消されているので以下のように書けば、記事を作成できる。

インストール

gem 'atomutil', '~> 0.1.5'

コード

def initialize
  @user_id         = ENV['HATENA_USER_ID']
  @password        = ENV['HATENA_API_KEY']
  @create_page_url = "#{ENV['HATENA_BLOG_ROOT_END_POINT']}/entry"
end

def create(title, content)
  auth   = Atompub::Auth::Wsse.new(username: @user_id, password: @password)
  client = Atompub::Client.new(auth: auth)

  entry = Atom::Entry.new({
    title:   title,
    content: content
  })

  client.create_entry(@create_page_url, entry)
end

...
...

title   = 'テストタイトル'
content = <<~'EOS'
  *表題
  - リスト1
  - リスト2
EOS

create(title content)

[他参考]
Rubyのヒアドキュメントの書き方いろいろ - Hack Your Design!
Ruby:はてなブログAPIを使って記事の一覧をJSON形式で取得する - Madogiwa Blog

【Lynis】Ubuntu16.04にセキュリティ監査ツール「Lynis」を入れてみた

インストール

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C80E383C3DE9F082E01391A0366C67DE91CA5D5F
apt install apt-transport-https
echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/99disable-translations
echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" > /etc/apt/sources.list.d/cisofy-lynis.list
apt update
apt remove lynis
apt install lynis

以下のサイト様より引用
linuxのセキュリティツール - fr33f0r4ll

使い方

$ lynis audit system

メールレポート送信

デフォルトでは、メールレポート送信機能はないので、
以下のスクリプトを作成。

Lynisはスキャンが終わると、そのレポートを「/var/log/lynis-report.dat」に作成する。
大事なのは、「Warning」と「Suggestion」箇所なので、
その部分を抽出し、各行数を追記し、レポートをメールを送信する。

一日に1回のスキャンで自分は良いので、cron.dailyにスクリプトを配置している。
結構汚いコードなので、あしからず。

/etc/cron.daily/lynis_daily

#!/bin/bash

LOGFILE="{{ lynis_log_directory }}/lynis-$(date +'%Y-%m-%d_%H:%M:%S').log";

DATA="{{ lynis_log_directory }}/lynis-data-$(date +'%Y-%m-%d_%H:%M:%S').txt";
WARNING_DATA="{{ lynis_log_directory }}/lynis-warning-$(date +'%Y-%m-%d_%H:%M:%S').txt";
SUGGESTION_DATA="{{ lynis_log_directory }}/lynis-suggestion-$(date +'%Y-%m-%d_%H:%M:%S').txt";
TMP_DATA="{{ lynis_log_directory }}/lynis-tmp-$(date +'%Y-%m-%d_%H:%M:%S').txt";

EMAIL_FROM="{{ lynis_mail_from }}";
EMAIL_TO="{{ lynis_scan_email }}";

SEPARATOR="--------------------------------------------------------------------------------"

echo "Starting a lynis scan"
lynis audit system

if [ -f /var/log/lynis-report.dat ]; then
cat /var/log/lynis-report.dat | grep 'warning\[\]' | sed -e 's/^warning\[\]\=/warning: /g' > ${WARNING_DATA}
cat /var/log/lynis-report.dat | grep 'suggestion\[\]' | sed -e 's/^suggestion\[\]\=/suggestion: /g' > ${SUGGESTION_DATA}
mv /var/log/lynis-report.dat ${DATA}

# [START] append header
WARNING_HEADER="Warnings ($(cat "$WARNING_DATA" | wc -l)):\n$SEPARATOR"
SUGGESTION_HEADER="\n\n\nSuggestions ($(cat "$SUGGESTION_DATA" | wc -l)):\n$SEPARATOR"

sed "1s/^/$WARNING_HEADER\n/" ${WARNING_DATA} > ${TMP_DATA}
cat "$TMP_DATA" > ${WARNING_DATA}

sed "1s/^/$SUGGESTION_HEADER\n/" ${SUGGESTION_DATA} > ${TMP_DATA}
cat "$TMP_DATA" > ${SUGGESTION_DATA}

rm "$TMP_DATA"
# [END] append header

cat "$WARNING_DATA" "$SUGGESTION_DATA" | mail -s "Lynis Report" -r "$EMAIL_FROM" "$EMAIL_TO";
fi

exit 0

【ClamAV】Ubuntu18.04にClam AntiVirusを設定してみた

ネット上で調べてみると、

clamscanとclamdscanの違いなどをまずは把握する必要がある。
ClamAV(R)でスキャンしてみる | カメノドットコム

自分の場合、頻繁にスキャンする用途ではなく、
1時間に1回の頻度でスキャンし、レポートメールを受け取れれば
それで良いので以下のように環境を構築した。

※前提として、メールは環境は別途構築済み(Postfix + mailutils)

後述するがリアルタイムスキャンの機能がclamavにもあるが、
メモリリソースを結構消費するので、メモリ消費が少ない時間帯を狙って
実行できるように設定する。

その設定方法は主に以下のサイトを参考にして作成する。(すごい役に立つ内容で感謝!)
ClamAVによる定期ウイルススキャンの設定 | 稲葉サーバーデザイン

1)インストール

$ apt install -y clamav

昔の記事をみるとclamav以外にもclamav-daemonやclamav-freshclamを別途インストールするような
記載がある記事もあるが、
上記だけで、clamav-daemonやclamav-freshclamもインストールされる。
ClamavNet

インストールした時点で、自動でウイルス定義ファイルの更新を行うデーモン(clamav-freshclam)が動いている。
手動で行う場合は、freshclamコマンドを打つ。
https://www.clamav.net/documents/signature-testing-and-management#freshclam

$ freshclam

ちなみにデフォルトだと、clamav-freshclamサービスが動作しているため
そのままfreshclamコマンドを打つと、「/var/log/clamav/freshclam.log is locked by another process」というエラーがでるので
一度サービスを止めてからコマンドを打つ。

$ sudo service clamav-freshclam stop

$ sudo freshclam

$ sudo service clamav-freshclam start

スキャンテスト

[オプション]

  • r・・・サブディレクトリごと再帰的に検査
  • i・・・ウイルスに感染したファイルのみを出力

システム全体のスキャン(ウイルスは削除しない)
$ clamscan -ri /

ホームディレクトリのみ
$ clamscan -ri /home

ウイルスを発見しだい削除
$ clamscan --remove -ri /home

ウイルスを発見したら他のディレクトリに移す
$ clamscan --move=DIRECTORY -ri /home

2)スキャンレポートメールスクリプトの作成

$ vim /etc/cron.d/clamscan

以下のサイトを参考に改造してものを使用。
ClamAVによる定期ウイルススキャンの設定 | 稲葉サーバーデザイン

スクリプト内の以下の変数は環境に応じて設定要
EXCLUDE_LIST_FILE="/etc/clamav/scanvirus_exclude_list.txt
EMAIL_FROM
EMAIL_TO

誤検知を防ぐために、スキャン結果のみを通知する仕組みにしている。

/etc/clamav/scanvirus_exclude_list.txt

/sys/
/proc/
/dev/

/etc/clamav/clamscan.sh

#!/bin/bash

# ClamAVによるウイルススキャンスクリプト clamscan.sh
# ウイルススキャンを実行し、ウイルスを検知したときのみ、
# 指定した宛先にアラートメールを送信する。
# 誤検知もあり得るため、検知しても駆除(削除)は実施しない。
#
# スキャンの実行前には、ClamAVプログラムおよびウイルス定義を
# アップデートする。
#
# スキャンの除外対象ディレクトリ、ファイルは、${EXCLUDE_LIST_FILE}
# ファイルに1行ずつ記載すること。ディレクトリの末尾には、/ をつける。

EXCLUDE_LIST_FILE="/etc/clamav/scanvirus_exclude_list.txt"
LOGFILE="/var/log/clamav/scanlog/clamav-$(date +'%Y-%m-%d_%H:%M:%S').log"
LATEST_SCAN_RESULT="/var/log/clamav/scanresult.txt"

MAX_FILESIZE=200M
MAX_SCANSIZE=200M

EMAIL_FROM=from@example.com
EMAIL_TO=to@example.com

export LANG=C

echo "===== Scan Virus =====" >> ${LOGFILE}

#########################################
#
#         2. ウイルス定義の更新
#
#########################################

echo "`date` Update Database start" >> ${LOGFILE}
/usr/bin/freshclam 1>> ${LOGFILE} 2>&1
echo "`date` Update Database end" >> ${LOGFILE}



#########################################
#
#         3. ウイルススキャンの実施
#
#########################################

echo "`date` Do Scan Virus start" >> ${LOGFILE}

## スキャン除外リストの展開
while read LINE
do
    if [ $(echo "${LINE}"|grep \/$) ]; then
        i=`echo ${LINE}|sed -e 's/^\([^ ]*\)\/$/\1/p' -e d`
        excludeopt="${excludeopt} --exclude-dir=^${LINE}"
    else
        excludeopt="${excludeopt} --exclude=^${LINE}"
    fi
done < ${EXCLUDE_LIST_FILE}

echo "excludeopt: ${excludeopt}" >> ${LOGFILE}



#########################################
#
#         4. ウイルススキャンの実行
#
#########################################

/usr/bin/clamscan \
--max-filesize=${MAX_FILESIZE} --max-scansize=${MAX_SCANSIZE} \
--infected --recursive ${excludeopt} / 1> ${LATEST_SCAN_RESULT} 2>> ${LOGFILE}

# get the value of "Infected lines"
MALWARE=$(tail "$LOGFILE"|grep Infected|cut -d" " -f3);

## ウイルスを検知したときのみ、アラートメールで通知する
if [ "$MALWARE" -ne "0" ];then
  cat ${LATEST_SCAN_RESULT} | mail -s "Virus Found in `hostname`" -a "From: ${EMAIL_FROM}" -r ${EMAIL_FROM} ${EMAIL_TO}
fi

cat ${LATEST_SCAN_RESULT} >> ${LOGFILE}

echo "`date` Do Scan Virus end" >> ${LOGFILE}

ex) 毎日17:00時に動作する設定
/etc/cron.d/clamscan

drwxr-xr-x   2 root root 4096 Mar 17 20:51 ./
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
# 分 時 日 月 曜日 ユーザー コマンド
0 17    * * *   root    cd /etc/clamav/ && ./clamscan.sh

あとは実行権限を付与するだけ。

$ chmod 0755 /etc/cron.d/clamscan

これで指定した時間にスキャンされ、レポートメールが届く。

リアルタイムスキャン(今回は設定しないが、参考までに。)

デフォルトでは、リアルタイムスキャン(オンアクセススキャン)が適応されていないので
必要ならば適用する必要がある。

しかしこの設定が結構曲者。
clamdのバージョンが0.102.0未満と0.102.0以上で設定方法が違う。
[0.102.0未満]
如是我聞 - a blog about life and tech
Ubuntu 18.04 で ClamAV オンアクセススキャンを使ってみる – Yut@rommx.com
ClamAVのオンアクセススキャンについて - Tbpgr Blog

[0.102.0以上]
Ubuntu16.04LTSにClamAV0.102.1を入れてon access scanning も有効にする | 我輩はイヌである

バージョンの確認方法

$ clamd -V

テスト

無害のテスト用のウイルスを以下のようにダウンロード可能。
※上記スクリプトでは、「/var」内がスキャン対象なので、「/var」以下にダウンロード

$ wget http://www.eicar.org/download/eicar_com.zip -O /var/eicar_com.zip

すぐにテストしたければ、直接スクリプトを実行すればよい。

$ ./etc/cron.hourly/clamscan_hourly

[参考]
Configure Clamav for daily system scans and email notification on Debian

ClamAVによる定期ウイルススキャンの設定 | 稲葉サーバーデザイン
Automate ClamAV to Perform Daily System Scan and Send Email Notifications on Linux | Lisenet.com :: Linux | Security | Networking
【Ubuntu 18.04/16.04 LTS Server】ClamAVで定期的にウイルスチェックし、メール通知する | The modern stone age.

【Postfix】迷惑メールになってしまう?何が悪いの?そんなときに使えるサイト

Gmailで迷惑メール判定されてしまい、
どうやっても、何が悪いのか、どう設定したら良いのか
わからなくなったとき、知り合いから教えてもらったサイト。

Newsletters spam test by mail-tester.com
f:id:Thoames1212:20180823004650p:plain

TOPページに表示されている、一時的に払い出されたメールアドレスに
テストしたいSMTPサーバ(Postfix)からメールを送信すると
スパム判定スコアを表示してくれ、どの設定が悪いのか10点満点で判定してくれる。

f:id:Thoames1212:20180823010034p:plain

原因がわかったら、あとは10点満点になるまで対応すれば良い。


また以下のサイトもいい感じで使えそう。
MX Lookup Tool - Check your DNS MX Records online - MxToolbox

ドメインからいろんな情報を調べることができる。

【DigitalOcean】ホスト名逆引き登録の設定

以下のサイトを参考にそのままできた。
[ホスティング] DNS逆引きを可能にする (迷惑メール判定回避) – 端くれプログラマの備忘録
How do I set up reverse DNS for my IP? | DigitalOcean

DigitalOceanでは、Droplet作成時にホスト名を設定可能。
後で変更する場合は、Dropletを一覧画面から選択後、Droplet名をクリックすると編集できる。
すごい簡単にできる。

※「Add a domain」から設定しないといけないのかと思ったが不要。

また、以下のコマンドでも逆引き登録の結果を確認できる。

$ nslookup IPアドレス

または

$ dig -x IPアドレス

[参考]
DNS逆引きの基本について - 基本へ帰ろう
サーバーのメールが迷惑メールにならないようにする設定 - はじめてのさくらVPS