マルチステージビルドした時のMeCabエラーを回避する


概要

MeCabを使ったマルチステージビルドで詰まったのでメモを残します。
今回はasariというパッケージを使いたかったためmecab-python3のバージョンが低いです。
今度時間があればバージョン上げても動くか検証してみます。

環境

python 3.7
mecab-python3 0.7

修正前

Dockerfile
FROM python:3.7-buster as builder

WORKDIR /work

RUN apt-get update \
    && apt-get install -y mecab mecab-utils libmecab-dev \
    && pip install -U pip

COPY requirements.txt /work

RUN pip install -r requirements.txt

FROM python:3.7-slim-buster as runner

COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages

WORKDIR /work

CMD python sample.py

sample.pyの中身はmecabを使用したファイルとします

sample.py
import MeCab

実行するとimportの際にエラーが出ます。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/MeCab.py", line 26, in <module>
    _MeCab = swig_import_helper()
  File "/usr/local/lib/python3.7/site-packages/MeCab.py", line 22, in swig_import_helper
    _mod = imp.load_module('_MeCab', fp, pathname, description)
  File "/usr/local/lib/python3.7/imp.py", line 242, in load_module
    return load_dynamic(name, filename, file)
  File "/usr/local/lib/python3.7/imp.py", line 342, in load_dynamic
    return _load(spec)
ImportError: libmecab.so.2: cannot open shared object file: No such file or directory

原因

エラー文にある通りlibmecab.so.2がないのが原因っぽいです。
一度マルチステージビルドしていない正しく動いたコンテナでどこにlibmecab.so.2があるのか調べてみます

>> find / | grep libmecab
/usr/share/doc/mecab/libmecab.html
/usr/share/doc/libmecab-dev
/usr/share/doc/libmecab-dev/changelog.Debian.gz
/usr/share/doc/libmecab-dev/copyright
/usr/share/doc/libmecab2
/usr/share/doc/libmecab2/changelog.Debian.gz
/usr/share/doc/libmecab2/copyright
/usr/lib/x86_64-linux-gnu/libmecab.so.2.0.0
/usr/lib/x86_64-linux-gnu/libmecab.a
/usr/lib/x86_64-linux-gnu/libmecab.so.2
/usr/lib/x86_64-linux-gnu/libmecab.so
/var/lib/dpkg/info/libmecab-dev.md5sums
/var/lib/dpkg/info/libmecab-dev.list
/var/lib/dpkg/info/libmecab2:amd64.triggers
/var/lib/dpkg/info/libmecab2:amd64.conffiles
/var/lib/dpkg/info/libmecab2:amd64.md5sums
/var/lib/dpkg/info/libmecab2:amd64.list
/var/lib/dpkg/info/libmecab2:amd64.shlibs

色々出てきましたが、とりあえずlibmecab.so.2は/usr/lib/x86_64-linux-gnu/libmecab.so.2にあることがわかったので、これをbuild用のコンテナからコピーすれば行けそうです

修正後

Dockerfile
FROM python:3.7-buster as builder

WORKDIR /work

RUN apt-get update \
    && apt-get install -y mecab mecab-utils libmecab-dev \
    && pip install -U pip

COPY requirements.txt /work

RUN pip install -r requirements.txt

FROM python:3.7-slim-buster as runner

COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages
# 追加部分
COPY --from=builder /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu

WORKDIR /work

CMD python sample.py

これで動きました。