title: How to address 'OSError: libc not found' raised on Gunicorn exec of Flask app inside Alpine docker container
body: <p>I'm working on a Flask application based on the Microblog app from Miguel Grinberg's mega-tutorial. Code lives here: <a href="https://github.com/dnilasor/quickgig" rel="noreferrer">https://github.com/dnilasor/quickgig</a> . I have a working docker implementation with a linked MySQL 5.7 container. Today I added an Admin View function using the Flask-Admin module. It works beautifully served locally (OSX) on Flask server via 'flask run' but when I build and run the new docker image (based on python:3.8-alpine), it crashes on boot with a <code>OSError: libc not found</code> error, the code for which seems to indicate <a href="https://github.com/benoitc/gunicorn/blob/438371ee90b9676336a44c7abaeb30ee7fc57a5c/gunicorn/socketfromfd.py#L26" rel="noreferrer">an unknown library</a></p>
  
  <p>It looks to me like Gunicorn is unable to serve the app following my additions. My classmate and I are stumped!</p>
  
  <p>I originally got the error using the python:3.6-alpine base image and so tried with 3.7 and 3.8 to no avail. I also noticed that I was redundantly adding PyMySQL, once in requirements.txt specifying version no. and again explicitly in the dockerfile with no spec. Removed the requirements.txt entry. Also tried incrementing the Flask-Admin version no. up and down. Also tried cleaning up my database migrations as I have seen multiple migration files causing the container to fail to boot (admittedly this was when using SQLite). Now there is only a single migration file and based on the stack trace it seems like the <code>flask db upgrade</code> works just fine.</p>
  
  <p>One thing I have yet to try is a different base image (less minimal?), can try soon and update this. But the issue is so mysterious to me that I thought it time to ask if anyone else has seen it : )</p>
  
  <p>I did find <a href="https://bugs.python.org/issue28134" rel="noreferrer">this socket bug</a> which seemed potentially relevant but it was supposed to be fully fixed in python 3.8.</p>
  
  <p>Also FYI I followed some of the advice <a href="https://github.com/miguelgrinberg/microblog/issues/49" rel="noreferrer">here</a> on circular imports and imported my admin controller function inside <code>create_app</code>.</p>
  
  <p>Dockerfile:</p>
  
  <pre><code>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"]
  
  </code></pre>
  
  <p>boot.sh:</p>
  
  <pre><code>#!/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
  </code></pre>
  
  <p>Implementation in <strong>init</strong>.py:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>admin.py:</p>
  
  <pre><code>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))
  </code></pre>
  
  <p>requirements.txt:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>When I run the container in interactive terminal I see the following stack trace:</p>
  
  <pre><code>(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  -&gt; 1f5feeca29ac, test
  Traceback (most recent call last):
    File "/home/quickgig/venv/bin/gunicorn", line 6, in &lt;module&gt;
      from gunicorn.app.wsgiapp import run
    File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 9, in &lt;module&gt;
      from gunicorn.app.base import Application
    File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/app/base.py", line 12, in &lt;module&gt;
      from gunicorn.arbiter import Arbiter
    File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/arbiter.py", line 16, in &lt;module&gt;
      from gunicorn import sock, systemd, util
    File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/sock.py", line 14, in &lt;module&gt;
      from gunicorn.socketfromfd import fromfd
    File "/home/quickgig/venv/lib/python3.8/site-packages/gunicorn/socketfromfd.py", line 26, in &lt;module&gt;
      raise OSError('libc not found')
  OSError: libc not found
  </code></pre>
  
  <p>I'd like the app to boot/be served by gunicorn inside the container so I can continue developing with my team using the docker implementation and leveraging dockerized MySQL vs the pain of local MySQL for development. Can you advise?</p>