Optimizing docker image
Optimizing Docker image and Docker permissions.

Hi, this is second blog of series where we dockerize django application. Here is link to first part if you want to start from beginning it. In this blog we will be optimizing our docker image size and managing docker permissions.
First we will be looking ways of optimizing the size of our docker image. Reducing our docker image size can help us speed up our build process. One of main reason to avoid bigger docker images is they increase potential security vulnerabilities. Some ways to reduce docker image sizes:
Using minimal base images.
Making multistage builds.
Minimizing number of layers.
Using Dockerignore.
Using minimal base images.
We can find different images to download from dockerhub. Choosing right docker image is important for optimizing size of your image. One of image with minimal footprint is alpine base image. We have been using alpine in this blog. You can further reduce image size by using distroless images.
Making Multistage builds
First lets check size of our image.
Enter command to see size of image we have created :
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
djangowithdocker_web latest dfc89fa29239 41 minutes ago 104MB
Here we can see size of our docker image to be 104MB
Now, lets update our dockerfile.
FROM python:3.10-alpine AS builder
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
RUN pip install --upgrade pip
ENV APP_DIR /home/DockerWithDjango
WORKDIR ${APP_DIR}
ADD requirements.txt ${APP_DIR}/
RUN pip install -r ${APP_DIR}/requirements.txt
COPY . ${APP_DIR}
FROM python:3.10-alpine
WORKDIR /home
COPY --from=builder /usr/local/lib/python3.10/site-packages/ /usr/local/lib/python3.10/site-packages/
COPY --from=builder /usr/local/bin/ /usr/local/bin/
COPY --from=builder /home/DockerWithDjango/ /home/
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Now build image by running following command and check image size again.
docker-compose build
REPOSITORY TAG IMAGE ID CREATED SIZE
djangowithdocker_web latest ed890f647878 2 minutes ago 92.4MB
New size of our image is 92.4MB. It has decreased from 104MB to 92.4MB. Since our project has very few packages installed so size is small and decreased size is also less. When project size increases multi-stage build will decrease lot of size.
Minimizing number of layers
An image is a read-only template with instructions for creating a Docker container. A Docker image is built up from a series of layers. Each step in Dockerfile creates a new layer. Instructions like RUN, COPY, ADD creates new layer and each layer adds build execution time and increases the storage requirements of the image. The other instructions create intermediate layers and do not influence the size of image. So, while creating Dockerfile we need to be careful about number of layers that is being created as it will affect size of our docker image.
Using Dockerignore
Using .dockerignore file can help us remove unwanted files from build. This file works similar to .gitignore file. We list files that we want docker to ignore during building our docker image.
Lets create a new .dockerignore file and list files we want docker to ignore. This file usually may contain logs, cache folders, git, markdown files etc. Here we will add list to ignore for our django application.
```
pycache/
.git
*.sqlite3
env/
*.md
```
Changing user permission
Running docker as root user may lead to broken permissions. Lets add new user group and create a new user. Then we will manage permission of our project to newly created user. ``` FROM python:3.10-alpine AS builder
ENV PYTHONUNBUFFERED=1 ENV PYTHONDONTWRITEBYTECODE=1
RUN addgroup -S -g 1000 django-with-docker && adduser -S -u 1000 django-with-docker -G django-with-docker
RUN pip install --upgrade pip
ENV APP_DIR /home/DockerWithDjango
WORKDIR ${APP_DIR}
ADD requirements.txt ${APP_DIR}/
RUN pip install -r ${APP_DIR}/requirements.txt
COPY . ${APP_DIR}
FROM python:3.10-alpine
WORKDIR /home COPY --from=builder /usr/local/lib/python3.10/site-packages/ /usr/local/lib/python3.10/site-packages/ COPY --from=builder /usr/local/bin/ /usr/local/bin/ COPY --from=builder /home/DockerWithDjango/ /home/
RUN chown -R 1000:1000 /home USER 1000
EXPOSE 8000 ``` In this blog we optimized our Dockerfile size and manage permissions of our django project inside docker.


