Introduction to the problem
Recently while building a Dockerfile for pipenv in alpine in order to have a smaller footprint image then kennethreitz/pipenv I started using ONBUILD
docker trigger.
For those who haven’t used ONBUILD
before , this is a build trigger that even by overriding the image will be ran when image is built according to the order defined for the base image. This is very useful, and is used in a multitude of images.
However, since I was using an alpine based image, some of my Pipenv dependencies had system dependencies that don’t come with the alpine base image, such as gcc
that is present in the build-base package.
This presented me with a challenge, I wanted to reuse that image and keep it small, but also had the need to extend its base packages to have a list of packages that were not present under the base image I built at first.
First attempt had me going with Dockerfile to override that image, but the triggers from the ONBUILD
were ran first, so I had two options, either give that base image build-base so I could use gcc, and force it to anyone using the image on the future but since I wouldn’t want that package in every single python project I would use so that’s definitely a NO, or just create a copy and add the RUN
directives first, but then why would I want to have a base image at all?
This made me wonder if I couldn’t just use build ARG
as a way to have both of this, allowing me to install new packages I would need without messing with the original image, and also without having a Dockerfile that would be a copy plus the extension I would need, but I wouldn’t also want a script to handle all the args or env’s I could pass to the Dockefile.
Keeping it simple using a ARG as list
As you can see from the Dockefile I ended up using Dockerfile for pipenv:alpine this is actually pretty simple to accomplish for this case.
1
2
3
ARG packages
RUN apk --update add ${packages} \
&& rm -rf /var/cache/apk/*
So now when I wanted to use this image and just add new system packages to it, I would simply use a –build-arg packages.
Usage for this case:
1
docker build -t andreilhicas/pipenv:alpine-custom --build-arg packages="build-base" .
Since this will be expanded in the RUN
command under the original image, if I wanted to have more packages I would simply delimit them with a blank space similar to how you would write it on the Dockerfile.
1
docker build -t andreilhicas/pipenv:alpine-custom --build-arg packages="build-base wget curl git"
But I don’t want to clone your repo to have custom packages in my Dockerfile
Of course the problem here lies on having a Dockerfile, since this cannot be achieved by using a docker run
or docker pull
since this is effectively build a new image using base image layers.
There are two possible approaches to this:
- Using a dockerfile
1
FROM andreilhicas/pipenv:alpine
And now you may make your changes using only the image that will be pulled from the hub.docker.com
in this case, since its a public image,
Or directly from the github repo that hosts this dockerfile.
1
docker build -t andreilhicas/pipenv:alpine-custom --build-arg packages="build-base" https://github.com/Ilhicas/alpine-pipenv.git
For further info on Build from URL
visit Docker BUILD Documentation