Come risolvere "OSError: libc not found" sollevato su Gunicorn exec dell'app Flask all'interno del container docker Alpine


13

Sto lavorando a un'applicazione Flask basata sull'app Microblog del mega-tutorial di Miguel Grinberg. Il codice vive qui: https://github.com/dnilasor/quickgig . Ho un'implementazione docker funzionante con un contenitore MySQL 5.7 collegato. Oggi ho aggiunto una funzione Admin View usando il modulo Flask-Admin. Funziona magnificamente servito localmente (OSX) sul server Flask tramite 'flask run' ma quando creo ed eseguo la nuova immagine docker (basata su python: 3.8-alpine), si blocca all'avvio con un OSError: libc not founderrore, il cui codice sembra indicare una libreria sconosciuta

Mi sembra che Gunicorn non sia in grado di servire l'app dopo le mie aggiunte. Io e il mio compagno di classe siamo perplessi!

Inizialmente ho ricevuto l'errore usando l'immagine di base di Python: 3.6-alpine e quindi ho provato con 3.7 e 3.8 senza risultati. Ho anche notato che stavo aggiungendo in modo ridondante PyMySQL, una volta nei requisiti.txt specificando la versione n. e ancora esplicitamente nel file docker senza specifiche. Rimossa la voce requisito.txt. Ho anche provato ad incrementare la versione Flask-Admin n. su e giù. Ho anche provato a ripulire le migrazioni del mio database poiché ho visto più file di migrazione che non riuscivano ad avviare il contenitore (è vero che quando si utilizzava SQLite). Ora c'è solo un singolo file di migrazione e in base alla traccia dello stack sembra ilflask db upgrade bene.

Una cosa che devo ancora provare è un'immagine di base diversa (meno minima?), Posso provare presto e aggiornarla. Ma il problema è così misterioso per me che ho pensato che fosse tempo di chiedere se qualcun altro lo avesse visto:)

Ho trovato questo bug socket che sembrava potenzialmente rilevante, ma doveva essere completamente risolto in Python 3.8.

Inoltre, ho seguito alcuni dei consigli qui sulle importazioni circolari e ho importato la mia funzione di controller di amministrazione all'interno 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

Implementazione in 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

Quando eseguo il contenitore nel terminale interattivo vedo la seguente traccia dello stack:

(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

Vorrei che l'app venisse avviata / gestita da Gunicorn all'interno del contenitore in modo da poter continuare a sviluppare con il mio team utilizzando l'implementazione della docker e sfruttando MySQL dockerizzato rispetto al dolore di MySQL locale per lo sviluppo. Puoi avvisare?

Risposte:


7

Nel tuo Dockerfile:

RUN apk add binutils libc-dev

Questo sembra funzionare. Sfortunatamente, aumenta notevolmente la dimensione dell'immagine.
dcart1234

1
Grazie! Ho modificato per includere solo binutils e libc-dev, rendendo l'immagine più piccola. Non so che cosa abbia bisogno di binutils, ma sembra essere fondamentale.
Clay Hardin,

3

Gunicorn 20.0.0 richiede il pacchetto libc-dev .

Quindi questo funziona per me:

RUN apk --no-cache add libc-dev

Volevo che funzionasse e l'ho provato prima (odio il downgrade / specificare le versioni esplicite) ma non ha funzionato: (
Dnilasor,

apk add libc-devnon ha funzionato neanche per me.
Devy,

3

Si è verificato un problema con gunicorn 20.0.0, monitorato qui: https://github.com/benoitc/gunicorn/issues/2160

Il problema è stato risolto in 20.0.1 e successivi. Quindi, cambia questo:

RUN venv/bin/pip install gunicorn pymysql

a questo:

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

Se l'aggiornamento non è un'opzione, come soluzione alternativa è possibile aggiungere la seguente riga:

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

Sfortunatamente questo aggiunge circa 20 MB al container docker risultante, ma al momento non ci sono altre soluzioni alternative conosciute.


2

Questo problema sembra correlato a una nuova versione di Gunicorn 20.0.0. Prova a utilizzare una precedente 19.9.0


1
python3 ctypes.util.find_library ('c') non funziona correttamente in python: alpine
Dmitrii Dmitriev

Sì, python3 -c "from ctypes.util import find_library; print(find_library('c'))"ritornaNone
Devy,

0

Ho risolto questo problema:

  1. Dockerfile: rimuovere questa installazione "RUN venv / bin / pip install gunicorn"
  2. requisito.txt: aggiungere questa riga "gunicorn == 19.7.1"

Sì. usato 19.9.0 ma,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.