#はじめに
社内のサーバーサイド公式言語であるGolangで、
形態素解析ライブラリのMeCab+NEologd
を試したいな〜
という情熱が燃えたぎったので、挑戦してみました。
Dockerfile、初体験であります。(ドキドキ)
#TL;DR
-
main.go
の用意 -
docker-compose.yml
の用意 -
Dockerfile
の作成 -
startup.sh
の作成
#main.go
go ginのフレームワークを使って、REST APIを作成し、テキストを受け取るとともにMeCabによる形態素解析の結果を返すmain.go
です。
(※エディタはgoland
を使いました。Go Modules
とかの管理が楽)
package main
import (
"fmt"
"log"
"net/http"
mecab "github.com/bluele/mecab-golang"
"github.com/gin-gonic/gin"
)
const (
ipadic = "/usr/local/lib/mecab/dic/mecab-ipadic-neologd"
)
func main() {
// Start HTTP server
r := gin.Default()
r.POST("/analyze", morphologicalAnalyze)
if err := r.Run(":8080"); err != nil {
log.Fatal(err)
}
}
func morphologicalAnalyze(c *gin.Context) {
text := c.PostForm("text")
// mecab here
mecab, err := mecab.New("-Owakati")
if err != nil {
panic(err)
}
defer mecab.Destroy()
data := parseToNode(mecab, text)
if err != nil {
c.JSON(http.StatusInternalServerError, "Something went wrong")
return
}
c.IndentedJSON(http.StatusOK, data)
}
func parseToNode(m *mecab.MeCab, text string) []map[string]interface{} {
tg, err := m.NewTagger()
if err != nil {
panic(err)
}
defer tg.Destroy()
lt, err := m.NewLattice(text)
if err != nil {
panic(err)
}
defer lt.Destroy()
node := tg.ParseToNode(lt)
data := make([]map[string]interface{}, 0)
for {
entry := make(map[string]interface{})
fmt.Printf("%s\t%s\n", node.Surface(), node.Feature())
entry[node.Surface()] = node.Feature()
data = append(data, entry)
if node.Next() != nil {
break
}
}
return data
}
※動かなかったらごめんなさいorz
#docker-compose.yml
goのAPIサーバーのコンテナを立ち上げるdocker-compose
ファイルです。
超軽量のAlpine Linux
のGo 1.15.10
のイメージを使ってコンテナを立ち上げます。
version: "3.8"
services:
api:
image: go-mecab-challenge:golang-1.15.10-alpine3.12
build:
context: ./docker/go
dockerfile: Dockerfile
container_name: api
ports:
- 8080:8080
volumes:
- ./api:/go/src/github.com/go-mecab-challenge/api
- /Users/username/go:/go
working_dir: /go/src/github.com/go-mecab-challenge/api/src
environment:
- APP_STAGE=local
- LOG_LEVEL=debug
必要なフォルダをdocker側にマウントする。
#Dockerfile
まずDockerfileをビルドして、コンテナを立ち上げる事前準備をします。
(※ちょっと時間かかる)
$ docker build ./docker/go # Dockerfileのあるディレクトリ指定
Alpine Linux
は超軽量なので、無駄なコマンドやファイル等が削られている状況。
なので、必要なコマンドであったりをapk add
でインストールしてカスタマイズが必要。
※下記、不要なものもあるはずなので、ご査収下さい。
FROM golang:1.15.10-alpine3.12
ENV MECAB_VERSION 0.996
ENV IPADIC_VERSION 2.7.0-20070801
ENV MECAB_URL https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE
ENV IPADIC_URL https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM
RUN apk update && \
apk upgrade && \
apk add --no-cache build-base curl git bash openssl openssh-client sudo && \
curl -SL -o mecab-${MECAB_VERSION}.tar.gz ${MECAB_URL} && \
tar zxf mecab-${MECAB_VERSION}.tar.gz && \
cd mecab-${MECAB_VERSION} && \
./configure --enable-utf8-only --with-charset=utf8 && \
make && \
make install && \
cd && \
curl -SL -o mecab-ipadic-${IPADIC_VERSION}.tar.gz ${IPADIC_URL} && \
tar zxf mecab-ipadic-${IPADIC_VERSION}.tar.gz && \
cd mecab-ipadic-${IPADIC_VERSION} && \
./configure --with-charset=utf8 && \
make && \
make install && \
cd && \
git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git /mecab-ipadic-neologd && \
/mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -a -y -p /usr/local/lib/mecab/dic/mecab-ipadic-neologd && \
echo "dicdir = /usr/local/lib/mecab/dic/mecab-ipadic-neologd" > /usr/local/etc/mecabrc && \
rm -rf \
mecab-${MECAB_VERSION}* \
mecab-${IPADIC_VERSION}* \
/mecab-ipadic-neologd
COPY startup.sh /startup.sh
RUN chmod 744 /startup.sh
CMD ["/startup.sh"]
###解説
- 環境変数として、
MeCab
や辞書ipadic
の情報を設定 -
alpine
のパッケージ管理コマンドapk
で必要なコマンド、ファイル等をインストール- コマンドたち:
curl git bash openssl sudo
-
openssh-client
: ssh接続に使えるssh hostname
とか -
build-base
:binutils, file, gcc, g++, make, libc-dev, fortify-headers, patch
を含む-
binutils
: GNUが提供しているツールのうち、バイナリのプログラミングを実装するためのツール -
gcc
: GNU Compiler Collection (グニューコンパイラコレクション) のこと -
g++
: [GNU C++コンパイラ] (https://ja.wikipedia.org/wiki/GNU%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3) -
libc-dev
: Linux カーネル由来のユーザスペースヘッダ群を提供するパッケージ。インストール済みのGNU libc
用ヘッダやほかの システムライブラリ用ヘッダで利用するそう
-
- コマンドたち:
-
MeCab
が保存されているgoogle drive
に直接アクセスしてtar.gz
をとってくる
-tar.gz
を解凍して展開 -
MeCab
のコンパイル用の設定(configure
)をして、コンパイル(make
)→インストール(make install
) -
ipadic
のインストール。MeCab
と同じ手順 -
NeoLogd
のインストール:gitリポジトリをとってきて、その中のコマンドを叩いてダウンロードする - 一旦不要になったフォルダやファイルを
rm
する -
startup.sh
でAPIサーバー起動
###ローカルへのMeCabインストールはこちらを参考ください
https://qiita.com/ichi_zamurai/items/6311614f83fc30dd28d2
#立ち上げCMDはShellScriptに別で記述
#!/bin/bash
export CGO_LDFLAGS="-L/usr/local/Cellar/mecab/0.996/lib -lmecab -lstdc++"
export CGO_CFLAGS="-I/usr/local/Cellar/mecab/0.996/include"
go run main.go --host 0.0.0.0 --port 8080
###解説と懸念点
-
MeCab
自体はC言語で書かれたライブラリらしく、go言語で使用する時にはCGO
という機能を使う必要があり、二つのパスをexport
させてからGo実行している。 - 実際にローカルでメカブを
$ go get github.com/bluele/mecab-golang
するときも、上記のexport
が必要。 - ただ、実行しているdockerコンテナ上に上記のパスがなかったんだけど、やってる意味あるのかなあ。。。という懸念点です。(要調査)
$ docker exec -it api /bin/bash # apiはコンテナ名。実行しているコンテナ内に潜り込む
#形態素解析「すもももももももものうち」
いざ桃太郎、出陣!!
goのAPIを叩いて、すももちゃんを投げてみる。
おお、できた。
ああ、でも、NEologd
をつかったら、なんだか一つの固有名詞になっちゃった。
実際にローカルで普通に やってみると(ipadic)
$ echo "すもももももももものうち" | mecab
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS
ってなったのになあ。
辞書の使い分けが必要っぽいなこれ。
もうひとつw
###「サンタさん立ったのたったの三本指で」
#まとめ
[GO+MeCab+Neologd+Docker]
という念願のアプリケーションを作ることができました。
まあ実用化には一切届かないけど、やっぱり立ち上げって大変だ。けど、面白い。
あとは想像力と努力で、アプリケーションを育てていくしかない。(∵)
例えば、各単語をポイント付けして、
固有名詞だけ重くして、バズりワードの解析とか、やったら面白そう。
以上ありがとうございました。
##こちらを参考にDockerfile作成させていただきました♪
わかりやすかったです。
参考:Alpine LinuxでMeCab with NEologd
参考:DockerでMeCab / Word2Vecの環境を構築する