Errbotとは
chatbotの1つでslackなどのチャットサービスにbotとして簡単に導入できます。
python実装のため、プラグイン開発もpythonで行えます。
実現したいこと
ローカルフォルダで開発中のプラグインをDocker内のerrbotで実行し、VSCodeでデバッグ実行できる。
開発後は、slackに接続してchatbot運用する。
動作確認したDockerバージョン
$ docker version
Client: Docker Engine - Community
Version: 18.09.2
API version: 1.39
Go version: go1.10.8
Git commit: 6247962
Built: Sun Feb 10 04:12:39 2019
OS/Arch: darwin/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.2
API version: 1.39 (minimum version 1.12)
Go version: go1.10.6
Git commit: 6247962
Built: Sun Feb 10 04:13:06 2019
OS/Arch: linux/amd64
Experimental: true
Errbot on Dockerの構築
errbot をビルドするために Dockerfile
,requirements.txt
,entrypoint.sh
,errbot設定ファイルsrv/config.py
を用意します。
docker-errbot/
|--Dockerfile
|--entrypoint.sh
|--requirements.txt
|--srv
| |--config.py
FROM python:alpine
WORKDIR /app
COPY . /app
# Install Requirments Packages.
RUN apk add --no-cache --virtual .build-deps \
gcc \
libffi-dev \
musl-dev \
openssl-dev \
&& : Install pip packages \
&& python -m pip install -r requirements.txt \
&& : Delete build-deps packages \
&& apk del --purge .build-deps \
&& : Delete pip cache files \
&& rm -rf /root/.cache
# Install minimal Packages, and Setup Errbot.
RUN apk add --no-cache \
bash \
shadow \
tzdata \
&& : Setup timezone \
&& cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
&& echo "Asia/Tokyo" > /etc/timezone \
&& : Setup user \
&& groupadd -r errbot && useradd -m -r -g errbot errbot \
&& : Setup errbot \
&& errbot --init \
&& : Change owner and group \
&& chown -R errbot:errbot /app \
&& : Change permission \
&& chmod +x entrypoint.sh
# Run
USER errbot
ENTRYPOINT [ "./entrypoint.sh" ]
CMD [ "run" ]
- できるだけイメージサイズを小さくしたいので
python:alpine
をベースイメージとして選択します - pip install 時だけに必要なパッケージは、
apk add --no-cache --virtual .build-deps
でインストールし、pip install 後にapk del --purge .build-deps
で削除します - pip install 時のキャッシュファイル
/root/.cache
も削除します - timezoneは
Asia/Tokyo
に設定します - ユーザ
errbot
でerrbotを起動します
errbot
slackclient
websocket-client
ptvsd
-
ptvsd(Python Tools for Visual Studio debug server)
を導入することでVSCodeからリモートデバッグできるようになります
#!/bin/bash -eu
[[ -v DEBUG ]] && ${DEBUG} && set -x
case ${1} in
run)
errbot -c srv/config.py
;;
debug)
python -m ptvsd --host 0.0.0.0 --port 5678 /usr/local/bin/errbot -c srv/config.py
;;
*)
exec "$@"
;;
esac
- entrypoint.shスクリプトをデバッグしたい時は
DEBUG=true
とすることでset -x
が実行されます -
entrypoint.sh run
で通常実行 -
entrypoint.sh debug
でデバッグ実行 - デバッグ実行時は ptvsd が
0.0.0.0:5678
でデバッグ接続を待ち受けて errbot を起動します
$ diff -u config-tempalate.py srv/config.py
--- config-template.py 2019-05-04 18:02:05.000000000 +0900
+++ srv/config.py 2019-05-04 18:13:20.000000000 +0900
@@ -17,6 +17,7 @@
##########################################################################
import logging
+import os
##########################################################################
# Core Errbot configuration #
@@ -44,7 +45,7 @@
# 'Telegram' - cloud-based mobile and desktop messaging app with a focus
# on security and speed. (https://telegram.org/)
-# BACKEND = 'XMPP' # defaults to XMPP
+BACKEND = os.environ.get('BACKEND', 'Text')
# STORAGE selection.
# This configures the type of persistence you wish to use Errbot with.
@@ -63,7 +64,7 @@
# The location where all of Err's data should be stored. Make sure to set
# this to a directory that is writable by the user running the bot.
-BOT_DATA_DIR = '/var/lib/err'
+BOT_DATA_DIR = '/app/data'
### Repos and plugins config.
@@ -82,7 +83,7 @@
# locally before publishing it. Note that you can specify only a single
# directory, however you are free to create subdirectories with multiple
# plugins inside this directory.
-BOT_EXTRA_PLUGIN_DIR = None
+BOT_EXTRA_PLUGIN_DIR = '/app/plugins'
# If you use an external backend as a plugin,
# this is where you tell Errbot where to find it.
@@ -126,7 +127,7 @@
# If you encounter any issues with Err, please set your log level to
# logging.DEBUG and attach a log with your bug report to aid the developers
# in debugging the issue.
-BOT_LOG_LEVEL = logging.INFO
+BOT_LOG_LEVEL = logging.getLevelName(os.environ.get('BOT_LOG_LEVEL', 'INFO'))
# Enable logging to sentry (find out more about sentry at www.getsentry.com).
# This is optional and disabled by default.
@@ -153,9 +154,9 @@
# The identity, or credentials, used to connect to a server
BOT_IDENTITY = {
# XMPP (Jabber) mode
- 'username':
- 'err@localhost', # The JID of the user you have created for the bot
- 'password': 'changeme', # The corresponding password for this user
+ # 'username':
+ # 'err@localhost', # The JID of the user you have created for the bot
+ # 'password': 'changeme', # The corresponding password for this user
# 'server': ('host.domain.tld',5222), # server override
## HipChat mode (Comment the above if using this mode)
@@ -170,7 +171,7 @@
# 'endpoint': 'https://api.hipchat.com'
## Slack mode (comment the others above if using this mode)
- # 'token': 'xoxb-4426949411-aEM7...',
+ 'token': os.environ.get('BOT_SLACK_TOKEN'),
## you can also include the proxy for the SlackClient connection
# 'proxies': {'http': 'some-http-proxy', 'https': 'some-https-proxy'}
@@ -198,7 +199,7 @@
#
# Unix-style glob patterns are supported, so 'gbin@localhost'
# would be considered an admin if setting '*@localhost'.
-BOT_ADMINS = ('gbin@localhost', )
+BOT_ADMINS = tuple(os.environ.get('BOT_ADMINS', '@admin').split(','), )
# Set of admins that wish to receive administrative bot notifications.
#BOT_ADMINS_NOTIFICATIONS = ()
@@ -238,7 +239,8 @@
# names, rather than the BOT_PREFIX above. This option allows you to
# specify alternative prefixes the bot will respond to in addition to
# the prefix above.
-#BOT_ALT_PREFIXES = ('Err',)
+BOT_ALT_PREFIXES = tuple(
+ os.environ.get('BOT_ALT_PREFIXES', 'Err').split(','), )
# If you use alternative prefixes, you might want to allow users to insert
# separators like , and ; between the prefix and the command itself. This
- errbotのconfig-templateを取得し、上記のように書き換えて
srv/config.py
にします - デフォルトはTextモードで起動されます
-
BACKEND=Slack
とすることでslackモードで起動し、slackに接続されます - slackのAPIトークンは
BOT_SLACK_TOKEN=xoxb-...
で設定します
dockerイメージのビルド
$ docker build ./ -t errbot
Sending build context to Docker daemon 50.18kB
Step 1/8 : FROM python:alpine
---> 715a1f28828d
Step 2/8 : WORKDIR /app
---> Running in 1a057f81fc87
Removing intermediate container 1a057f81fc87
---> 9cca706eba25
Step 3/8 : COPY . /app
---> 780a7a9beb56
Step 4/8 : RUN apk add --no-cache --virtual .build-deps gcc libffi-dev musl-dev openssl-dev && : Install pip packages && python -m pip install -r requirements.txt && : Delete build-deps packages && apk del --purge .build-deps && : Delete pip cache files && rm -rf /root/.cache
---> Running in c19b0fedc8f4
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz
(1/16) Installing binutils (2.31.1-r2)
(2/16) Installing gmp (6.1.2-r1)
(3/16) Installing isl (0.18-r0)
※省略
Errbotを通常(Text)モードで起動確認
下記のコマンドでerrbotを起動します。
[@admin ➡ @errbot] >>>
でerrbotの起動が成功し、コマンド待ち状態となります。
$ docker run --rm -it --name errbot errbot
20:29:58 INFO errbot.bootstrap Found Storage plugin: Shelf.
20:29:58 INFO errbot.bootstrap Found Backend plugin: Text
20:29:59 INFO errbot webhooks: Flag to bind /echo to echo
────────────────────────────────────────────────────────────────────────────────
You start as a bot admin in a one-on-one conversation with the bot.
Context of the chat
• Use !inroom to switch to a room conversation.
• Use !inperson to switch back to a one-on-one conversation.
• Use !asuser to talk as a normal user.
• Use !asadmin to switch back as a bot admin.
Preferences
• Use !ml to flip on/off the multiline mode (Enter twice at the end to send).
────────────────────────────────────────────────────────────────────────────────
[@admin ➡ @errbot] >>>
VSCode側のデバッグ構成
VSCodeでデバッグ構成ファイル(launch,json)を下記のように設定します
"configurations": [
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"port": 5678,
"host": "localhost",
"pathMappings": [
{
"localRoot": "${workspaceFolder}/plugins",
"remoteRoot": "/app/plugins"
}
]
},
※省略
-
Python: Attach
実行時にlocalhost:5678
に接続します -
Python: Attach
実行時にローカルのplugins
フォルダとリモートの/app/plugins
フォルダをマッピングします
Errbotをデバッグ(Text)モードで起動
下記コマンドでerrbotを起動してVSCodeでデバッグPython:attach
を実行するとブレークポイントの指定や変数の状態なども確認でき、デバッグが簡単にできるようになります。
$ docker run --rm -it --name errbot -v $(pwd)/plugins:/app/plugins:ro -p 5678:5678 -e DEBUG=true errbot debug
+ case ${1} in
+ python -m ptvsd --host 0.0.0.0 --port 5678 /usr/local/bin/errbot -c srv/config.py
20:42:37 INFO errbot.bootstrap Found Storage plugin: Shelf.
20:42:37 INFO errbot.bootstrap Found Backend plugin: Text
20:42:39 INFO errbot webhooks: Flag to bind /echo to echo
────────────────────────────────────────────────────────────────────────────────
You start as a bot admin in a one-on-one conversation with the bot.
Context of the chat
• Use !inroom to switch to a room conversation.
• Use !inperson to switch back to a one-on-one conversation.
• Use !asuser to talk as a normal user.
• Use !asadmin to switch back as a bot admin.
Preferences
• Use !ml to flip on/off the multiline mode (Enter twice at the end to send).
────────────────────────────────────────────────────────────────────────────────
[@admin ➡ @errbot] >>>
- pluginsフォルダ配下に開発中のプラグインソースを置きます
- docker起動時の -vオプションで
plugins
フォルダをdocker内/app/plugins
にマウントします - docker起動時の -pオプションで
port 5678
をdocker内のptvsdが待ち受けているport 5678
に接続できます - docker起動時の -eオプションで
DEBUG=true
でentrypoin.sh
スクリプトの実行も確認できます
slackのchatbotとしての運用方法
slackモードで運用するときには、docker runで渡すパラメータが増えて大変なのでdocker-composeで起動できるように下記のdocker-compose.yml
を用意します
version: '2.1'
services:
errbot:
image: errbot
build:
context: .
environment:
- BACKEND=Slack
- BOT_SLACK_TOKEN
- BOT_ADMINS=@admin
stdin_open: true
tty: true
BOT_SLACK_TOKEN
にslackのAPIトークンを直接記載してもよいのですが、docker-compose.yml
もgit管理にしたいのでBOT_SLACK_TOKEN
は.env
ファイルに記載します。
.env
ファイルを.gitignore
でgit管理外に設定することでAPIトークンを誤ってgithubにpushしないようにするためです。
BOT_SLACK_TOKEN=xoxb-...