Containers
A Factory’s containers.git
repo holds the source for Docker containers, as well as Compose Apps.
When changes are made to this repo, new Targets will be built.
The CI logic for building a Target is based on simple naming rules:
- Ignores top-level directories that ends with
.disabled
.- A container image will be built for every top-level directory containing a file named
Dockerfile
.- A compose app will be built for every top-level directory containing a file named
docker-compose.yml
.
Both a container image and compose app will be built if both a Dockerfile and Docker-compose file are included.
Advanced Container Usage
A docker-build.conf
file enables advanced functionality.
This is sourced by the CI shell script and can set build time options:
- TEST_CMD: Adding
TEST_CMD="<some command>"
directs the CI builder to run the command inside the container to verify that it is functioning correctly.- SKIP_ARCHS: A container will not be built for the specified architecture, e.g.,
SKIP_ARCHS=arm64
.- EXTRA_TAGS_$ARCH: This can work with
SKIP_ARCHS
. If builds are skipped for arm64, an arm32 container could be tagged for it withEXTRA_TAGS_arm=arm64
.- DOCKER_BUILD_CONTEXT: Set an alternative directory for the Docker build context.
Examples
# Only build for amd64 and arm
SKIP_ARCHS="arm64"
# Use a 32-bit arm container for a 64-bit host:
SKIP_ARCHS="arm64"
EXTRA_TAGS_arm="arm64"
# Use container.git as the build context
BUILD_CONTEXT="../"
Passing Arguments to Build Context
Containers may require Dockerfile ARG support for including build time variables.
If the file .docker_build_args
exists in a container director, the contents are used as --build-arg
options.
These are passed to the docker build
command.
Static information can be done by defining a file like:
# <container>/.docker_build_args
KEY=Value
KEY2="Value with spaces"
This produces a build command that includes --build-arg KEY=Value --build-arg KEY2="Value with spaces"
.
The need for dynamic arguments means some values must be generated at build time.
This can be accomplished is by taking advantage of docker-build.conf
;
as it is sourced by the build script, it can be used to generate content dynamically.
Example
A common case is including Git commit information in a container:
<container>/docker-build.conf
# $TAG is set by the build script as the Git short hash of the
# containers.git commit being built.
#
# $x is the path to the container.
cat <<EOF >$x/.docker_build_args
GIT_SHA=$TAG
GIT_MSG="$(git log --format=%s -1)"
EOF
<container>/Dockerfile
...
# NOTE - These ARG's change *every* build. In order to maximize
# Docker build caching, they should be as close to the end of the
# file as possible so that the steps after these lines don't have
# to get re-run *every* build.
ARG GIT_SHA
ARG GIT_MSG
ENV GIT_SHA=$GIT_SHA
ENV GIT_MSG=$GIT_MSG
Advanced Container Dependencies
If you need custom code to be executed before the Docker build,
add pre-build.conf
in the top-level directory of containers.git
.
Examples
Here are examples of what can be done in pre-build.conf
:
# Create a file with build environment for container "shellhttpd":
env > shellhttpd/envvars
# Allow containers in factory to use a common base image
# First: Make our images build in a predictable order.
# This ensures 0base is built first so other containers can inherit it:
export IMAGES=$(find ./ -mindepth 2 -maxdepth 2 -name Dockerfile | cut -d / -f2 | sort)
# Second: Modify each container to use the locally build arch-specific base image:
_base_img="hub.foundries.io/${FACTORY}/0base:$LATEST-$ARCH"
for x in $IMAGES ; do
echo "Prebuild checking $x for FROM override"
sed -i "s|hub.foundries.io/${FACTORY}/0base|${_base_img}|" $x/Dockerfile
done
Note
If there is shared files between containers, the recommendation is to put the common folder in the base image. The containers can inherit the files using Multi-Stage Container Builds.