[Docker] Build multi stage image
Existing Dockerfile
Dockerfile:
FROM python:3
ENV PYBASE /pybase
ENV PYTHONUSERBASE $PYBASE
ENV PATH $PYBASE/bin:$PATH
RUN pip install pipenv
WORKDIR /tmp
COPY Pipfile .
RUN pipenv lock
RUN PIP_USER=1 PIP_IGNORE_INSTALLED=1 pipenv install -d --system --ignore-pipfile
COPY . /app/notes
WORKDIR /app/notes
EXPOSE 80
CMD [ "flask", "run", "--port=80", "--host=0.0.0.0" ]
Build the image:
docker build -t notesapp:default .
Set a variable to view the layers of the image:
export showLayers='{{ range .RootFS.Layers }}{{ println . }}{{end}}'
Set a variable to show the size of the image:
export showSize='{{ .Size }}'
Show the image layers:
docker inspect -f "$showLayers" notesapp:default
sha256:a9099c3159f52e46aeed72420924377873529e3f36a80eddbfeb63860d036a04
sha256:a463dbda46648cc9a3af3f009b2c73035cb068639edb24f1fb5a792b057c6aa8
sha256:49b333f7bad4d30043c926b2e1270833f419ee03da204f91e09bd7939c68032e
sha256:9f4f964da72795eddb83aa809dd2b336cb37b93238a18a2e230b0adec951d1a7
sha256:a4db1a4057634db9daf255df4f001ff04cd7f0018d9b1aac8f56c3cf800f466b
sha256:dc6462f7bb8b1f906aa41ee08e5950c439fe30ba35c5eb05fba8d4a43d24d47e
sha256:52671c2fdc002602e02618d37653da28f4f06cd70d31c99ad56bdef714dbbbd6
sha256:258fef020bc42d77252f3f101b78b008a7835c230806bd45c5882ae64bb2fee2
sha256:b3683446f8e5bfa05977978d9370a115d1bf6ab81e080a8c138a44fb3dcb7730
sha256:79cd603fb06da84f169e4754828379375d8bed42f2fbcc354a67293bc50a9ac5
sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef
sha256:37bf192760afd096a3a2886aef195dec0dd9bb03035b008f2094cc77df6f1529
sha256:2f27fc3d94d973a3dea19e0a49a3067a1b68211bbf6f42f72b47fb2549ce8c41
sha256:4f36d94e66694e9a8d3f43c62b2dca00cd3e5597e4749037a70d2c667fa75eac
sha256:1963e112f11a8b8e657cb93524dbb0491fc35bdbb75bf2720bc861b2eb1681b1
sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef
Let's count how many lines of output layters:
docker inspect -f "$showLayers" notesapp:default | wc -l
Result is 17, but need to reduce 1 empty line, so actual is 16.
Let's see the size:
[cloud_user@ip-10-0-1-179 notes]$ docker inspect -f "$showSize" notesapp:default | numfmt --to=iec
1013M
Add a multi build stage
vim Dockerfile
- FROM python:3
+ FROM python:3 AS base
ENV PYBASE /pybase
ENV PYTHONUSERBASE $PYBASE
ENV PATH $PYBASE/bin:$PATH
+ FROM baase AS builder
RUN pip install pipenv
WORKDIR /tmp
COPY Pipfile .
RUN pipenv lock
RUN PIP_USER=1 PIP_IGNORE_INSTALLED=1 pipenv install -d --system --ignore-pipfile
+ From base
+ COPY --from=builder /pybase /pybase
COPY . /app/notes
WORKDIR /app/notes
EXPOSE 80
CMD [ "flask", "run", "--port=80", "--host=0.0.0.0" ]
Let's build our new image: docker build -t notesapp:multistage .
Let's see the layers and size:
docker inspect -f "$showLayers" notesapp:multistage | wc -l
13
docker inspect -f "$showSize" notesapp:multistage | numfmt --to=iec
919M
So the multi stage image can reduce the size and layer fo the final image.