Adding and Modifying Container Images¶
All container images are defined in the bci_build.package
package as
instances of the DevelopmentContainer
,
ApplicationStackContainer
or
OsContainer
classes.
The different classes result in slightly different images, mostly with respect
to the way versions, tags and labels are handled. For example instances of
ApplicationStackContainer
will receive the label
com.suse.image-type="application"
, whereas all others will have
com.suse.image-type="sle-bci"
.
To create a new container image, pick the most fitting class for it and create an instance of it supplying the following values:
name
: This is a short identifier of your image and is used to generate the name of this image on the registry as well as the prefixlabel. Pick something short and descriptive, e.g.node
for a Node.js container image.package_name
: The name of the package on build.opensuse.org indevel:BCI:SLE-15-SP${os_version}
that is used to build this container image. This value is not autogenerated, as we were inconsistent in the past, but this value should default touid
-image
.package_list
: The list of packages to be installed into the container image. You can either provide a list of strings here or provide a list ofPackage
class instances. The latter is only necessary if you want to build your container image with kiwi and wish to customize the package installation (or deletion) process. See Installing Packages into the Container Image for further details.
Adding files to the Image¶
The package on build.opensuse.org will by default only consist of the following files:
Dockerfile
or$pkg_name.kiwi
and optionally aconfig.sh
$pkg_name.changes
_service
It is sometimes necessary to include additional files in a Container Image,
e.g. a longer script or configuration file. This can be achieved by adding the
file to the extra_files
dictionary. The key should be the file name and the value are the file contents.
Please only include very short files directly in
package
. Longer files should go into a subdirectory of
src/bci_build/package/
and be read in on construction. In case you are
taking the additional file from an upstream source, then consider adding it to
the script update-files.sh
as well. A Github Action runs this script
every day and ensures that your external file stays up to date.
Automatic Package Version Substitution¶
Some Container Images ship with environment variables that include the version
of a component in the container image. For example the PostgreSQL Container
Image sets the environment variable PG_VERSION
to the major.minor
version of PostgreSQL installed in the container image.
Setting this environment variable manually is rather brittle and would require to constantly update the sources. Instead, we can leverage the service obs-service-replace_using_package_version.
The BaseContainerImage
has builtin support for
this service via the attribute
replacements_via_service
. To
use it in your container image, pick a replacement string that is unique for
your whole build description. For the PostgreSQL version we could for instance
pick %%pg_version%%
. Then an instance of
Replacement
needs to be added to the list
replacements_via_service
, where
the attribute
regex_in_build_description
is set to
the replacement string. Additionally the attribute
package_name
has to be set to the
exact name of the package which version we wish to extract. If only a part
of the version is required, e.g. as with PG_VERSION
where we only care about
the major and minor version, but not the patch level, we can instruct the
service to only extract the version up to a certain point via the attribute
parse_version
.
Our PostgreSQL example would result in the following code:
ApplicationStackContainer(
additional_versions=[f"%%pg_version%%"],
env={
"PG_VERSION": f"%%pg_version%%",
},
replacements_via_service=[
Replacement(
regex_in_build_description="%%pg_version%%",
package_name=f"postgresql14-server",
parse_version="minor",
)
],
# rest follows here
)
Note that this process is not limited to environment variable, it can be
used to replace anything inside the container build description. This can be
seen in the above code block, where we also set the
additional_versions
attribute via this mechanism.
Caution
The current setup cannot replace versions in READMEs. If you rely on
versions getting replaced in a README (usually via the
pretty_reference
property),
then you must hardcode the version using the mechanism outlined in the
versions
module.
Installing Packages into the Container Image¶
In most cases it sufficient to just set the
package_list
attribute to a
list of package names as strings. This will yield a RUN zypper -n
in --no-recommends $list_of_packages line in the Dockerfile
or the
following XML in the kiwi build description:
<packages type="image">
<!-- one line per package -->
<package name="$pkg_name"/>
</packages>
Kiwi supports additional package types to e.g. explicitly delete packages or add them to the bootstrap image. Please see https://osinside.github.io/kiwi/concept_and_workflow/packages.html for further details.
To add packages of a different type than image
requires to use instances of
Package
with the
pkg_type
set to the appropriate value. For
example:
package_list=[
Package(name, pkg_type=PackageType.BOOTSTRAP)
for name in (
"bash",
"ca-certificates-mozilla-prebuilt",
"distribution-release",
)
]
Applying additional changes to your Image¶
Container Images can be tweaked extensively via a plethora of different keywords
in Dockerfile
. To stay compatible with kiwi build descriptions and to
avoid some common pitfalls when creating a Dockerfile
.
For the following Dockerfile
settings, use the respective properties of
BaseContainerImage
:
ENTRYPOINT
:entrypoint
CMD
:cmd
VOLUME
:volumes
EXPOSE
:exposes_ports
ENV
:env
LABEL
:extra_labels
MAINTAINER
:maintainer
USER
:entrypoint_user
For additional settings that do not fit the existing attributes, either create
an abstraction (if feasible and meaningful) or use
custom_end
to write a raw
Dockerfile
yourself.
New Package Checklist¶
[ ] Merge the pull request creating the container into
main
[ ] Review the automatically created pull request against the deployment branches and add a changelog entry
[ ] Create the package on
devel:BCI:
with a<scmsync>
entry so that it is pulled from git, this can be done automatically via the scratch_build_bot setup_obs_package command.[ ] Set up branch protection rules for the deployment branches including the newly added package for the OBS SCM builds