DockerコンテナからのsyslogをMacで受信する

Dockerコンテナ内からsyslogを飛ばすテストをしたいのだが、適当なサーバーがなく、ホストOSのMacで代用した話が本記事の元ネタになっています。

#概要

CentOSのDockerコンテナからsyslogを飛ばし、ホストOSのMac側にファイル出力させます。この過程でMacのsyslog設定を変更していきます。


**前提**

mac: OS X(High Sierra v10.13)
Docker: 18.06.1-ce


# Macのセキュリティ機能をOFF
MacのSIP(System Integrity Protection)をOFFにします。
SIPは、OSで保護されたファイルの改竄等を防止する機能ですが、今回は変更対象のファイルが保護対象にあたるので、一旦OFFにします。

MANO_fukuokaさんの[投稿](https://qiita.com/MANO_fukuoka/items/9eaa2e9926b764556ad5)を参考に実施していきます。

###SIPの状態確認
まずは、SIPの稼働状況を確認します。

```
csrutil status
System Integrity Protection status: enabled.
``` 

ちなみに、SIPが有効な状態で無効化を試みると、Recovery OSから実行しなさいと怒られます。

```
csrutil disable
csrutil: failed to modify system integrity configuration. This tool needs to be executed from the Recovery OS.
```

###SIPの無効化

####リカバリモードの起動
Recovery OSから実行しなさいということなので、Macを再起動し[command + R]を押し続け、リカバリモードで起動します。

####SIPの無効化

画面上部のメニューからターミナルを起動し、以下のコマンドを実行します。

```Terminal:Terminal@RecoveryMode
csrutil disable
Successufully disabled System Integrity Protection. Please restart the machine for the changes to take effect.
```

変更を反映させるために再起動します。

```Terminal:Terminal@RecoveryMode
reboot
```

#Macのsyslog受信設定

Macのsyslog起動設定は、下記のファイルに記載します。
/System/Library/LaunchDaemons/com.apple.syslogd.plist

デフォルトでは、外部から受信不可なので、可能にするために編集を行います。

###Copy&Backup

```
cp -p /System/Library/LaunchDaemons/com.apple.syslogd.plist ./
cp -p ./com.apple.syslogd.plist com.apple.syslogd.plist_bk
```

###XML形式へ変換

元のファイルは、バイナリ形式なのでXML形式へ変換します。

```
plutil -convert xml1 ./com.apple.syslogd.plist
```

###編集

適当なエディターでファイルを編集します。
NetworkListenerタグ以降を追加します。

```
vi ./com.apple.syslogd.plist

#以下、ファイル内容
  <dict>
    <key>BSDSystemLogger</key>
    <dict>
      <key>SockPathMode</key>
      <integer>438</integer>
      <key>SockPathName</key>
      <string>/var/run/syslog</string>
      <key>SockType</key>
      <string>dgram</string>
    </dict>
    <!--ここから -->
    <key>NetworkListener</key>
    <dict>
      <key>SockServiceName</key>
      <string>syslog</string>
      <key>SockType</key>
      <string>dgram</string>
    </dict>
    <!--ここまで -->
```


ちなみに、この追加内容は、syslogdのmanで確認できます

```
 -udp_in      The ``udp_in'' module receives log messages on the UDP socket associated with the
               Internet syslog message protocol.

               This module is normally enabled, but is inactive.  The actual UDP sockets are man-
               aged by launchd, and configured in the syslogd configuration file /Sys-
               tem/Library/LaunchDaemons/com.apple.syslogd.plist.  In the default configuration,
               launchd does not open any sockets for the ``syslog'' UDP service, so no sockets
               are provided to the ``udp_in'' module.  If no sockets are provided, the module
               remains inactive.  A socket may be specified by adding the following entry to the
               ``Sockets'' dictionary in the com.apple.syslogd.plist file.

                          <key>NetworkListener</key>
                          <dict>
                               <key>SockServiceName</key>
                               <string>syslog</string>
                               <key>SockType</key>
                               <string>dgram</string>
                          </dict>

```

###修正確認

```
plutil -lint com.apple.syslogd.plist 
com.apple.syslogd.plist: OK
```

###バイナリへ再変換

```
plutil -convert binary1 ./com.apple.syslogd.plist
```

###ファイルを上書き

```
sudo cp ./com.apple.syslogd.plist /System/Library/LaunchDaemons/com.apple.syslogd.plist
```


#Macのsyslogファイル出力設定

Macのsyslogは、Sierra以降、ASL(Apple System Logger)に統合されたらしく、ファイル出力の設定は、このASLを通して行います。

設定方法は、以下の２つが考えられます。

 - /private/etc/asl.conf を修正
 - /private/etc/asl/配下に設定ファイルを追加 

ここでは、/private/etc/asl/配下に設定ファイルを追加します。

###設定ファイル作成

「docker.syslog.try」というファイル名で作成します。

下記条件で送信されたsyslogを「/var/log/docker-syslog-try.log」へ出力させます。

 - host : senderhost  ※後ほど、このホスト名でコンテナを起動します
 - facility : local1

```
vi docker.syslog.try

#以下ファイル内容

? [= Facility local1] [= Host senderhost] claim only
* file /var/log/docker-syslog-try.log mode=0644 rotate=seq compress file_max=1M all_max=50M format=raw
```

なお、設定ファイルの記載方法は、manで確認できます。

```
man asl.conf
```


###設定ファイルコピー

```
sudo cp -p docker.syslog.try /private/etc/asl/
```

###syslog再起動

```
sudo launchctl unload /System/Library/LaunchDaemons/com.apple.syslogd.plist
sudo launchctl load /System/Library/LaunchDaemons/com.apple.syslogd.plist
```

#Dockerコンテナ作成

ここからは、syslog送信元のDockerコンテナの作成を行います。

###Dockerfile作成

下記内容のDockerfileを作成します。

ここで、sedでrsyslog.confを更新している実行している理由は[ここ](https://qiita.com/mokemokechicken/items/393e7e31a2cc36834bcb)を参照してください。

また、syslogの送信先に設定している[host.docker.internal](https://docs.docker.com/docker-for-mac/networking/)は、コンテナからホストへアクセスするためのDNS名です。

```
vi Dockerfile

#以下、ファイル内容
FROM centos:centos7
RUN yum update -y
RUN yum install -y rsyslog

RUN sed -i -e '/$ModLoad imjournal/s/^/#/' /etc/rsyslog.conf
RUN sed -i -e 's/$OmitLocalLogging on/$OmitLocalLogging off/' /etc/rsyslog.conf
RUN sed -i -e '/$IMJournalStateFile/s/^/#/' /etc/rsyslog.conf
RUN sed -i -e '/$SystemLogSocketName/s/^/#/' /etc/rsyslog.d/listen.conf

RUN echo '*.* @host.docker.internal:514' >> /etc/rsyslog.conf

ENTRYPOINT tail -f /dev/null
```

###docker build

buildします。タグ名は任意です。

```
docker build -t syslog.centos:v1 ./
#実行結果は途中省略
Successfully built d75625c7c8ab
Successfully tagged syslog.centos:v1
```

### docker run

コンテナを起動します。 ここでコンテナのホスト名を--hostnameで指定しています。
このホスト名は、Mac側のsyslogに設定したしたホスト名です。

```terminal:Mac
docker run --hostname senderhost syslog.centos:v1
```

### 稼働確認

さあ、稼働確認してみましょう。
まず、コンテナ内にログインしてみます。

```terminal:Mac
# container idの確認
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
ab0cf16a364d        syslog.centos:v1    "/bin/sh -c 'tail -f…"   22 seconds ago      Up 20 seconds                           relaxed_kilby

#コンテナへログイン
docker exec -it ab0cf16a364d /bin/bash
```

次に、rsyslogを起動し、loggerコマンドでsyslogを出力してみます


```termina:コンテナ
#rsyslog起動
/usr/sbin/rsyslogd

#syslog出力
echo "test message" | logger -p local1.notice -t senderApp

#コンテナ内のsyslog出力確認
cat /var/log/messages
Nov  7 06:37:33 senderhost rsyslogd:  [origin software="rsyslogd" swVersion="8.24.0" x-pid="24" x-info="http://www.rsyslog.com"] start
Nov  7 06:38:40 senderhost senderApp: test message
```

最後に、Mac(ホスト)側のsyslog出力結果を確認します
出力フォーマットをrawにしているので若干見辛いですが、ご容赦を。

```terminal:Mac
cat /var/log/docker-syslog-try.log
[Time 1541540366] [Facility local1] [Sender senderApp] [PID -1] [Message test message] [Level 5] [UID -2] [GID -2] [Host senderhost] [ReadGID 80]
```