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
erro, cujo código parece indica 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 acontecia ao usar SQLite). Agora, existe apenas um único arquivo de migração e, com base no rastreamento da pilha, parece que flask db upgrade
funciona bem.
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 aqui sobre importações circulares e importei minha função de controlador administrativo para dentro 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?