ํต์ฌ ์์ฝ
- 1ํธ์์ "์ ๊ทธ๋ฅ ์ ๋๋๊ฐ"(RHEL 6.5 = GLIBC 2.12 = ์ต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฑฐ๋ถ)๋ฅผ ์ ๋ฆฌํ์ต๋๋ค. ์ด๋ฒ ํธ์ ์ค์ ๋ก ์์ฒด์๊ฒฐ ๋ฒ๋ค์ ๋ง๋ ๊ณผ์ ์ ๋๋ค.
- ํต์ฌ์ RHEL 6.5์ ๊ฐ์ GLIBC 2.12 ํ๊ฒฝ(
manylinux2010๋์ปค ์ด๋ฏธ์ง)์์ ๋น๋ํ๋ ๊ฒ์ ๋๋ค. ์๋์ฐ๋ ์ต์ ์ฐ๋ถํฌ์์ ๋ง๋ค๋ฉด GLIBC๊ฐ ๋์ RHEL 6.5์์ ์ ๋๋๋ค. - ๋ง๋๋ ๋์ ํจ์ ์ด ์ฌ๋ฟ ์์์ต๋๋ค. โ ๋์ปค์ Python์ด ์ค์ ํ์ผ์ด ์๋๋ผ ์ฌ๋ณผ๋ฆญ ๋งํฌ์๋ ๊ฒ(๋ฒ๋ค์ด 196KB๋ก ๋์ด) โก RHEL 6.5์ ์๋ ๋นํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ 2๊ฐ๋ฅผ ๊ฐ์ด ๋ด์์ผ ํ๋ ๊ฒ โข ๊ฒ์ฆ ํ๊ฒฝ(CentOS 6 ์ปจํ ์ด๋)์ด ์ธ๊ทธํดํธ๋ก ์ฃฝ์ ๊ฒ ๋ฑ์ ๋๋ค.
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋๋ฟ ์๋๋ผ ์ฑ์ด ๋๊น์ง ๋๋์ง(์์ง→ํ์ง→๋ฆฌํฌํธ), ๋ชจ๋ธ ์ฌํ์ต, ๊ทธ๋ํ ํ๊ธ ํฐํธ๊น์ง ๊ฒ์ฆํ์ต๋๋ค.
- ์ต์ข
์ฐ์ถ๋ฌผ์ ์ฝ 124MB์
tar.gzํ ๊ฐ์ ๋๋ค. RHEL 6.5์์ ์ธํฐ๋ท·์์คํ ํ์ด์ฌ ์์ด ํ์ด์ ์คํํ๋ฉด ํ๊ธ ๊ทธ๋ํ ๋ฆฌํฌํธ๊น์ง ๋์ต๋๋ค.
1. ๋น๋ ์ ๋ต: ์ ๋์ปค์ด๊ณ , ์ manylinux2010์ธ๊ฐ
๋ง๋ค ๊ฒ์ "์ธํฐ๋ท ์์ด RHEL 6.5์์ ๊ทธ๋ฅ ํ๋ฉด ๋๋ ํ ๋ฉ์ด๋ฆฌ(tar.gz)" ์ ๋๋ค. ์์ ๋ค์ด๊ฐ ๊ฒ์ โ RHEL 6.5 ํธํ Python โก ๋ผ์ด๋ธ๋ฌ๋ฆฌ โข ์ฑ ์ฝ๋ โฃ ๋ชจ๋ธ์ ๋๋ค.
์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ ๊ฒฐ์ ์ ์ด๋์ ๋น๋ํ๋๋์
๋๋ค. 1ํธ์์ ๋ดค๋ฏ, RHEL 6.5๋ GLIBC 2.12๋ผ ๊ทธ ํ๊ฒฝ์์ ๋๋ Python·๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ์ GLIBC 2.12 ํ๊ฒฝ์์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ๊ทธ ํ๊ฒฝ์ ์์ฝ๊ฒ ์ฃผ๋ ๊ฒ์ด manylinux2010 ๋์ปค ์ด๋ฏธ์ง์
๋๋ค. ์ด ์ด๋ฏธ์ง๋ CentOS 6 ๊ธฐ๋ฐ(GLIBC 2.12)์ ํ์ด์ฌ ํจํค์ง ๋น๋์ ํ์ํ ๊ฒ๋ค์ด ๋ฏธ๋ฆฌ ๋ค์ด ์์ต๋๋ค.
๋์ปค ์ปจํ ์ด๋๋ "๊ทธ ์ค๋๋ง๊ณผ ๋๊ฐ์ ๋ก์ ๋ฐฉ์ ์ฆ์์์ ์ง๊ณ ๋ค ์ฐ๋ฉด ๋ฒ๋ฆฌ๋ ์กฐ๋ฆฝ์ ๋ฐฉ"์ ๋๋ค. manylinux2010์ "RHEL 6.5์ ๊ฐ์ ํํ์ ๋ชจ๋ธํ์ฐ์ค"์ ๋๋ค. ๊ฐ๊ตฌ(ํ์ด์ฌ·๋ผ์ด๋ธ๋ฌ๋ฆฌ)๋ ๊ทธ ๋ชจ๋ธํ์ฐ์ค ์์์ ๋ง์ถฐ์ผ ์ง์ง ์ค๋๋ง ๋ฌธํ(๋ฎ์ GLIBC)์ ๋ค์ด๊ฐ๋๋ค.

manylinux2010 ์ปจํ ์ด๋(CentOS 6 / GLIBC 2.12)์์ ๋ฒ๋ค์ ๋ง๋ค๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฌผ์ RHEL 6.5์ ๊ฐ์ ธ๊ฐ๋ ํ๋ฆ์ ๋ณด์ฌ์ค๋๋ค. ๋ ํ๊ฒฝ์ GLIBC๊ฐ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋น๋ ๊ฒฐ๊ณผ๊ฐ ๋ชฉ์ ์ง์์ ๊ทธ๋๋ก ๋๋ค๋ ์ ์ด ํต์ฌ์ ๋๋ค.
๋ก์ปฌ์ ๋์ปค๊ฐ ๊น๋ ค ์์ผ๋ฉด(Docker Desktop) ๋ณ๋ ์๋ฒ ์์ด ์๋์ฐ์์๋ ๋ฆฌ๋ ์ค ์ปจํ ์ด๋๋ก ๋น๋ํ ์ ์์ต๋๋ค. ์ด๋ฏธ์ง๋ถํฐ ๋ฐ์ต๋๋ค.
$ docker pull quay.io/pypa/manylinux2010_x86_64
Status: Downloaded newer image ... # ์ฝ 1GB
์ปจํ
์ด๋ ์์์ Python 3.7์ /opt/python/cp37-cp37m/bin/python ์ ์์ต๋๋ค.
2. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ง์ง ๋๋์ง ๋จผ์ ํ์ธ
์ ๋ต์ ์ข์๋ฐ, ๊ฐ์ฅ ํฐ ์๋ฌธ์ด ๋จ์ ์์์ต๋๋ค.
"๊ทธ๋์ ์ง์ง๋ก, RHEL 6.5์์ ๋๋(manylinux2010) pandas·scikit-learn์ด ์กด์ฌํ๊ธด ํ๋?"
์ด๊ฒ ์ ๋๋ฉด ์ ๋ต ์์ฒด๊ฐ ๋ฌด๋์ง๋๋ค. ๊ทธ๋์ ์ด๊ฑธ ์ ์ผ ๋จผ์ ํ์ธํ์ต๋๋ค.
๋จผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฐ์ ์ ์๋์ง๋ถํฐ ๋ดค์ต๋๋ค. ์ฌ๊ธฐ์ ์ค์ํ ์ ์, ์ด ํ์ธ์ ์๋์ฐ ๋ก์ปฌ์์ ํ๋ค๋ ๊ฒ์
๋๋ค. pip download๋ ํจํค์ง๋ฅผ ์ค์น·์คํํ์ง ์๊ณ ํ์ผ๋ง ๋ด๋ ค๋ฐ๊ธฐ๋ง ํ๊ณ , "์ด๋ค OS·ํ์ด์ฌ ๋ฒ์ ์ฉ wheel์ ๋ฐ์์ง"๋ฅผ ์ต์
์ผ๋ก ์ง์ ํ ์ ์์ด์, ์๋์ฐ์์๋ RHEL 6.5์ฉ ๋ฆฌ๋
์ค wheel ํ์ผ์ ๋ฐ์๋ณผ ์ ์์ต๋๋ค.
$ pip download --only-binary=:all: \
--platform manylinux2010_x86_64 --platform manylinux1_x86_64 \
--python-version 37 --implementation cp --abi cp37m \
-d ./wheels \
numpy==1.19.5 scipy==1.5.4 pandas==1.1.5 \
scikit-learn==0.24.2 matplotlib==3.3.4 joblib==1.1.0 PyYAML==5.4.1
์ต์ ์ ํ์ด ์ฝ์ผ๋ฉด ์ด๋ ์ต๋๋ค.
--platform manylinux2010_x86_64: "RHEL 6.5(CentOS 6) ํธํ wheel๋ง"--python-version 37: "ํ์ด์ฌ 3.7์ฉ์ผ๋ก" (๊ตฌ๋ฒ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ณดํต 3.7๊น์ง manylinux2010 wheel์ด ์์)--only-binary=:all:: "์์ค ๋ง๊ณ ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ wheel๋ง" (ํ์ฅ์์ ์ปดํ์ผ ๋ชป ํ๋๊น)- ๋ฒ์ ์ ๊ตฌ๋ฒ์ ์ผ๋ก ์ฝ ์ง์ (pandas 1.1.5 ๋ฑ) — ์ต์ ์ manylinux2014๋ผ ์ ๋๋๊น
๊ฒฐ๊ณผ๋ ์ ๋ถ ๋ฐ์์ก์ต๋๋ค. 15๊ฐ wheel, ํฉ๊ณ 86MB. ํ์ผ ์ด๋ฆ ๋์ manylinux2010_x86_64·manylinux1_x86_64๊ฐ "RHEL 6.5์์ ๋๋ค"๋ ๋ณด์ฆ์์
๋๋ค.
numpy-1.19.5-cp37-cp37m-manylinux2010_x86_64.whl # RHEL6.5 ํธํ
scipy-1.5.4-cp37-cp37m-manylinux1_x86_64.whl # ๋ ์๋ ๊ธฐ์ค์ด๋ผ ๋ ์์
pandas-1.1.5-cp37-cp37m-manylinux1_x86_64.whl
scikit_learn-0.24.2-cp37-cp37m-manylinux2010_x86_64.whl
matplotlib-3.3.4-cp37-cp37m-manylinux1_x86_64.whl
...
๊ทธ๋ฐ๋ฐ "๋ฐ์์ง๋ค"์ "์ง์ง ๋๋ค"๋ ๋ค๋ฆ
๋๋ค. ๋ค์์ผ๋ก, manylinux2010 ์ปจํ
์ด๋ ์์์ ์ธํฐ๋ท์ ๋๊ณ (--no-index) ์ค์นํ๊ณ import๊น์ง ๋๋์ง ๋ดค์ต๋๋ค.
$ docker run --rm -v "$PWD/wheels:/wheels:ro" -v "$PWD:/deploy:ro" \
quay.io/pypa/manylinux2010_x86_64 bash -c '
cat /etc/redhat-release; ldd --version | head -1
PY=/opt/python/cp37-cp37m/bin/python; $PY --version
$PY -m pip install --no-index --find-links /wheels -r /deploy/requirements-rhel65.txt
MPLBACKEND=Agg $PY -c "import numpy,scipy,pandas,sklearn,matplotlib,yaml,joblib; print(pandas.__version__)"'
๊ฒฐ๊ณผ:
CentOS release 6.10 (Final)
GLIBC: ldd (GNU libc) 2.12
Python 3.7.13
Successfully installed numpy-1.19.5 pandas-1.1.5 scikit-learn-0.24.2 ... matplotlib-3.3.4
ALL OK -> pandas 1.1.5 | sklearn 0.24.2 | numpy 1.19.5 | matplotlib 3.3.4
--no-index๋ "๋งํธ(์ธํฐ๋ท) ๋ฌธ์ ์ ๊ทธ๊ณ , ๋ค๊ณ ์จ ์ฅ๋ฐ๊ตฌ๋(wheel)๋ง์ผ๋ก ์๋ฆฌ๊ฐ ๋๋ ๋ณธ ๊ฒ"์ ๋๋ค.import์ฑ๊ณต์ "์ฌ๋ฃ๋ฅผ ์ค์ ๋ก ๋๋น์ ๋ฃ์ด๋ณด๋ ๋ฉ์ฉกํ ์ต๋๋ผ" — ์ฆ ๋ณด๊ด๋ง ๋ ๊ฒ ์๋๋ผ ์ง์ง ์ธ ์ ์๋ ์ํ์์ ํ์ธํ ๊ฒ์ ๋๋ค.
import๊ฐ ์ ๋ถ ์ฑ๊ณตํ๋ค๋ ๊ฑด GLIBC 2.12(=RHEL 6.5)์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ค์ ๋ก ๋ก๋๋๋ค๋ ์ค์ฆ์
๋๋ค. ์ด ์์
์ ๊ฐ์ฅ ํฐ ๋ถํ์ค์ฑ์ด ์ฌ๊ธฐ์ ํ๋ ธ์ต๋๋ค.

์๋์ฐ ๋ก์ปฌ์์ pip download๋ก wheel์ ๋ฐ๊ณ , ๊ทธ๊ฒ์ manylinux2010 ์ปจํ
์ด๋์ ๋ฃ์ด ์ธํฐ๋ท ์์ด ์ค์น·import๊น์ง ๊ฒ์ฆํ๋ ๋จ๊ณ๋ฅผ ๋ณด์ฌ์ค๋๋ค. "๋ฐ๊ธฐ"์ "์ค์ ๋ก ๋๊ธฐ"๋ฅผ ๋ถ๋ฆฌํด ํ์ธํ๋ค๋ ์ ์ด ๋๋ฌ๋ฉ๋๋ค.
3. ๋ฒ๋ค ์กฐ๋ฆฝ๊ณผ ์ฒซ ํจ์ : ์ฌ๋ณผ๋ฆญ ๋งํฌ
์ด์ ์ค์ ๋ก ํ ๋ฉ์ด๋ฆฌ๋ก ๋ฌถ์ ์ฐจ๋ก์ ๋๋ค. ์ฒ์์ ๋จ์ํ๊ฒ "๋์ปค ์ Python ํด๋๋ฅผ ๋ณต์ฌํ๋ฉด ๋๊ฒ ์ง" ํ์ต๋๋ค.
cp -r /opt/python/cp37-cp37m $BUNDLE/python
๊ทธ๋ฐ๋ฐ ๋ฒ๋ค์ด 196KB๋ฐ์ ์ ๋์ต๋๋ค. Python ํ๋๊ฐ ์์ญ MB์ผ ํ
๋ฐ ์ด์ํฉ๋๋ค. ํ์ธํด๋ณด๋ /opt/python/cp37-cp37m์ ์ค์ Python์ด ์๋๋ผ ๋งํฌ ๋ชจ์์ด์๊ณ , ์ง์ง Python์ ๋ค๋ฅธ ๊ณณ์ ์์์ต๋๋ค.
$ readlink -f /opt/python/cp37-cp37m/bin/python3.7
/opt/_internal/cpython-3.7.13/bin/python3.7 # ์ง์ง๋ ์ฌ๊ธฐ (68MB)
๋ ๊ณ ์ฝํ ๊ฑด, ์ฒซ "์ฌ๋ฐฐ์น ๊ฒ์ฆ"์ด ๊ฑฐ์ง์ผ๋ก ํต๊ณผํ๋ค๋ ์ ์
๋๋ค. ๋ณต์ฌ๋ณธ์ด ๋งํฌ๋ผ, ์ปจํ
์ด๋ ์์ ๋จ์์๋ ์๋ณธ์ ๋ฐ๋ผ๊ฐ์ import๊ฐ ๋๋ ๊ฒ์
๋๋ค. ๋ชฉ์ ์ง(RHEL 6.5)์ ์๋ณธ์ด ์์ผ๋ ์ค์ ๋ก ์ ๋์ ์ํฉ์
๋๋ค.
๋์ฅ๊ณ ๋ฅผ ํต์งธ๋ก ์ฎ๊ธด ์ค ์์๋๋ฐ, ์๊ณ ๋ณด๋ ์ฎ๊ธด ๊ฑด "๋์ฅ๊ณ ๋ ์ ์ชฝ์ ์์"์ด๋ผ๊ณ ์ ํ ์ชฝ์ง(๋งํฌ)์์ต๋๋ค. ์ง์ง ๋์ฅ๊ณ (์๋ณธ Python)๋ ์๋ ๋ฐฉ์ ๊ทธ๋๋ก ์์ด์, ๊ทธ ๋ฐฉ ์์์ ํ ์คํธํ๋ฉด ์ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค(๊ฑฐ์ง ํต๊ณผ). ์ชฝ์ง๋ง ๋ค๊ณ ์ค๋๋ง์ ๊ฐ๋ฉด ๋์ฅ๊ณ ๊ฐ ์์ต๋๋ค.

cp -r๋ก ์ฎ๊ธด ๊ฒ์ด ์ค์ ํ์ผ์ด ์๋๋ผ ์๋ณธ์ ๊ฐ๋ฆฌํค๋ ๋งํฌ์๊ณ , ๊ฐ์ ์ปจํ
์ด๋ ์์ ์๋ณธ์ด ๋จ์ ์์ด ํ
์คํธ๊ฐ ํต๊ณผํ ๊ฒ์ฒ๋ผ ๋ณด์๋ ์ํฉ์ ๋ณด์ฌ์ค๋๋ค. ๋ชฉ์ ์ง์ ์๋ณธ์ด ์์ผ๋ฏ๋ก ์ค์ ๋ก๋ ๋์ํ์ง ์๋๋ค๋ ์ ์ด ํต์ฌ์
๋๋ค.
๊ตํ์ ๋ ๊ฐ์ง์
๋๋ค. โ ์ง์ง Python(/opt/_internal/cpython-3.7.13)์ ๋ณต์ฌํ ๊ฒ โก ๊ฒ์ฆ์ "์๋ณธ์ ๋ค ์น์ด ์ํ"๋ก ํด์ผ ์ง์ง๋ค.
4. ๊ฐ์ด ๋ด์์ผ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฐพ๊ธฐ (ldd)
Python์ ์ ๋๋ก ๋ณต์ฌํ์ด๋ ๋์ด ์๋๋๋ค. Python ๋ฐ์ด๋๋ฆฌ์ ํ์ค ํ์ฅ ๋ชจ๋์ด ์์กดํ๋ ๊ณต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.so) ์ค RHEL 6.5์ ์๋ ๊ฒ์ด ์์ผ๋ฉด ์คํ ์ ์ฃฝ์ต๋๋ค. ๊ทธ๋์ ldd๋ก ์์กด์ฑ์ ํ์ด, ํ์ค ์์คํ
๊ฒฝ๋ก(/lib64·/usr/lib64) ๋ฐ๊นฅ์์ ์ค๋ ๊ฒ์ ์ฐพ์์ต๋๋ค.
$ { ldd .../python3.7; find . -name "*.so*" -exec ldd {} \; ; } \
| grep -E '=> (/usr/local|/opt)'
libcrypt.so.2 => /usr/local/lib/libcrypt.so.2 # libxcrypt, 198KB
libsqlite3.so.0 => /usr/local/lib/libsqlite3.so.0 # 1.2MB
๋ฑ ๋ ๊ฐ์์ต๋๋ค. ์ด ๋๋ง ๋ฒ๋ค์ ๊ฐ์ด ๋ฃ๊ณ , ์คํํ ๋ LD_LIBRARY_PATH๋ก ์ก์์ฃผ๋ฉด ๋ฉ๋๋ค.
ํด๋์ฉ ๋ถ์(Python)์ด ํน์ ์ฝ์ผํธ ๋ ๊ฐ(libcrypt·libsqlite3)๊ฐ ์์ด์ผ ๋๋๋ฐ, ๋ก์ ์ค๋๋ง์ ๊ทธ ์ฝ์ผํธ๊ฐ ์์ด ์ด๋ํฐ ๋ ๊ฐ๋ ๋ฐ์ค์ ๊ฐ์ด ์ฑ๊ธฐ๋ ์ ์ ๋๋ค.
๋๋จธ์ง๋ ์ด๋ป๊ฒ ์๊ธ๋๋์ง๋ ํ์ธํ์ต๋๋ค.
- numpy·scipy·matplotlib·Pillow์ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(openblas·libpng ๋ฑ): manylinux wheel์ด ํจํค์ง ์
*.libs/ํด๋์ ์์ฒด ํฌํจํฉ๋๋ค. → ๋ฒ๋ค์ ๊ทธ๋๋ก ๋ฐ๋ผ์ต๋๋ค(์๊ธ). - openssl(
_ssl·_hashlib): manylinux Python์ openssl์ ์ ์ ๋งํฌํฉ๋๋ค(ldd์ libssl ์์,ssl.OPENSSL_VERSION์ด ํ์๋จ). → ์ธ๋ถ openssl ๋ถํ์(์๊ธ).
openssl์ "๋ฐฐํฐ๋ฆฌ ๋ด์ฅํ ๋๊ตฌ"๋ผ ์ฝ์ผํธ๊ฐ ํ์ ์๊ณ , numpy·matplotlib ๊ฐ์ ์ฌ๋ฃ๋ "์๊ธฐ ์๋ ์ ํต์งธ๋ก ๋ค๊ณ ๋ค๋๋" ์ ์ ๋๋ค. ๊ทธ๋์ ๋ฐ์ค ๋ฐ์์ ๋ ์ฑ๊ธธ ๊ฒ ๋ฑ ๋ ๊ฐ๋ฟ์ด์์ต๋๋ค.
์ด์ ๋ฒ๋ค์ ์กฐ๋ฆฝํฉ๋๋ค(์ปจํ ์ด๋ ์์์).
B=/work/db_ai_bundle
cp -r /opt/_internal/cpython-3.7.13 $B/python # ์ง์ง Python
mkdir $B/python/lib_extra
cp -P /usr/local/lib/libcrypt.so.2* libsqlite3.so.0* $B/python/lib_extra/ # ๋นํ์ค .so 2์ข
$B/python/bin/python3.7 -m pip install --no-index --find-links /wheels -r requirements.txt
cp app/*.py app/config.yaml $B/app/ ; cp -r models $B/app/models # ์ฑ ์ฝ๋+๋ชจ๋ธ
cp run.sh $B/ ; tar czf bundle.tar.gz db_ai_bundle # ์์ถ
run.sh๋ ๋ฒ๋ค ์ Python์ผ๋ก ์ฑ์ ์คํํ๋ ๋ฐ์ฒ์
๋๋ค. ๋๋ดํ .so ๋ ๊ฐ๋ฅผ ์ฐพ๋๋ก LD_LIBRARY_PATH๋ฅผ ์ก์์ค๋๋ค.
#!/bin/bash
DIR="$(cd "$(dirname "$0")" && pwd)"
export LD_LIBRARY_PATH="$DIR/python/lib_extra:$LD_LIBRARY_PATH"
cd "$DIR/app"
exec "$DIR/python/bin/python3.7" main.py "$@"

๋ฒ๋ค ํ ๋ฉ์ด๋ฆฌ ์์ Python ์คํ๊ธฐ์ ๋๋ดํ ๋นํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ(lib_extra), ์ฑ ์ฝ๋์ ๋ชจ๋ธ, ์คํ ๋ฐ์ฒ๊ฐ ์ด๋ป๊ฒ ๋ค์ด๊ฐ๋์ง ๋ณด์ฌ์ค๋๋ค. ๋ฐ์ค ๋ฐ์์ ๋ฐ๋ก ์ฑ๊ธธ ๊ฒ์ด ๋นํ์ค .so ๋ ๊ฐ๋ฟ์ด๋ผ๋ ์ ์ด ๋๋ฌ๋ฉ๋๋ค.
๊ฒฐ๊ณผ๋ ๋ฒ๋ค ํด๋ ์ฝ 414MB, ์์ถ๋ณธ tar.gz ์ฝ 124MB์์ต๋๋ค.
5. ์ง์ง ๊ฒ์ฆ: ๊นจ๋ํ ํ๊ฒฝ์์ ์๊ธ์์กฑ
3์ฅ์ ๊ตํ๋๋ก, ๊ฒ์ฆ์ "์๋ณธ์ ๋ค ์น์ด ์ํ"๋ก ํด์ผ ํฉ๋๋ค. ์ฒ์์ ์ง์ง RHEL 6.5์ ๊ฐ๊น์ด CentOS 6 ๋์ปค ์ด๋ฏธ์ง(centos:6)๋ก ํ์ด๋ณด๋ ค ํ์ต๋๋ค.
$ docker run --rm centos:6 bash -c 'cat /etc/redhat-release; ...'
$ echo $?
139 # ์ธ๊ทธํดํธ
์ข ๋ฃ์ฝ๋ 139๋ ์ธ๊ทธํดํธ์ ๋๋ค. CentOS 6 ์ปจํ ์ด๋๊ฐ ์ต์ ์ปค๋์์ ๋ชป ๋๋ ์๋ ค์ง ๋ฌธ์ (vsyscall)์ ๋๋ค. CentOS 6 ์ด๋ฏธ์ง ์์ฒด๋ฅผ ํ ์คํธ ๋ฒ ๋๋ก ์ธ ์ ์์์ต๋๋ค.
๋์ , ์ด๋ฏธ ์ ๋๋ manylinux2010(๊ฐ์ GLIBC 2.12) ์์์ manylinux ์ ์ฉ ๊ฒฝ๋ก๋ฅผ ์จ๊ฒจ RHEL 6.5๋ฅผ ์ฌํํ์ต๋๋ค.
mv /opt/_internal /opt/_internal_HIDDEN # ์๋ณธ Python ์น์
mv /usr/local/lib /usr/local/lib_HIDDEN # ๋นํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ์ฒ ์น์
cd /tmp/db_ai_bundle ; export LD_LIBRARY_PATH=$PWD/python/lib_extra
ldd python/bin/python3.7 | grep 'not found' # ๋ฏธํด๊ฒฐ ์์ ํ์ธ
./python/bin/python3.7 importtest.py
๊ฒฐ๊ณผ:
๋ฏธํด๊ฒฐ(not found) ์์
Python 3.7.13
FULL import OK
pandas 1.1.5 | sklearn 0.24.2 | numpy 1.19.5 | matplotlib 3.3.4
ssl: OpenSSL 1.1.1q | sqlite3: 3.39.2
์๋ณธ Python๊ณผ ๋นํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ๋ค ์น์ด ์ํ์์, ๋ฒ๋ค ์์ฒด ์์๋ง์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ์ค ๋ชจ๋(ssl·sqlite3 ๋ฑ)๊น์ง ์ ๋ถ ๋ก๋๋์ต๋๋ค. GLIBC 2.12์์ ์๊ธ์์กฑ์ผ๋ก ๋๋ ๊ฒ์ ์ค์ฆํ ๊ฒ์
๋๋ค.

๋น๋ ํ๊ฒฝ์ ๋จ์ ์๋ ์๋ณธ Python·๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ์ผ๋ถ๋ฌ ์น์ฐ๊ณ (์จ๊ธฐ๊ณ ), ๋ฒ๋ค ์์ ์์๋ง์ผ๋ก ๋์ํ๋์ง ํ์ธํ๋ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ค๋๋ค. "๋ฐ์ค ๋ฐ ๋์ ์์ด ๋์ผ๋ ์ง์ง ์ค๋๋ง์์๋ ๋๋ค"๋ ๋ ผ๋ฆฌ๋ฅผ ์๊ฐํํฉ๋๋ค.
6. ์ฑ์ด ๋๊น์ง ๋๋๊ฐ (e2e)
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋๋ฟ ์๋๋ผ, ์ฐ๋ฆฌ ์ฑ์ด ์ด ๊ตฌ๋ฒ์ ์คํ(Python 3.7·pandas 1.1.5)์์ ๋๊น์ง ๋๋์ง๋ ํ์ธํด์ผ ํฉ๋๋ค. ์ฝ๋๋ ์ต์ (Python 3.12)์์ ์งฐ์ผ๋, ๊ตฌ๋ฒ์ ์์ ๊นจ์ง ์ ์์ต๋๋ค.
๋จผ์ ๋ฌธ๋ฒ๋ถํฐ ๋ดค์ต๋๋ค. ์ฝ๋๊ฐ 3.8 ์ด์ ์ ์ฉ ๋ฌธ๋ฒ(walrus := ๋ฑ)์ ์ฐ๋ฉด 3.7์์ ์์ ์ปดํ์ผ์ด ์ ๋ฉ๋๋ค.
$ for f in *.py; do python3.7 -m py_compile "$f"; done
# ์ ์ฒด ํต๊ณผ — 3.8+ ๋ฌธ๋ฒ ์ ์
๋ค์์ผ๋ก ์ค์ ํ์ดํ๋ผ์ธ์ ๋๋ค. ํ์ฅ๊ณผ ๊ฐ์ ๊ฒฝ๋ก(API์์ ๋ฐ์ดํฐ ์์ง)๋ฅผ ์ฌํํ๋ ค๊ณ , ๋ฐ์ดํฐ๋ฅผ API ํํ๋ก ์๋นํ๋ ๋ชจ์ ์๋ฒ๋ฅผ ๋์ฐ๊ณ , ๋ฒ๋ค์ด ๊ทธ๊ฑธ ํธ์ถํ๊ฒ ํ์ต๋๋ค. ์ฌ๊ธฐ์ ์์ ํจ์ ์ด ์์์ต๋๋ค.
urllib.error.HTTPError: HTTP Error 404: Not Found
์ฐ๊ฒฐ์ ๋๋๋ฐ 404์์ต๋๋ค. ์์ง ๋ชจ๋์ด base_url + "/data/metrics" ๋ก ํธ์ถํ๋๋ฐ, base_url์ API ๊ฒฝ๋ก ์ผ๋ถ(/v1 ๋ฑ)๊ฐ ๋น ์ ธ ์์์ต๋๋ค. ๊ฒฝ๋ก๋ฅผ ๋ง์ถ๋ ํต๊ณผํ์ต๋๋ค.
์์ง ์๋ฃ: 3๊ฐ DB
[mysql] ๋ฑ๊ธ=warning ์ด์=1๊ฑด
[oracle] ๋ฑ๊ธ=warning ์ด์=1๊ฑด
[postgresql] ๋ฑ๊ธ=warning ์ด์=2๊ฑด
๋ฆฌํฌํธ HTML ์ ์ฅ: report.html
์๋ฃ.
๋ฒ๋ค Python์ผ๋ก ์์ง → ์ด์ ํ์ง → ๋ฆฌํฌํธ ์์ฑ๊น์ง ์๋ฌ ์์ด ์์ฃผํ์ต๋๋ค. ๊ตฌ๋ฒ์ ์คํ์์ ์ฑ์ด ์ ์ ๋์ํจ์ ์ค์ฆํ ๊ฒ์ ๋๋ค.

๋ฐ์ดํฐ๋ฅผ API ํํ๋ก ๋ด๋ณด๋ด๋ ๋ชจ์ ์๋ฒ์, ๊ทธ๊ฒ์ ํธ์ถํด ์์ง→ํ์ง→๋ฆฌํฌํธ๊น์ง ๋๋ ๋ฒ๋ค์ ์ฐ๊ฒฐ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ค๋๋ค. ํ์ฅ(์ค์ API)๊ณผ ๊ฐ์ ํธ์ถ ๊ฒฝ๋ก๋ก ๊ฒ์ฆํ๋ค๋ ์ ์ด ํต์ฌ์ ๋๋ค.
7. ๋ชจ๋ธ ์ฌํ์ต: ๋ฒ์ ์ผ๊ฐ๊ด๊ณ
์ด์ ํ์ง์๋ ๋ฏธ๋ฆฌ ํ์ตํ ๋ชจ๋ธ์ด ๋ค์ด๊ฐ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด ๋ชจ๋ธ์ ๋ฒ๋ค์ scikit-learn ๋ฒ์ (0.24.2)์ผ๋ก ํ์ตํด์ผ ๋ก๋๋ฉ๋๋ค. ๊ธฐ์กด ๋ชจ๋ธ์ ์ต์ ๋ฒ์ ์ผ๋ก ํ์ต๋ผ ์์ด ์ ๋ง์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ํ์ต ์ฝ๋๋ ์์ ์ ์ฝ์ด์ผ ํ๊ณ , ์์ ์ฝ๊ธฐ์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๋ฒ์ pandas(2.2+)์์๋ง ๋๋ ์์ง์ด์์ต๋๋ค. ์ฆ:
- ์์ ์ฝ๊ธฐ = ์ ๋ฒ์ pandas ํ์
- ๋ชจ๋ธ ํ์ต = ๊ตฌ๋ฒ์ scikit-learn ํ์
- ๊ทธ๋ฐ๋ฐ ์ ๋ฒ์ pandas์ ๊ตฌ๋ฒ์ scikit-learn์ numpy ์๊ตฌ ๋ฒ์ ์ด ์ถฉ๋ํด ํ ํ๊ฒฝ์ ๊ฐ์ด ๋ชป ๋
"์ฌ๋ฃ๋ฅผ ๋ค๋ฌ๋ ์นผ(์์ ์ฝ๊ธฐ)"์ ์ต์ ๋๋ง(์ pandas)์์๋ง ๋ง๊ณ , "์๋ฆฌ๋ฒ(๊ตฌ scikit-learn)"์ ์๋ ์ฃผ๋ฐฉ์์๋ง ๋ฉ๋๋ค. ๋์ ํ ์ฃผ๋ฐฉ์ ๋ชป ๋ก๋๋ค.

์์ ์ฝ๊ธฐ์ ํ์ํ ์ ๋ฒ์ pandas์ ๋ชจ๋ธ ํ์ต์ ํ์ํ ๊ตฌ๋ฒ์ scikit-learn์ด numpy ์๊ตฌ ๋ฒ์ ๋๋ฌธ์ ํ ํ๊ฒฝ์ ๊ณต์กดํ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ์ผ๊ฐํ์ผ๋ก ๋ณด์ฌ์ค๋๋ค. ๊ทธ๋์ "์ฝ๊ธฐ ๋ฐฉ์๋ง ๋ฐ๊ฟ" ์ฐํํ ๋ฐฐ๊ฒฝ์ด ๋๋ฌ๋ฉ๋๋ค.
ํด๊ฒฐ์, ํ์ตํ ๋๋ง ์์ ์ฝ๊ธฐ ๋ฐฉ์์ ๋ฒ์ ๋ฌด๊ดํ ๋ฐฉ๋ฒ์ผ๋ก ๋ฐ๊ฟ์น๊ธฐ(๋ฐํ์ ๋ชฝํคํจ์น) ํ๋ ๊ฒ์ด์์ต๋๋ค. ์๋ณธ ์ฝ๋๋ ๊ฑด๋๋ฆฌ์ง ์๊ณ , ํ์ต ๋๋ผ์ด๋ฒ์์๋ง ์์ ์ฝ๊ธฐ ํจ์๋ฅผ ๊ต์ฒดํ์ต๋๋ค.
# ์ผํ์ฑ ํ์ต ๋๋ผ์ด๋ฒ (์๋ณธ ์ฝ๋ ๋ฌด์์ )
from python_calamine import get_sheet_data
import collector
def _read_compat(path):
rows = get_sheet_data(path, 0) # ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ง์ ํธ์ถ (pandas ๋ฒ์ ๋ฌด๊ด)
... # DataFrame์ผ๋ก ๋ณํ
collector.ExcelMetricSource._read_series = staticmethod(_read_compat)
import train; train.main() # ๊ฐ์ ๋ฒ์ (scikit-learn 0.24.2)์ผ๋ก ํ์ต
๋ฒ๋ค๊ณผ ๊ฐ์ ๋ฒ์ (Python 3.7 + scikit-learn 0.24.2)์ ๊น ์ปจํ ์ด๋์์ ์ด ๋๋ผ์ด๋ฒ๋ก ํ์ตํด, ๋ชจ๋ธ ์ธ ๊ฐ๋ฅผ ์๋ก ๋ง๋ค์์ต๋๋ค. ์ด์ ๋ฒ๋ค์ scikit-learn์ผ๋ก ๊ทธ๋๋ก ๋ก๋๋ฉ๋๋ค.
8. ๋ง์ง๋ง ํ ๊ฑธ์: ํ๊ธ ํฐํธ
ML๊น์ง ์ผ๊ณ ๋ค์ ๋๋ฆฌ๋ ๊ทธ๋ํ ์ธ ๊ฐ๊ฐ ๋์๋๋ฐ, ๊ฒฝ๊ณ ๊ฐ ๋ด์ต๋๋ค.
RuntimeWarning: Glyph 54588 missing from current font.
๊ทธ๋ํ์ ํ๊ธ์ด โก๋ก ๋์ค๋ ๋ฌธ์ ์
๋๋ค. ํ์๋ง ์๋ฒ์๋ ํ๊ธ ํฐํธ๊ฐ ์์ด์์
๋๋ค. ํ์ ๊ฐ์ผ๋ฉด apt install fonts-nanum์ผ๋ก ๊น๊ฒ ์ง๋ง, ํ์๋ง์ด๋ผ ์ค์น ๋์ ๋ฒ๋ค์ ํฐํธ๋ฅผ ๋๋ดํด์ผ ํฉ๋๋ค.
๋คํํ ๋ฆฌํฌํธ ์ฝ๋๊ฐ ํฐํธ๋ฅผ ์๋ ์ ํํ ๋ ํ๋ณด ๋ชฉ๋ก์์ "NanumGothic"์ ์ฐพ๋๋ก ๋ผ ์์์ต๋๋ค. ๊ทธ๋์ NanumGothic.ttf๋ฅผ ๋ฒ๋ค์ matplotlib ํฐํธ ํด๋์ ๋ฃ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ฝ๋ ์์ ์ ํ์ ์์์ต๋๋ค.
# ๋ฒ๋ค์ matplotlib ํฐํธ ํด๋์ ํ๊ธ ํฐํธ ๋๋ด
cp NanumGothic.ttf $B/python/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
๋ค์ ๊ฒ์ฆํ๋ ํฐํธ ์ธ์ True, "Glyph missing" ๊ฒฝ๊ณ 0, ๊ทธ๋ํ ์ธ ๊ฐ๊ฐ ํ๊ธ๊น์ง ์ ์์ผ๋ก ๋์์ต๋๋ค.
9. ๊ฒฐ๊ณผ
์ต์ข
์ฐ์ถ๋ฌผ์ ์ฝ 124MB์ tar.gz ํ ๊ฐ์
๋๋ค. RHEL 6.5์์ ์ธํฐ๋ท·์์คํ
ํ์ด์ฌ ์์ด ํ์ด์ ์คํํ๋ฉด, ์์ง๋ถํฐ ํ๊ธ ๊ทธ๋ํ๊ฐ ํฌํจ๋ ๋ฆฌํฌํธ ์์ฑ๊น์ง ๋์ํฉ๋๋ค.
์ ๋ฆฌํ๋ฉด, ์ด๋ฒ ์์ ์ "๋ฐ์์ง๋ค"์์ ์์ํด ๋ค์ ์์๋ก ํ์ ์ ์์๊ฐ ๊ณผ์ ์ด์์ต๋๋ค.
- RHEL 6.5 ํธํ wheel์ด ์กด์ฌํ๋๊ฐ →
pip download๋ก ํ์ธ - ๊ทธ ์์์ import ๋๋๊ฐ →
--no-index์ค์น·import๋ก ํ์ธ - ๋ฒ๋ค์ด ์๊ธ์์กฑ์ธ๊ฐ → ์๋ณธ ๊ฒฝ๋ก๋ฅผ ๋ค ์น์ด ์ํ์์ ํ์ธ
- ์ฑ์ด ๋๊น์ง ๋๋๊ฐ → ๋ชจ์ API๋ก e2e ํ์ธ
- ๋ชจ๋ธ·๊ทธ๋ํ ํ๊ธ๊น์ง → ์ฌํ์ต·ํฐํธ ๋๋ด์ผ๋ก ํ์ธ
๊ฐ ๋จ๊ณ์์ "๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ๊ฒ"๊ณผ "์ง์ง ๋๋ ๊ฒ"์ ๊ตฌ๋ถํ๋ ๊ฒ ํต์ฌ์ด์์ต๋๋ค(์ฌ๋ณผ๋ฆญ ๋งํฌ ๊ฑฐ์ง ํต๊ณผ๊ฐ ๋ํ์ ์ ๋๋ค).
๋ถ๋ก: ํธ๋ฌ๋ธ์ํ ์์ฝ
| ์ฆ์ | ์์ธ | ํด๊ฒฐ |
|---|---|---|
| ๋ฒ๋ค์ด 196KB๋ก ๋์ด | /opt/python์ด ์ฌ๋ณผ๋ฆญ ๋งํฌ |
์ง์ง Python(/opt/_internal/...) ๋ณต์ฌ |
| ์ฌ๋ฐฐ์น ๊ฒ์ฆ์ด ํต๊ณผํ๋๋ฐ ๋ฏธ์ฌ์ฉ์ | ์๋ณธ์ด ๊ฐ์ ์ปจํ ์ด๋์ ๋จ์ ๊ฑฐ์ง ํต๊ณผ | ์๋ณธ ๊ฒฝ๋ก๋ฅผ ์น์ด ์ํ์์ ์ฌ๊ฒ์ฆ |
์คํ ์ .so ๋ชป ์ฐพ์ ์ํ |
RHEL 6.5์ ์๋ libcrypt·libsqlite3 ์์กด | ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋๋ด + LD_LIBRARY_PATH |
centos:6 ์ปจํ
์ด๋ ์ธ๊ทธํดํธ(139) |
์ต์ ์ปค๋ vsyscall ๋นํธํ | manylinux2010์์ ๊ฒฝ๋ก ์จ๊ฒจ RHEL 6.5 ์ฌํ |
| ๋ชจ์ API ํธ์ถ 404 | base_url์ API ๊ฒฝ๋ก ์ผ๋ถ ๋๋ฝ |
๊ฒฝ๋ก๋ฅผ ๋ง์ถฐ ํธ์ถ |
| ๋ชจ๋ธ ๋ก๋ ๋ฒ์ ๋ถ์ผ์น | ์ pandas์ ๊ตฌ scikit-learn ๊ณต์กด ๋ถ๊ฐ | ์์ ์ฝ๊ธฐ๋ง ๋ฐํ์ ๊ต์ฒดํด ๊ฐ์ ๋ฒ์ ์ผ๋ก ํ์ต |
| ๊ทธ๋ํ ํ๊ธ์ด โก | ์๋ฒ์ ํ๊ธ ํฐํธ ์์ | NanumGothic.ttf๋ฅผ ๋ฒ๋ค์ ๋๋ด |