Как обратиться к «OSError: libc not found», появившемуся в exec Gunicorn приложения Flask внутри док-контейнера Alpine

13

Я работаю над приложением Flask, основанным на приложении Microblog из мега-учебника Мигеля Гринберга. Код живет здесь: https://github.com/dnilasor/quickgig . У меня есть рабочая реализация докера со связанным контейнером MySQL 5.7. Сегодня я добавил функцию Admin View, используя модуль Flask-Admin. Он прекрасно работает локально (OSX) на сервере Flask через «флеш-запуск», но когда я собираю и запускаю новый образ докера (на основе python: 3.8-alpine), он вылетает при загрузке с OSError: libc not foundошибкой, код для которой кажется указать неизвестную библиотеку

Мне кажется, что Gunicorn не может обслуживать приложение после моих дополнений. Мой одноклассник и я в тупик!

Изначально я получил сообщение об ошибке, используя базовый образ python: 3.6-alpine, поэтому попытался с 3.7 и 3.8 безрезультатно. Я также заметил, что я избыточно добавлял PyMySQL, однажды в файле require.txt, указав номер версии. и снова явно в докер-файле без спецификации. Удалена запись в файл require.txt. Также попытался увеличить версию Flask-Admin. вверх и вниз. Также попытался очистить миграцию моей базы данных, так как я видел несколько файлов миграции, вызывающих сбой загрузки контейнера (правда, это было при использовании SQLite). Теперь существует только один файл миграции, и, основываясь на трассировке стека, кажется, что все flask db upgradeработает отлично.

Одна вещь, которую мне еще предстоит попробовать, - это другой базовый образ (менее минимальный?), Могу попробовать в ближайшее время и обновить его. Но этот вопрос настолько загадочный для меня, что я подумал, что пришло время спросить, видел ли это кто-то еще :)

Я нашел эту ошибку сокета, которая казалась потенциально актуальной, но должна была быть полностью исправлена ​​в python 3.8.

Также, к вашему сведению, я следовал некоторым советам здесь по циклическому импорту и импортировал внутри себя функцию моего администратора create_app.

Dockerfile:

FROM python:3.8-alpine

RUN adduser -D quickgig

WORKDIR /home/quickgig

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/pip install gunicorn pymysql

COPY app app
COPY migrations migrations
COPY quickgig.py config.py boot.sh ./
RUN chmod +x boot.sh

ENV FLASK_APP quickgig.py

RUN chown -R quickgig:quickgig ./
USER quickgig

EXPOSE 5000
ENTRYPOINT ["./boot.sh"]

boot.sh:

#!/bin/sh
source venv/bin/activate
while true; do
    flask db upgrade
    if [[ "$?" == "0" ]]; then
        break
    fi
    echo Upgrade command failed, retrying in 5 secs...
    sleep 5
done
# flask translate compile
exec gunicorn -b :5000 --access-logfile - --error-logfile - quickgig:app

Реализация в init .py:

from flask_admin import Admin
app_admin = Admin(name='Dashboard')

def create_app(config_class=Config):
  app = Flask(__name__)
  app.config.from_object(config_class)
...
  app_admin.init_app(app)

...
  from app.admin import add_admin_views
  add_admin_views()
...
  return app

from app import models

admin.py:

from flask_admin.contrib.sqla import ModelView
from app.models import User, Gig, Neighborhood
from app import db
# Add views to app_admin

def add_admin_views():
    from . import app_admin
    app_admin.add_view(ModelView(User, db.session))
    app_admin.add_view(ModelView(Neighborhood, db.session))
    app_admin.add_view(ModelView(Gig, db.session))

requirements.txt:

alembic==0.9.6
Babel==2.5.1
blinker==1.4
certifi==2017.7.27.1
chardet==3.0.4
click==6.7
dominate==2.3.1
elasticsearch==6.1.1
Flask==1.0.2
Flask-Admin==1.5.4
Flask-Babel==0.11.2
Flask-Bootstrap==3.3.7.1
Flask-Login==0.4.0
Flask-Mail==0.9.1
Flask-Migrate==2.1.1
Flask-Moment==0.5.2
Flask-SQLAlchemy==2.3.2
Flask-WTF==0.14.2
guess-language-spirit==0.5.3
idna==2.6
itsdangerous==0.24
Jinja2==2.10
Mako==1.0.7
MarkupSafe==1.0
PyJWT==1.5.3
python-dateutil==2.6.1
python-dotenv==0.7.1
python-editor==1.0.3
pytz==2017.2
requests==2.18.4
six==1.11.0
SQLAlchemy==1.1.14
urllib3==1.22
visitor==0.1.3
Werkzeug==0.14.1
WTForms==2.1

Когда я запускаю контейнер в интерактивном терминале, я вижу следующую трассировку стека:

(venv) ****s-MacBook-Pro:quickgig ****$ docker run -ti quickgig:v7
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 1f5feeca29ac, test
Traceback (most recent call last):
  File "/home/quickgig/venv/bin/gunicorn", line 6, in <module>
    from gunicorn.app.wsgiapp import run
  File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 9, in <module>
    from gunicorn.app.base import Application
  File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/app/base.py", line 12, in <module>
    from gunicorn.arbiter import Arbiter
  File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 16, in <module>
    from gunicorn import sock, systemd, util
  File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/sock.py", line 14, in <module>
    from gunicorn.socketfromfd import fromfd
  File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/socketfromfd.py", line 26, in <module>
    raise OSError('libc not found')
OSError: libc not found

Мне бы хотелось, чтобы приложение загружалось / обслуживалось gunicorn внутри контейнера, чтобы я мог продолжить разработку с моей командой, используя реализацию докера и используя DoSQL, настроенный на основе Docker, против боли локального MySQL для разработки. Вы можете посоветовать?

Dnilasor
источник

Ответы:

7

В вашем Dockerfile:

RUN apk add binutils libc-dev
Клей Хардин
источник
Это похоже на работу. К сожалению, это резко увеличивает размер изображения.
dcart1234
1
Спасибо! Я отредактировал, чтобы просто включить binutils и libc-dev, чтобы уменьшить изображение. Я не знаю, для чего нужен binutils, но, похоже, это имеет решающее значение.
Клей Хардин
3

Да Gunicorn 20.0.0 требует пакет libc-dev .

Так что это работает для меня:

RUN apk --no-cache add libc-dev
Фабрицио Фубелли
источник
Я хотел, чтобы это сработало, и сначала попробовал (ненавижу понижение версии / указание явных версий), но это не сработало: (
Dnilasor
apk add libc-devу меня тоже не сработало.
Деви
3

Это была проблема с gunicorn 20.0.0, отслеживаемая здесь: https://github.com/benoitc/gunicorn/issues/2160

Проблема исправлена ​​в 20.0.1 и выше. Итак, измени это:

RUN venv/bin/pip install gunicorn pymysql

к этому:

RUN venv/bin/pip install 'gunicorn>=20.0.1,<21' pymysql

Если обновление не вариант, в качестве обходного пути вы можете добавить следующую строку:

RUN apk --no-cache add binutils musl-dev

К сожалению, это добавляет около 20 МБ к получающемуся контейнеру докера, но в настоящее время нет другого известного обходного пути.

cheeseandcereal
источник
2

Эта проблема, похоже, связана с новой версией Gunicorn 20.0.0. Попробуйте использовать предыдущий 19.9.0

Дмитрий Дмитриев
источник
1
python3 ctypes.util.find_library ('c') некорректно работает в python: alpine
Дмитрий Дмитриев
Да, python3 -c "from ctypes.util import find_library; print(find_library('c'))"возвращаетсяNone
Деви
0

Я решил эту проблему:

  1. Dockerfile: удалите эту установку "RUN venv / bin / pip install gunicorn"
  2. require.txt: добавить эту строку "gunicorn == 19.7.1"
Бо Нгуен Цао
источник
Ага. использовал 19.9.0 но да
Дниласор