DockerでAlpineイメージを使ってpandasのインストール&importエラーが発生した時にやったこと

Docker初心者です。Dockerを使い始めてUdemyのチュートリアル通りにやって問題なく動いていたのですが、pythonでAlipineイメージにpandasをインストールしようとしたらエラーが発生。それを解決したら今度はimportエラーが発生。解決するのに5日間、10h以上かかったので備忘録として残しておきます。（結果的にこの設定でうまく行ったというもので不要なライブラリのインストールなど含まれているかもしれませんのでご了承ください。）

#環境
mac OS 10.14
python3.7.3
Docker(Desktop for mac) 18.09.2
pandas 0.24.2

#pandasインストールエラーとなったファイル内容
```Dockerfile.
FROM　python:3.7.3-alpine3.9

ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /requirements.txt
RUN apk --update-cache add python3-dev postgresql-client \
    gcc libc-dev linux-headers postgresql-dev
RUN pip3 install --upgrade pip
RUN pip3 install -r /requirements.txt
（以下略）

```

```requirements.txt
Django>=2.1.3,<2.3.0
psycopg2>=2.7.5,<2.8.0
flake8>=3.6.0,<3.8.0
requests>=2.21.0
pandas
```

#事象その1
DockerのAlpineイメージを使ってpandasをインストールしたらエラー。

```
(中略)
Step 8/14 : RUN pip3 install -r /requirements.txt
 ---> Running in 7abd71a59c5b
(中略)
Building wheels for collected packages: psycopg2, pandas, numpy
  Building wheel for psycopg2 (setup.py): started
  Building wheel for psycopg2 (setup.py): finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/15/f1/8a/d13558357a3377f18341c9a66b2b38be2f5275bcbf8df891e0
  Building wheel for pandas (setup.py): started
  Building wheel for pandas (setup.py): finished with status 'error'
  ERROR: Complete output from command /usr/local/bin/python -u -c 'import setuptools, tokenize;__file__='"'"'/tmp/pip-install-cgl0ivji/pandas/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-nrxipcxk --python-tag cp37:
  ERROR: running bdist_wheel
  running build
  running build_py
(中略)
error: command 'gcc' failed with exit status 1
  ----------------------------------------
  ERROR: Failed building wheel for pandas

```

#解決策
Dockerfileに定義している、以下の部分に何かしら定義が漏れているとエラーとなるようです。

```
RUN apk --update-cache add python3-dev postgresql-client \
    gcc libc-dev linux-headers postgresql-dev
```

自分の場合はこれにg++を追加したらうまく行きました。

```
RUN apk --update-cache add python3-dev postgresql-client \
    gcc g++ libc-dev linux-headers postgresql-dev
```
[alpinelinux.org](https://pkgs.alpinelinux.org/packages)で調べてみましたが、g++はC++のライブラリとコンパイラーのようですね。最終的には事象その２で参考にさせて頂いたQiitaに合わせて下記ライブラリを追加しています。postgresqlを使うのでそれも追加しました。

[gcc](https://pkgs.alpinelinux.org/package/edge/main/x86_64/gcc)
[g++](https://pkgs.alpinelinux.org/package/edge/main/x86_64/g++)
[python3-dev](https://pkgs.alpinelinux.org/package/edge/main/x86_64/python3-dev)
[libc-dev](https://pkgs.alpinelinux.org/package/edge/main/x86_64/libc-dev)
[make](https://pkgs.alpinelinux.org/package/edge/main/x86_64/make)
[gfortran](https://pkgs.alpinelinux.org/package/edge/main/x86_64/gfortran)
[openblas-dev](https://pkgs.alpinelinux.org/package/edge/community/x86_64/openblas-dev)
[linux-headers](https://pkgs.alpinelinux.org/package/edge/main/x86_64/linux-headers)
[postgresql-client](https://pkgs.alpinelinux.org/package/edge/main/x86_64/postgresql-client)
[postgresql-dev](https://pkgs.alpinelinux.org/package/edge/main/x86_64/postgresql-dev)

インストールしたライブラリとパッケージは下記の通りです。

```
docker run -it <コンテナ名> /bin/sh
/app $ apk info
busybox
alpine-baselayout
alpine-keys
libcrypto1.1
libssl1.1
ca-certificates-cacert
libtls-standalone
ssl_client
zlib
apk-tools
scanelf
musl-utils
libc-utils
ca-certificates
libffi
libintl
libuuid
ncurses-terminfo-base
ncurses-terminfo
ncurses-libs
libbz2
sqlite-libs
xz-libs
expat
gdbm
krb5-conf
libcom_err
keyutils-libs
libverto
krb5-libs
libtirpc
libnsl
readline
.python-rundeps
libgcc
libstdc++
binutils
gmp
isl
libgomp
libatomic
mpfr3
mpc1
gcc
musl-dev
libc-dev
g++
libquadmath
libgfortran
gfortran
linux-headers
make
openblas-ilp64
openblas
pkgconf
openblas-dev
libedit
db
libsasl
libldap
libpq
postgresql-client
openssl-dev
postgresql-libs
postgresql-dev
python3
python3-dev
```

#事象その2
pandasのインストール正常終了後にpythonでpandasをimportしようとすると下記のエラーが発生。このエラー解決に一番時間がかかりました。

```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/pandas/__init__.py", line 42, in <module>
    from pandas.core.api import *
  File "/usr/lib/python3.7/site-packages/pandas/core/api.py", line 10, in <module>
    from pandas.core.groupby.groupby import Grouper
  File "/usr/lib/python3.7/site-packages/pandas/core/groupby/__init__.py", line 2, in <module>
    from pandas.core.groupby.groupby import (
  File "/usr/lib/python3.7/site-packages/pandas/core/groupby/groupby.py", line 49, in <module>
    from pandas.core.frame import DataFrame
  File "/usr/lib/python3.7/site-packages/pandas/core/frame.py", line 74, in <module>
    from pandas.core.series import Series
  File "/usr/lib/python3.7/site-packages/pandas/core/series.py", line 3978, in <module>
    Series._add_series_or_dataframe_operations()
  File "/usr/lib/python3.7/site-packages/pandas/core/generic.py", line 8891, in _add_series_or_dataframe_operations
    from pandas.core import window as rwindow
  File "/usr/lib/python3.7/site-packages/pandas/core/window.py", line 36, in <module>
    import pandas._libs.window as _window
ImportError: Error loading shared library libstdc++.so.6: No such file or directory (needed by /usr/lib/python3.7/site-packages/pandas/_libs/window.cpython-36m-x86_64-linux-gnu.so)
```
最後のメッセージにlibstdc++.so.6とありますが、このエラーメッセージから追っていってlibstdc++をインストールしてもダメで、そもそもこのエラーメッセージで検索しても英語では同じエラーの情報がほとんど見つからず、ヒットした中国語のサイトの解決策も試しましたがダメでした。


#解決策
こちらのQiitaを参考にさせて頂きました。
（結果的に日本語のサイトで解決できました。）

[Alpine Linuxにnumpy, scipy, scikit-learn, pandasを入れた](https://qiita.com/ricesho/items/e56bf08f51ea406674eb)

pandasのpipに--no-build-isolationをつけるとよいとの事。[githubのIssue](https://github.com/pypa/pip/issues/5299)によるとpipのバージョンも関係ありそうなのでpip3のバージョンアップとrequirements.txtに定義していたpandasを削除して下記の通りに変更。

```Dockerfile.
RUN pip3 install --upgrade pip
#pandasのpipに--no-build-isolationをつける
RUN pip3 install --no-cache-dir pandas --no-build-isolation
RUN pip3 install -r /requirements.txt
```

```requirements.txt
Django>=2.1.3,<2.3.0
psycopg2>=2.7.5,<2.8.0
flake8>=3.6.0,<3.8.0
requests>=2.21.0
#ここにあったpandasを削除
```

ちなみにAlpineイメージは3.7.3-alpine3.9→3.7.3-alpineに変更しています。

```Dockerfile.
FROM python:3.7.3-alpine
```

上記を全てやった後にdockerをbuild&docker-composeもbuild。

```
docker build .
docker-compose build
```

Dockerコンテナ上でpythonインタプリタを立ち上げ。

```
docker run -it <コンテナ名> /bin/sh
/app $ python3
Python 3.7.3 (default, Jun 27 2019, 22:53:21) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas
>>>
```

importできました！