Reputation: 1657
I am very new to docker, so I would appreciate any guidelines or best practice suggestions. So, this is the problem I am facing. I am building an image with the below Dockerfile config.
FROM python:3.7.9-slim
RUN apt update && apt-get install -y nginx nano
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
EXPOSE 8000
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["gunicorn", "mainapp.wsgi", "-b 0.0.0.0:8000"]
I was experimenting with different official Python images. However I am astonished to see that after running the build a few number of times, the image size shoots up from around 100 mb to 400 mb. The problem is, now even if I go back to the previous Python images, the image sizes simply don't go down. Please see the output from 'docker images'.
So I am trying to go back to the 3.7.9-slim-stretch image which was around 96 mbs. The dates in the output are shown wrong for some reason. My current image which are based on slim and slim-stretch are the top 2 in the output.
Is there something obvious I am missing here? Are there any best practices to avoid this?
Edits: below is the content of the requirements.txt file:
asgiref==3.2.10
certifi==2020.6.20
cffi==1.14.0
chardet==3.0.4
cryptography==2.9.2
defusedxml==0.6.0
Django==3.0.8
django-cors-headers==3.4.0
django-rest-auth==0.9.5
djangorestframework==3.11.0
gunicorn==20.0.4
idna==2.10
joblib==0.16.0
numpy==1.19.1
oauthlib==3.1.0
pandas==1.0.5
Pillow==7.2.0
psycopg2-binary==2.8.5
pycparser==2.20
python-dateutil==2.8.1
python3-openid==3.2.0
pytz==2020.1
requests==2.24.0
requests-oauthlib==1.3.0
scikit-learn==0.23.1
scipy==1.5.2
six==1.15.0
sklearn==0.0
sqlparse==0.3.1
threadpoolctl==2.1.0
urllib3==1.25.9
Also I performed a docker history which shows the below output:
The size of my app folder other wise is 3.5 mbs.
Upvotes: 0
Views: 395
Reputation: 5063
The final size of the image is a sum of sizes of all its layers, so as @Zeiyounator stated in his comment to your question, your final size seems about right. There are a few things you can do to make it smaller though.
First remove or disable if possible any unnecessary caches created during package installation.
Second, if you COPY a file and then RUN chmod to change its permissions you create two layers with exactly the same size (you can see that in your docker history
output). In your case that only wastes 305 B of space, but in general it's a good practice to avoid that by using a multistage build and doing all permission changes in a separate stage.
With all that said, I would rewrite your Dockerfile
as:
FROM python:3.7.9-slim AS init
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM python:3.7.9-slim
RUN apt-get update && apt-get -y install nginx nano && apt-get -y clean && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
COPY --from=init /entrypoint.sh /entrypoint.sh
EXPOSE 8000
ENTRYPOINT ["/entrypoint.sh"]
CMD ["gunicorn", "mainapp.wsgi", "-b 0.0.0.0:8000"]
Upvotes: 1