Unable to containerize python-tkinter based project on alpine3.15 - python-3.x

This is the link to my project HERE
I am trying to containerize this and i have written a dockerfile for this which below,
FROM python:3-alpine3.15
WORKDIR /app
COPY . /app
RUN apk update
RUN apk add python3
RUN apk add python3-tkinter
#RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 3000
CMD python3 ./sortingAlgs.py
It doesn't run since "tkinter-tclerror-no-display-name-and-no-display-environment-variable" (the error in docker desktop terminal)
After a lot of struggle I found "matplotlib" module can help and i tried including
import matplotlib
matplotlib.use('Agg')
at the starting of my source-code file ("sortingAlgs.py")
but no luck..
I am unable to make use of "requirements.txt" since i am new to docker.. and i am getting errors like (module not found) when it comes at "pip install -r requirements.txt" and fails.
and i only have experience on debian linux (ubuntu). hencce, working with alpine is a problem as well..
i want to host this application as an containerized application and push it on docker hub

Related

Python "exec /usr/local/bin/python3: exec format error" on Docker while using Apple M1 Max

My docker images were working fine as soon as I moved to my new Mac M1 Max. Even with my M1 Max, I have installed docker and successfully created image, and pushed to AWS ECR. Now when I'm running that image, it doesn't run but throws an error
exec /usr/local/bin/python3: exec format error
My Dockerfile looks like below but no luck yet. The same error everytime. I know that it's not straight forward to built docker images on Mac M1 Max and run them but in many StackOverflow answers I found that the below addition --platform=linux/arm64 helps but not in my case yet.
FROM --platform=linux/amd64 python:3.8-slim-buster
# FROM --platform=linux/arm64 python:3.8-slim-buster (tried this one as well)
# FROM --platform=linux/arm64/v8 python:3.8-slim-buster (tried this one as well)
WORKDIR /project
COPY ./requirements.txt .
RUN apt-get -qq update
RUN pip3 --quiet install --requirement requirements.txt \
--force-reinstall --upgrade
COPY . .
I got it working by just adding as build.
So the first line will look like
FROM --platform=linux/amd64 python:3.8-slim-buster as build
I'm not exactly sure what's the difference between the above line and the one I was using earlier but some as build is mentioned in the docker docs. Now it works fine

Docker run exits when running an amd64/python image

I am very elementary at Docker and I know a few commands to test my tasks. I have built a Docker image for 64-bit python because I had to install CatBoost in it. My dockerfile looks like this:
FROM amd64/python:3.9-buster
RUN apt update
RUN apt install -y libgl1-mesa-glx apt-utils
RUN pip install -U pip
RUN pip install --upgrade setuptools
# We copy just the requirements.txt first to leverage Docker cache
COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip --default-timeout=100 install -r requirements.txt
COPY . /app
EXPOSE 5000
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]
I built the image with docker build -t myimage ., it gets built for a long time presumably successfully. When I run the image using the following command: docker run -p 5000:5000 myimage, it gives a warning WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested and downloads some things for while and then exits. Not sure whats happening. How do I tackle this?
I managed to solve it by running the same thing on a linux machine.

Dockerfile support multiple from

I have a need to run python on different CPU architectures such as AMD64 and ARM (Raspberry Pi) etc. I read the documentation from Docker that Multi Stage Build is probably the way to go.
FROM python:3.10-slim
LABEL MAINTAINER=XXX
ADD speedtest-influxdb.py /speedtest/speedtest-influxdb.py
ENV INFLUXDB_SERVER="http://10.88.88.10:49161"
RUN apt-get -y update
RUN python3 -m pip install 'influxdb-client[ciso]'
RUN python3 -m pip install speedtest-cli
CMD python3 /speedtest/speedtest-influxdb.py
FROM arm32v7/python:3.10-slim
LABEL MAINTAINER=XXX
ADD speedtest-influxdb.py /speedtest/speedtest-influxdb.py
ENV INFLUXDB_SERVER="http://10.88.88.10:49161"
RUN apt-get -y update
RUN python3 -m pip install 'influxdb-client[ciso]'
RUN python3 -m pip install speedtest-cli
CMD python3 /speedtest/speedtest-influxdb.py
But as you can see there's a bit to repetition. Is there a better way?
A typical use of a multi-stage build is to build some artifact you want to run or deploy, then COPY it into a final image that doesn't include the build tools. It's not usually the right tool when you want to build several separate things, or several variations on the same thing.
In your case, all of the images are identical except for the FROM line. You can use an ARG to specify the image you're building FROM (in this specific case ARG comes before FROM)
ARG base_image=python:3.10-slim
FROM ${base_image}
...
CMD ["/speedtest/speedtest.py"]
# but only once
If you just docker build this image, you'll get the default base_image, which will use a default Python for the current default architecture. But you can request a different base image, or a different target platform
# Use the ARM32-specific image
docker build --build-arg base_image=arm32v7/python:3.10-slim .
# Force an x86 image (with emulation if supported)
docker build --platform linux/amd64 .

Unable to build docker image for python code

I have created a docker file with the following:
FROM python:3.9.2
MAINTAINER KSMC
RUN apt-get update -y && apt-get install -y python3-pip python-dev
WORKDIR /Users/rba/Documents/Projects/DD/DD-N4
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["main.py"]
My python code is in main.py , my python version is 3.9.2 and all my python code, requirements.txt and docker file are in the location /Users/rba/Documents/Projects/DD/DD-N4. Upon trying to create docker image using:
docker build -t ddn4image .
I am getting the following error:
#8 1.547 ERROR: Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt'
------ executor failed running [/bin/sh -c pip3 install -r requirements.txt]: exit code: 1
Can someone point out what is causing this?
You forgot to do a COPY statement.
Before you run RUN pip3 install -r requirements.txt, just put the following line
COPY . .
You need to do this because your local files need to be copied into the docker image build, so when your container is created, the files will exists on it.
Read the docs about COPY at docker docs.
Hint
Remove the ENTRYPOINT statement and use
CMD ["python3", "main.py"]
Here it is a good explanation about ENTRYPOINT and CMD difference.

AWS Mythical Mysfits - Nomodule named flask - ImportError

I am very new to aws and especially docker
so I have been following this link to understand stuff about developing a web application -
https://aws.amazon.com/getting-started/hands-on/build-modern-app-fargate-lambda-dynamodb-python/module-two/
I am stuck at the point where it asks us to test the service locally using a 'docker run' command(in module - 2)
when I run the command I am getting an 'ImportError'.
Here are my code-snippets ....please help me out !
mythicalMysfitsService.py -
from flask import Flask, jsonify, json, Response, request
from flask_cors import CORS
# A very basic API created using Flask that has two possible routes for requests.
app = application = Flask(__name__)
CORS(application)
# The service basepath has a short response just to ensure that healthchecks
# sent to the service root will receive a healthy response.
#app.route("/")
def healthCheckResponse():
return jsonify({"message" : "Nothing here, used for health check. Try /mysfits instead."})
# The main API resource that the next version of the Mythical Mysfits website
# will utilize. It returns the data for all of the Mysfits to be displayed on
# the website. Because we do not yet have any persistent storage available for
# our application, the mysfits are simply stored in a static JSON file. Which is
# read from the the filesystem, and directly used as the service response.
#app.route("/mysfits")
def getMysfits():
# read the mysfits JSON from the listed file.
response = Response(open("mysfits-response.json").read())
# set the Content-Type header so that the browser is aware that the response
# is formatted as JSON and our frontend JavaScript code is able to
# appropriately parse the response.
response.headers["Content-Type"]= "application/json"
return response
# Run the service on the local server it has been deployed to,
# listening on port 8080.
if __name__ == "__main__":
application.run(host="0.0.0.0", port=8080)
Dockerfile -
FROM ubuntu:latest
RUN echo Updating existing packages, installing and upgrading python and pip.
RUN apt-get update -y
RUN apt-get install -y python3-pip python-dev build-essential
RUN pip3 install --upgrade pip
RUN echo Copying the Mythical Mysfits Flask service into a service directory.
COPY ./service /MythicalMysfitsService
WORKDIR /MythicalMysfitsService
RUN echo Installing Python packages listed in requirements.txt
RUN pip3 install -r ./requirements.txt
RUN echo Starting python and starting the Flask service...
ENTRYPOINT ["python"]
CMD ["mythicalMysfitsService.py"]
docker build -
ec2-user:~/environment/aws-modern-application-workshop/module-2/app (python) $ docker build . -t 054166015944.dkr.ecr.us-east-2.amazonaws.com/mythicalmysfits/service:latest
OUTPUT -
Sending build context to Docker daemon 14.85kB
Step 1/14 : FROM ubuntu:latest
---> 1d622ef86b13
Step 2/14 : RUN echo Updating existing packages, installing and upgrading python and pip.
---> Using cache
---> 7cdaa818c9c2
Step 3/14 : RUN apt-get update -y
---> Using cache
---> a1fd46891d1e
Step 4/14 : RUN apt-get install -y python3-pip python-dev build-essential
---> Using cache
---> f81dc75dfc3f
Step 5/14 : RUN pip3 install --upgrade pip
---> Using cache
---> 0cee88c88f43
Step 6/14 : RUN echo Copying the Mythical Mysfits Flask service into a service directory.
---> Using cache
---> 709b50aac794
Step 7/14 : COPY ./service /MythicalMysfitsService
---> Using cache
---> f70454638e83
Step 8/14 : WORKDIR /MythicalMysfitsService
---> Using cache
---> 418a08d8ac32
Step 9/14 : RUN echo Installing Python packages listed in requirements.txt
---> Using cache
---> 03659d0cb00e
Step 10/14 : RUN pip3 install -r ./requirements.txt
---> Using cache
---> cb65480b6104
Step 11/14 : RUN echo Starting python and starting the Flask service...
---> Using cache
---> 89738a63f437
Step 12/14 : ENTRYPOINT ["python"]
---> Using cache
---> 97b4f200a571
Step 13/14 : CMD ["mythicalMysfitsService.py"]
---> Using cache
---> a22fe5fb5bdb
Step 14/14 : RUN unset -v PYTHONPATH
---> Using cache
---> f43930d6410a
Successfully built f43930d6410a
Successfully tagged 054166015944.dkr.ecr.us-east-2.amazonaws.com/mythicalmysfits/service:latest
docker run to test service locally -
$ docker run -p 8080:8080 054166015944.dkr.ecr.us-east-2.amazonaws.com/mythicalmysfits/service:latest
error -
Traceback (most recent call last):
File "mythicalMysfitsService.py", line 1, in <module>
from flask import Flask, jsonify, json, Response, request
ImportError: No module named flask
checked for flask using flask --version
OUTPUT -
Flask 1.0.4
Werkzeug 1.0.0
So I have 'flask' installed but it still says No module named flask.
Using ubuntu:latest as base image is a bad idea. If you pulled a few months ago, you'd get Ubuntu 18.04. If you pulled today, you'd get Ubuntu 20.04. So it's possible to get inconsistent builds. Better to have a specific release as base image, e.g. ubuntu:20.04. Better yet, use python:3.8-slim-buster as the base image and you'll get latest Python 3.8 pre-installed on Debian, and can easily switch to 3.9 when it's out.
My guess is you installed libraries on Python 3 (pip3 install) but you're running the code with Python 2. Try switching ENTRYPOINT to python3 instead of python.
This article talks more about choosing a good tag for your base image: https://pythonspeed.com/articles/reproducible-docker-builds-python/
I just tried your instruction and was able to get the flask app to run.
I would suggest that you delete the image that was built previously and build again. Delete the image using docker rmi 054166015944.dkr.ecr.us-east-2.amazonaws.com/mythicalmysfits/service:latest.
If you get an error stating that the image is being referenced by a container, you'll have to delete the referenced containers using docker rm <container id> or run docker rmi -f 054166015944.dkr.ecr.us-east-2.amazonaws.com/mythicalmysfits/service:latest to force the delete although referenced.
You may want to try this (It solved the same problem I have):
Update python at 4 places in the Dockerfile
FROM ubuntu:latest
RUN echo Updating existing packages, installing and upgrading python and pip.
RUN apt-get update -y
RUN apt-get install -y python3-pip python-dev build-essential
RUN pip3 install --upgrade pip
RUN echo Copying the Mythical Mysfits Flask service into a service directory.
COPY ./service /MythicalMysfitsService
WORKDIR /MythicalMysfitsService
RUN echo Installing Python packages listed in requirements.txt
RUN pip3 install -r ./requirements.txt
RUN echo Starting python and starting the Flask service...
ENTRYPOINT ["python3"]
CMD ["mythicalMysfitsService.py"]

Resources