roci is a packaging utility that converts OCI images to RPM packages. It is
intended to reduce the barrier to entry when building system packages.
ARG VERSION=4.3
ARG DIST
FROM fedora-rpm-buildroot:${DIST} as buildrequires
WORKDIR /src/
COPY poke-${VERSION}.tar.gz .
COPY poke-${VERSION}.tar.gz.sig .
RUN dnf -y install emacs gcc gc-devel nbdkit make
FROM localhost/poke-buildrequires as builder
RUN rpmdev-extract poke-${VERSION}.tar.gz
WORKDIR /src/poke-${VERSION}
RUN ./configure; \
make build; \
make check
RUN make install PREFIX=/usr/local
FROM fedora-rpm-buildroot:${DIST} as poke
LABEL org.opencontainers.image.version=${VERSION}
LABEL org.opencontainers.image.url="https://www.jemarch.net/poke"
LABEL org.opencontainers.image.title="Extensible editor for structured binary data"
LABEL org.opencontainers.image.description="GNU poke is an interactive, extensible editor for binary data."
LABEL org.opencontainers.image.licenses="GPL-3.0-or-later AND GFDL-1.3-no-invariants-or-later"
COPY --from=builder /usr/local/bin /usr/binroci can read all rpm package metadata from a configuration file. This is
necessary for certain rpm settings that cannot be set as labels, e.g. Requires
or scriptlets.
Name: "poke"
Version: 4.3
Release: $AUTORELEASE
Summary: "Extensible editor for structured binary data"
Description: |
GNU poke is an interactive, extensible editor for binary data. Not
limited to editing basic entities such as bits and bytes, it provides
a full-fledged procedural, interactive programming language designed
to describe data structures and to operate on them.
URL: "https://www.jemarch.net/poke"
License: "GPL-3.0-or-later AND GFDL-1.3-no-invariants-or-later"
Requires:
- "poke-data = $VERSION-$RELEASE"
- "poke-libs = $VERSION-$RELEASE"
Requires(preun): ""
Preun: "/usr/sbin/alternatives --remove poke /usr/bin/poke || :"
package:
poke-devel:
Name: "poke-devel"
Summary: "Development files for poke"
Requires:
- "poke = $VERSION-$RELEASE"
Description: |
The poke-devel package contains libraries and header files for
developing applications that use poke.Each output stage must be defined in the config file, except for the main package, which is always built.
The yaml configuration file must be called $pkg-name.yaml where
$pkg-name is the main package's name (this should be the same as the directory)
The following OCI annotations/labels are directly converted into RPM tags:
org.opencontainers.image.version->Versionorg.opencontainers.image.url->URLorg.opencontainers.image.title->Summaryorg.opencontainers.image.description->Descriptionorg.opencontainers.image.licenses->License
Additionally, we invent our own to address the remaining missing RPM tags:
org.rpm.name->Nameorg.rpm.epoch->Epochorg.rpm.release->Release
To support consistent building of packages from Containerfiles, the following
stages must be present in the Containerfile:
-
buildrequires- the first stage where all sources are copied into the container build/buildroot and dependencies are installed. This stage runs with network access to install build dependencies. Package sources must be pre-downloaded andCOPY'd into the buildroot. The result of this stage is tagged as$name-buildrequires. This stage must${distro}-rpm-buildroot:$DISTasFROM. -
build- the stage that actually builds the package and runs the tests. It must uselocalhost/$name-buildrequiresas theFROMimage. -
$nameand$subpkg-namestages - the build results are copied into these stages. These stages must use${distro}-rpm-buildroot:$DISTasFROMand
Subpackages are defined as build stages in the Containerfile, but they must be
named as dictionary entries in the package key. Stages not defined in the
config file, are ignored.
RPM supports automatic provides and requires generation from package file
contents, also called AutoReqProv. It is nowadays generally enabled and
absolutely crucial for modern packaging workflows.
roci generates automatic provides & requires using rpmdeps. This binary used
to be used for AutoReqProv in the past, but nowadays rpm does that
internally. Yet the binary remains and can be used. roci launches rpmdeps in
the $name and $subpkg-name containers, parses its output and inserts the
result into the fully assembled rpm.
Dockerfiles do not support typical rpm constructs like %bcond or
macros.
roci supports a few ways to circumvent this limitation:
-
common compiler flags are exported as environment variables in the
${distro}-rpm-buildrootcontainer images -
The common directory macros like
%_bindiror%_mandirare passed as build arguments during the build with the name in uppercase and without the leading_. I.e. if you want to put something into%_bindir, then
$ roci build [path/to/dist-git-dir]