Upon revisiting one of my past projects, I attempted to build the docker image I once prepared but encountered a failure:
$ docker build -t fortune-api:0.4.2 \
'https://github.com/lbacik/fortune-api.git#v0.4.2'
...
6.520 Reading state information...
6.523 E: Unable to locate package fortunes-off
6.523 E: Unable to locate package fortunes-fr
...
ERROR: failed to solve:
process "/bin/sh -c apt-get -y update && apt-get -y install ..."
did not complete successfully: exit code: 100
It had definitely worked in the past – the previously created image is still functional: https://fortune-api.luka.sh/.
Why does it fail now? 🤔
A glimpse at Dockerfile (v0.4.2):
FROM python:3.9
ENV FORTUNES=/usr/share/games/fortunes
ENV CORS=yes
RUN apt-get -y update && apt-get -y install \
fortunes \
fortunes-off \
fortune-anarchism \
fortunes-bg \
fortunes-bofh-excuses \
fortunes-br \
fortunes-cs \
fortunes-de \
fortunes-debian-hints \
fortunes-es \
fortunes-es-off \
fortunes-fr \
fortunes-ga \
fortunes-it \
fortunes-it-off \
fortunes-mario \
fortunes-pl \
fortunes-ru \
fortunes-zh
COPY . /opt/project
WORKDIR /opt/project
RUN pip install -r requirements.txt
EXPOSE 8080
CMD uwsgi --ini config.ini
The problem is the Debian distro version, which the python:3.9 image has been built on. Dockerhub shows now:
When I created the Dockerfile and built it previously, the python:3.9 image used Debian’s “Bullseye” version (debian:11).
The latest version of Debian was released on June 10, 2023. Unfortunately, it caused my Dockerfile build to fail due to package changes.
Certainly, there is a straightforward solution to my problem. I can specify the image version more precisely as python:3.9-bullseye. This should work, but it doesn’t seem too elegant. My application requires data — but the source of this data is not essential (for the app) and can change!
FROM debian:11 as base
# hadolint ignore=DL3008,DL3015
RUN apt-get -y update && apt-get -y install \
fortunes \
fortunes-off \
fortune-anarchism \
fortunes-bg \
fortunes-bofh-excuses \
fortunes-br \
fortunes-cs \
fortunes-de \
fortunes-debian-hints \
fortunes-es \
fortunes-es-off \
fortunes-fr \
fortunes-ga \
fortunes-it \
fortunes-it-off \
fortunes-mario \
fortunes-pl \
fortunes-ru \
fortunes-zh
FROM python:3.9
ENV FORTUNES=/usr/share/games/fortunes
ENV CORS=yes
COPY --from=base /usr/share/games/fortunes /usr/share/games/fortunes
COPY . /opt/project
WORKDIR /opt/project
# hadolint ignore=DL3042
RUN pip install -r requirements.txt
EXPOSE 8080
CMD ["uwsgi", "--ini", "config.ini"]
A multi-stage build fits here great, doesn’t it?!
And for Debian 12:
FROM debian:12 as base
# hadolint ignore=DL3008,DL3015
RUN apt-get -y update && apt-get -y install \
fortune-anarchism \
fortune-mod \
fortunes-bg \
fortunes-bofh-excuses \
fortunes-br \
fortunes-cs \
fortunes-de \
fortunes-debian-hints \
fortunes-eo \
fortunes-es-off \
fortunes-es \
fortunes-ga \
fortunes-it-off \
fortunes-it \
fortunes-mario \
fortunes-min \
fortunes-pl \
fortunes-ru \
fortunes-zh \
fortunes
FROM python:3.9
ENV FORTUNES=/usr/share/games/fortunes
ENV CORS=yes
COPY --from=base /usr/share/games/fortunes /usr/share/games/fortunes
COPY . /opt/project
WORKDIR /opt/project
# hadolint ignore=DL3042
RUN pip install -r requirements.txt
EXPOSE 8080
CMD ["uwsgi", "--ini", "config.ini"]
- The app part doesn’t change
- There is a separate step to prepare the required data (this step can be easily aligned to the appropriate source)
Isn’t it much cleaner?