DEV Community

Discussion on: docker learn #06: Hello Python in Alpine

Collapse
 
elsahib20 profile image
Osman Elsahib

Hi,
I'm trying to run a flask application on a python 3.7 alpine image, My application uses bcrypt and it's in the requirements.txt. when ever I try to build the image it fails with an error (Package libffi was not found in the pkg-config search path). Any Ideas or suggessions are very much appreciated.

Collapse
 
autoferrit profile image
Shawn McElroy

the alpine images arent built with the same c compiler/extensions. So a lot of that stuff doesnt work by default. That is why a lot of people use the "slim" builds like python:3.8-slim-buster. you may be able to do apk add libffi but i don't remember off hand. Also, other python libraries that use any native C extensions, like psycopg2 for postgres, wont work on alpine because there is no .whl (wheel) packages for them. So you would have to compile those on your own. theres ways around some of if but you would have to research that.

Honestly, if you're just learning docker or just want it to work, use the slim versions instead. As you learn more or you decide you want to optimize, you can look into using alpine more. The difference in speed for them start up for 99% of people is negligible.

Collapse
 
elsahib20 profile image
Osman Elsahib

Shawn, thanks for your reply.
I managed to get it working using the following in the Dockerfile:
RUN apk update
RUN apk add libffi-dev
RUN apk add mysql-client
RUN apk add gawk
It was a good learning experience, though.

Thread Thread
 
autoferrit profile image
Shawn McElroy

Awesome! Glad you got it. One thing to keep in mind, is that each RUN command will result in another docker layer that can be cached. So its good to string them together like so:

RUN apk update \
    apk add libffi-dev \
    apk add mysql-client \
    apk add gawk

That way, that one layer can be cached for future builds. This can also effect image sizes. running api update and so on will download other metadata and those will stay on the image. Anything added in a layer will take up space in all future layers, unless its also removed in that same layer. So when using apk (or other package managers) in docker you want to clean up afterwards. Here is how I would re-write the above to do that

RUN apk add --no-cache --virtual .build-deps \
    # requirements you usually don't need to keep around but need to build libs
    gcc libc-dev make \
    # requirements you need to make your app run
    libffi-dev mysql-client gawk \
    # example installing anything that needs those build requirements
    && pip install --no-cache-dir uvicorn gunicorn \ 
    # this will remove the deps no longer needed, as well as clean up anything else
    && apk del .build-deps gcc libc-dev make

And all that will be cached in 1 layer, and those temporary deps installed by apk won't take up any space. this is the image I took this from
github.com/tiangolo/uvicorn-gunico...