Docker injection images¶
Some utilities that Whitebox requires to operate need to be built from source
(for example, ffmpeg). As those images seldom update, we can build them once
and reuse that build in all future builds.
As an example, take a look at packaging/docker/injection_images/ffmpeg.Dockerfile.
It downloads ffmpeg and compiles it with flags that we need, allowing us to
reuse this image. For easier access, this image is distributed to
Whitebox project's container registry.
Using injection images¶
To use an injection image, you should find it at the container repository, and
you can then copy its files inside the container you are building. For example,
with ffmpeg, everything that's compiled resides in /usr/local/, so to use
it, you need to COPY all those files into your build:
Some injection images may need additional steps, such as dynamic linked update,
additional dependency installations through package manager, etc. Refer to the
originating Dockerfile's comments, in this example - ffmpeg.Dockerfile.
Building and managing injection images¶
To simplify image management, there is a
packaging/scripts/maintenance/build_registry_images.sh
script available. You can use it to build (and push) *.Dockerfiles inside
packaging/docker/injection_images/ and packaging/docker/standalone_images/.
You can either specify image names, or provide --all argument to specify
build targets. Additionally, provide --push to push them to registry.
Tag version, obtained from Dockerfile's ENV REGISTRY_TAG=VERSION_VALUE line,
will be used to tag the resulting image and will be pushed with that tag. If
the file does not contain such a line, image will not be built.
Writing Dockerfiles for injection images¶
File contents¶
As mentioned above, these Dockerfiles need to be placed within
packaging/docker/injection_images/.
The script needs to define environment variable REGISTRY_TAG that will be
used to infer the tag version when pushing the image. For example, if you want
your image to be tagged with version 1.3.37a, you would need to place this
line in your file:
Optimizing image size¶
When writing an image to compile a program, the resulting image is usually
going to be extremely heavy, as it would contain minimal OS layer, compilers,
additionally downloaded dependencies, etc. As these images exist only to hold
data to be injected into other images, you can strip the end result image to
contain only the data they actually need to provide (e.g. produced libraries
and executables). Even if not technically mandatory, you should not skip this
step as the gains can be huge (e.g. for ffmpeg, this reduced the resulting
image size from ~750MB to ~75MB).
For the sake of the example, let's assume:
- Your build requires you to start from
debianimage - Your build's output is contained to two dirs, /usr/local/
and/opt/helloworld/`
You can start a new image from a blank slate and just add those files to it:
# Name the first build step for easier access
FROM debian AS builder
ENV ENV REGISTRY_TAG=1.3.37a
# Run your build here that produces those files
# Now let's create a new build step, that will be the actual end resulting image
# that gets pushed to the registry
FROM scratch
COPY --from=builder /usr/local/ /usr/local/
COPY --from=builder /opt/helloworld/ /opt/helloworld/
And voilĂ ~, you now have a lightweight image!