Jak rozwiązać problem „OSError: libc not found” podniesiony w Gunicorn exec aplikacji Flask wewnątrz kontenera dokowanego Alpine

13

Pracuję nad aplikacją Flask opartą na aplikacji Microblog z mega poradnika Miguela Grinberga. Kod mieszka tutaj: https://github.com/dnilasor/quickgig . Mam działającą implementację dokera z połączonym kontenerem MySQL 5.7. Dzisiaj dodałem funkcję Admin View za pomocą modułu Flask-Admin. Działa pięknie obsługiwany lokalnie (OSX) na serwerze Flask poprzez „uruchomienie flask”, ale kiedy buduję i uruchamiam nowy obraz dokera (oparty na pythonie: 3.8-alpine), ulega awarii przy rozruchu z OSError: libc not foundbłędem, którego kod wydaje się być wskaż nieznaną bibliotekę

Wydaje mi się, że Gunicorn nie jest w stanie obsłużyć aplikacji po moich dodatkach. Mój kolega z klasy i ja jesteśmy zakłopotani!

Pierwotnie dostałem błąd używając Pythona: 3.6-alpejski obraz podstawowy, więc próbowałem z 3.7 i 3.8, ale bezskutecznie. Zauważyłem również, że nadmiarowo dodawałem PyMySQL, raz w pliku wymagania.txt, podając wersję nr. i ponownie jawnie w pliku dokera bez specyfikacji. Usunięto wpis wymagania.txt. Próbowałem także zwiększyć liczbę wersji Flask-Admin nr. w górę i w dół. Próbowałem też wyczyścić migracje bazy danych, ponieważ widziałem wiele plików migracji, które powodowały błąd uruchamiania kontenera (co prawda miało to miejsce podczas korzystania z SQLite). Teraz jest tylko jeden plik migracji i na podstawie śledzenia stosu wygląda na to, że flask db upgradedziała dobrze.

Jedną rzeczą, którą muszę jeszcze wypróbować, jest inny obraz podstawowy (mniej minimalny?), Można wypróbować wkrótce i zaktualizować to. Ale sprawa jest dla mnie tak tajemnicza, że ​​pomyślałem, że nadszedł czas, aby zapytać, czy ktoś ją widział:)

Znalazłem ten błąd gniazda, który wydawał się potencjalnie istotny, ale miał być w pełni naprawiony w Pythonie 3.8.

Również FYI skorzystałem z niektórych porad tutaj na temat importu cyklicznego i zaimportowałem wewnątrz moją funkcję administratora create_app.

Plik Docker:

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

Implementacja w 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))

wymagania.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

Po uruchomieniu kontenera w terminalu interaktywnym widzę następujący ślad stosu:

(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

Chciałbym, aby aplikacja uruchamiała się / była obsługiwana przez gunicorn w kontenerze, dzięki czemu mogę nadal rozwijać się z moim zespołem, używając implementacji dokera i wykorzystując zadokowany MySQL w porównaniu z bólem lokalnego MySQL do programowania. Możesz doradzić?

Dnilasor
źródło

Odpowiedzi:

7

W twoim pliku Docker:

RUN apk add binutils libc-dev
Clay Hardin
źródło
To wydaje się działać. Niestety, dramatycznie zwiększa rozmiar obrazu.
dcart1234,
1
Dzięki! Zredagowałem, aby uwzględnić binutils i libc-dev, dzięki czemu obraz jest mniejszy. Nie wiem, co potrzebuje binutils, ale wydaje się to kluczowe.
Clay Hardin
3

Tak Gunicorn 20.0.0 wymaga pakietu libc-dev .

Więc to działa dla mnie:

RUN apk --no-cache add libc-dev
Fabrizio Fubelli
źródło
Chciałem, żeby to zadziałało i wypróbowałem to jako pierwsze (nienawidzę obniżania wersji / określania jawnych wersji), ale tak się nie stało: (
Dnilasor,
apk add libc-devteż nie działało dla mnie.
Devy,
3

To był problem z gunicorn 20.0.0, który można śledzić tutaj: https://github.com/benoitc/gunicorn/issues/2160

Problem został rozwiązany w wersji 20.0.1 i nowszych. Więc zmień to:

RUN venv/bin/pip install gunicorn pymysql

do tego:

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

Jeśli aktualizacja nie jest opcją, w celu obejścia tego problemu możesz dodać następujący wiersz:

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

Niestety dodaje to około 20 MB do wynikowego kontenera dokowanego, ale w tej chwili nie ma innego znanego obejścia.

cheeseandcereal
źródło
2

Ten problem wydaje się związany z nową wersją Gunicorn 20.0.0. Spróbuj użyć poprzedniej wersji 19.9.0

Dmitrii Dmitriev
źródło
1
python3 ctypes.util.find_library ('c') nie działa poprawnie w python: alpine
Dmitrii Dmitriev
Tak, python3 -c "from ctypes.util import find_library; print(find_library('c'))"powracaNone
Devy,
0

Rozwiązałem ten problem:

  1. Plik Docker: usuń tę instalację „RUN venv / bin / pip install gunicorn”
  2. wymagany.txt: dodaj ten wiersz „gunicorn == 19.7.1”
Bảo Nguyễn Cao
źródło
tak. używane 19.9.0, ale tak
Dnilasor,