python - Como resolver 'OSError: libc not found' gerado no exec Gunicorn do aplicativo Flask dentro do contêiner Alpine docker




sockets (4)

Estou trabalhando em um aplicativo Flask baseado no aplicativo Microblog do mega-tutorial de Miguel Grinberg. O código mora aqui: https://github.com/dnilasor/quickgig . Eu tenho uma implementação de docker de trabalho com um contêiner MySQL 5.7 vinculado. Hoje eu adicionei uma função Admin View usando o módulo Flask-Admin. Ele funciona lindamente servido localmente (OSX) no servidor Flask via 'flask run', mas quando eu construo e executo a nova imagem do docker (baseada em python: 3.8-alpine), ela trava na inicialização com um OSError: libc not found , código para o qual parece indicar uma biblioteca desconhecida

Parece-me que o Gunicorn não pode servir o aplicativo após minhas adições. Meu colega e eu estamos perplexos!

Originalmente, recebi o erro usando a imagem base python: 3.6-alpine e tentei com 3.7 e 3.8 sem sucesso. Também notei que estava adicionando redundantemente o PyMySQL, uma vez no requirements.txt, especificando a versão no. e novamente explicitamente no arquivo docker sem especificação. Removida a entrada requirements.txt. Também tentei incrementar a versão do Flask-Admin no. para cima e para baixo. Também tentei limpar minhas migrações de banco de dados, pois vi vários arquivos de migração causando falha na inicialização do contêiner (é certo que isso ocorreu ao usar o SQLite). Agora, existe apenas um único arquivo de migração e, com base no rastreamento da pilha, parece que a flask db upgrade do flask db upgrade funciona perfeitamente.

Uma coisa que ainda tenho que tentar é uma imagem base diferente (menos mínima?), Pode tentar em breve e atualizar isso. Mas a questão é tão misteriosa para mim que achei que era hora de perguntar se mais alguém a viu:)

Eu encontrei esse bug de soquete que parecia potencialmente relevante, mas deveria ser totalmente corrigido no python 3.8.

Também para sua informação, segui alguns conselhos here sobre importações circulares e importei minha função de controlador administrativo dentro de 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

Implementação em 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 executo o contêiner no terminal interativo, vejo o seguinte rastreamento de pilha:

(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

Eu gostaria que o aplicativo inicializasse / fosse atendido pelo gunicorn dentro do contêiner, para que eu pudesse continuar desenvolvendo com minha equipe usando a implementação do docker e aproveitando o MySQL dockerized versus a dor do MySQL local para desenvolvimento. Você pode aconselhar?


Esse é um problema do gunicorn 20.0.0 que está sendo rastreado aqui: https://github.com/benoitc/gunicorn/issues/2160

Até que esse problema seja corrigido e lançado, você pode simplesmente adicionar a seguinte linha:

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

Infelizmente, isso adiciona cerca de 20 MB ao contêiner do docker resultante, mas não há nenhuma outra solução conhecida no momento.


Esse problema parece relacionado a uma nova versão do Gunicorn 20.0.0. Tente usar um anterior 19.9.0


No seu Dockerfile:

RUN apk add binutils libc-dev

Sim O Gunicorn 20.0.0 requer o pacote libc-dev .

Então, isso funciona para mim:

RUN apk --no-cache add libc-dev




gunicorn