diff --git a/classes/image-oci-sloci-image.inc b/classes/image-oci-sloci-image.inc new file mode 100644 index 00000000..36d3c2da --- /dev/null +++ b/classes/image-oci-sloci-image.inc @@ -0,0 +1,67 @@ +IMAGE_CMD_oci() { + sloci_options="" + + bbdebug 1 "OCI image settings:" + bbdebug 1 " author: ${OCI_IMAGE_AUTHOR}" + bbdebug 1 " author email: ${OCI_IMAGE_AUTHOR_EMAIL}" + bbdebug 1 " tag: ${OCI_IMAGE_TAG}" + bbdebug 1 " arch: ${OCI_IMAGE_ARCH}" + bbdebug 1 " subarch: ${OCI_IMAGE_SUBARCH}" + bbdebug 1 " entrypoint: ${OCI_IMAGE_ENTRYPOINT}" + bbdebug 1 " entrypoing args: ${OCI_IMAGE_ENTRYPOINT_ARGS}" + bbdebug 1 " labels: ${OCI_IMAGE_LABELS}" + bbdebug 1 " uid: ${OCI_IMAGE_RUNTIME_UID}" + bbdebug 1 " working dir: ${OCI_IMAGE_WORKINGDIR}" + bbdebug 1 " env vars: ${OCI_IMAGE_ENV_VARS}" + bbdebug 1 " ports: ${OCI_IMAGE_PORTS}" + + # Change into the image deploy dir to avoid having any output operations capture + # long directories or the location. + cd ${IMGDEPLOYDIR} + + oci_image_label_options="" + if [ -n "${OCI_IMAGE_LABELS}" ]; then + for l in ${OCI_IMAGE_LABELS}; do + oci_image_label_options="${oci_image_label_options} --label ${l}" + done + fi + oci_image_env_options="" + if [ -n "${OCI_IMAGE_ENV_VARS}" ]; then + for l in ${OCI_IMAGE_ENV_VARS}; do + oci_image_env_options="${oci_image_env_options} --env ${l}" + done + fi + oci_image_port_options="" + if [ -n "${OCI_IMAGE_PORTS}" ]; then + for l in ${OCI_IMAGE_PORTS}; do + oci_image_port_options="${oci_image_port_options} --port ${l}" + done + fi + + if [ -n "${OCI_IMAGE_RUNTIME_UID}" ]; then + oci_image_user_options="--user ${OCI_IMAGE_RUNTIME_UID}" + fi + + if [ -n "${OCI_IMAGE_WORKINGDIR}" ]; then + oci_image_working_dir_options="--working-dir ${OCI_IMAGE_WORKINGDIR}" + fi + + if [ -n "${OCI_IMAGE_TAR_OUTPUT}" ]; then + sloci_options="$sloci_options --tar" + fi + + # options that always appear are required for a valid oci container image + # others are optional based on settings. + sloci-image $sloci_options \ + --arch ${OCI_IMAGE_ARCH} \ + --arch-variant "${OCI_IMAGE_SUBARCH}" \ + --entrypoint ${OCI_IMAGE_ENTRYPOINT} \ + --cmd "${OCI_IMAGE_ENTRYPOINT_ARGS}" \ + --author ${OCI_IMAGE_AUTHOR_EMAIL} \ + ${oci_image_user_options} \ + ${oci_image_label_options} \ + ${oci_image_env_options} \ + ${oci_image_working_dir_options} \ + ${oci_image_port_options} \ + ${IMAGE_ROOTFS} ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci:${OCI_IMAGE_TAG} +} diff --git a/classes/image-oci-umoci.inc b/classes/image-oci-umoci.inc new file mode 100644 index 00000000..b622714e --- /dev/null +++ b/classes/image-oci-umoci.inc @@ -0,0 +1,111 @@ +IMAGE_CMD_oci() { + umoci_options="" + + bbdebug 1 "UMOCI image settings:" + bbdebug 1 " author: ${OCI_IMAGE_AUTHOR}" + bbdebug 1 " author email: ${OCI_IMAGE_AUTHOR_EMAIL}" + bbdebug 1 " tag: ${OCI_IMAGE_TAG}" + bbdebug 1 " arch: ${OCI_IMAGE_ARCH}" + bbdebug 1 " subarch: ${OCI_IMAGE_SUBARCH}" + bbdebug 1 " entrypoint: ${OCI_IMAGE_ENTRYPOINT}" + bbdebug 1 " entrypoint args: ${OCI_IMAGE_ENTRYPOINT_ARGS}" + bbdebug 1 " labels: ${OCI_IMAGE_LABELS}" + bbdebug 1 " uid: ${OCI_IMAGE_RUNTIME_UID}" + bbdebug 1 " working dir: ${OCI_IMAGE_WORKINGDIR}" + bbdebug 1 " env vars: ${OCI_IMAGE_ENV_VARS}" + bbdebug 1 " ports: ${OCI_IMAGE_PORTS}" + + OCI_REUSE_IMAGE="" + + # Change into the image deploy dir to avoid having any output operations capture + # long directories or the location. + cd ${IMGDEPLOYDIR} + + new_image=t + image_name="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci" + image_bundle_name="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci-bundle" + if [ -n "$OCI_REUSE_IMAGE" ]; then + if [ -d $image_name ]; then + bbdebug 1 "OCI: reusing image directory" + new_image="" + fi + else + bbdebug 1 "OCI: removing existing container image directory" + rm -rf $image_name $image_bundle_name + fi + + if [ -z "${OCI_IMAGE_TAG}" ]; then + OCI_IMAGE_TAG="initial-tag" + fi + + if [ -n "$new_image" ]; then + bbdebug 1 "OCI: umoci init --layout $image_name" + umoci init --layout $image_name + umoci new --image $image_name:${OCI_IMAGE_TAG} + umoci unpack --rootless --image $image_name:${OCI_IMAGE_TAG} $image_bundle_name + else + # todo: create a different tag, after checking if the passed one exists + true + fi + + bbdebug 1 "OCI: populating rootfs" + bbdebug 1 "OCI: cp -r ${IMAGE_ROOTFS}/* $image_bundle_name/rootfs/" + cp -r ${IMAGE_ROOTFS}/* $image_bundle_name/rootfs + + bbdebug 1 "OCI: umoci repack --image $image_name:${OCI_IMAGE_TAG} $image_bundle_name" + umoci repack --image $image_name:${OCI_IMAGE_TAG} $image_bundle_name + + bbdebug 1 "OCI: configuring image" + if [ -n "${OCI_IMAGE_LABELS}" ]; then + for l in ${OCI_IMAGE_LABELS}; do + bbdebug 1 "OCI: umoci config --image $image_name --config.label $l" + umoci config --image $image_name --config.label $l + done + fi + if [ -n "${OCI_IMAGE_ENV_VARS}" ]; then + for l in ${OCI_IMAGE_ENV_VARS}; do + bbdebug 1 "umoci config --image $image_name --config.env $l" + umoci config --image $image_name --config.env $l + done + fi + if [ -n "${OCI_IMAGE_PORTS}" ]; then + for l in ${OCI_IMAGE_PORTS}; do + bbdebug 1 "umoci config --image $image_name --config.exposedports $l" + umoci config --image $image_name --config.exposedports $l + done + fi + if [ -n "${OCI_IMAGE_RUNTIME_UID}" ]; then + bbdebug 1 "umoci config --image $image_name --config.user ${OCI_IMAGE_RUNTIME_UID}" + umoci config --image $image_name --config.user ${OCI_IMAGE_RUNTIME_UID} + fi + if [ -n "${OCI_IMAGE_WORKINGDIR}" ]; then + bbdebug 1 "umoci config --image $image_name --config.workingdir ${OCI_IMAGE_WORKINGDIR}" + umoci config --image $image_name --config.workingdir ${OCI_IMAGE_WORKINGDIR} + fi + if [ -n "${OCI_IMAGE_OS}" ]; then + bbdebug 1 "umoci config --image $image_name --os ${OCI_IMAGE_OS}" + umoci config --image $image_name --os ${OCI_IMAGE_OS} + fi + + bbdebug 1 "umoci config --image $image_name --architecture ${OCI_IMAGE_ARCH}" + umoci config --image $image_name --architecture ${OCI_IMAGE_ARCH} + # NOTE: umoci doesn't currently expose setting the architecture variant, + # so if you need it use sloci instead + if [ -n "${OCI_IMAGE_SUBARCH}" ]; then + bbnote "OCI: image subarch is set to: ${OCI_IMAGE_SUBARCH}, but umoci does not" + bbnote " expose variants. use sloci instead if this is important" + fi + umoci config --image $image_name --config.entrypoint ${OCI_IMAGE_ENTRYPOINT} + if [ -n "${OCI_IMAGE_ENTRYPOINT_ARGS}" ]; then + umoci config --image $image_name --config.cmd "${OCI_IMAGE_ENTRYPOINT_ARGS}" + fi + umoci config --image $image_name --author ${OCI_IMAGE_AUTHOR_EMAIL} + + # make a tar version of the image direcotry + if [ -n "${OCI_IMAGE_TAR_OUTPUT}" ]; then + tar -cf "$image_name.tar" "$image_name" + fi + + # We could make this optional, since the bundle is directly runnable via runc + rm -rf $image_bundle_name +} diff --git a/classes/image-oci.bbclass b/classes/image-oci.bbclass index c256b12c..464ea3b4 100644 --- a/classes/image-oci.bbclass +++ b/classes/image-oci.bbclass @@ -16,19 +16,32 @@ # And then create the bundle: # % oci-image-tool create --ref name=latest container-base--.rootfs-oci container-base-oci-bundle # +# Alternatively, the bundle can be created with umoci (use --rootless if sudo is not available) +# % sudo umoci unpack --image container-base--.rootfs-oci:latest container-base-oci-bundle +# # Or to copy (push) the oci image to a docker registry, skopeo can be used (vary the # tag based on the created oci image: # # % skopeo copy --dest-creds : oci:container-base--:latest docker://zeddii/container-base # +# If your build host architecture matches the target, you can execute the unbundled +# container with runc: +# +# % sudo runc run -b container-base-oci-bundle ctr-build +# / % uname -a +# Linux mrsdalloway 4.18.0-25-generic #26-Ubuntu SMP Mon Jun 24 09:32:08 UTC 2019 x86_64 GNU/Linux +# # We'd probably get this through the container image typdep, but just # to be sure, we'll repeat it here. ROOTFS_BOOTSTRAP_INSTALL = "" # we want container and tar.bz2's to be created IMAGE_TYPEDEP_oci = "container tar.bz2" + # sloci is the script/project that will create the oci image -do_image_oci[depends] += "sloci-image-native:do_populate_sysroot" +# OCI_IMAGE_BACKEND ?= "sloci-image" +OCI_IMAGE_BACKEND ?= "umoci" +do_image_oci[depends] += "${OCI_IMAGE_BACKEND}-native:do_populate_sysroot" # # image type configuration block @@ -75,70 +88,7 @@ def oci_map_subarch(a, f, d): return '' return '' -IMAGE_CMD_oci() { - sloci_options="" +# the IMAGE_CMD_oci comes from the .inc +OCI_IMAGE_BACKEND_INC ?= "${@"image-oci-" + "${OCI_IMAGE_BACKEND}" + ".inc"}" +include ${OCI_IMAGE_BACKEND_INC} - bbdebug 1 "OCI image settings:" - bbdebug 1 " author: ${OCI_IMAGE_AUTHOR}" - bbdebug 1 " author email: ${OCI_IMAGE_AUTHOR_EMAIL}" - bbdebug 1 " tag: ${OCI_IMAGE_TAG}" - bbdebug 1 " arch: ${OCI_IMAGE_ARCH}" - bbdebug 1 " subarch: ${OCI_IMAGE_SUBARCH}" - bbdebug 1 " entrypoint: ${OCI_IMAGE_ENTRYPOINT}" - bbdebug 1 " entrypoing args: ${OCI_IMAGE_ENTRYPOINT_ARGS}" - bbdebug 1 " labels: ${OCI_IMAGE_LABELS}" - bbdebug 1 " uid: ${OCI_IMAGE_RUNTIME_UID}" - bbdebug 1 " working dir: ${OCI_IMAGE_WORKINGDIR}" - bbdebug 1 " env vars: ${OCI_IMAGE_ENV_VARS}" - bbdebug 1 " ports: ${OCI_IMAGE_PORTS}" - - # Change into the image deploy dir to avoid having any output operations capture - # long directories or the location. - cd ${IMGDEPLOYDIR} - - oci_image_label_options="" - if [ -n "${OCI_IMAGE_LABELS}" ]; then - for l in ${OCI_IMAGE_LABELS}; do - oci_image_label_options="${oci_image_label_options} --label ${l}" - done - fi - oci_image_env_options="" - if [ -n "${OCI_IMAGE_ENV_VARS}" ]; then - for l in ${OCI_IMAGE_ENV_VARS}; do - oci_image_env_options="${oci_image_env_options} --env ${l}" - done - fi - oci_image_port_options="" - if [ -n "${OCI_IMAGE_PORTS}" ]; then - for l in ${OCI_IMAGE_PORTS}; do - oci_image_port_options="${oci_image_port_options} --port ${l}" - done - fi - - if [ -n "${OCI_IMAGE_RUNTIME_UID}" ]; then - oci_image_user_options="--user ${OCI_IMAGE_RUNTIME_UID}" - fi - - if [ -n "${OCI_IMAGE_WORKINGDIR}" ]; then - oci_image_working_dir_options="--working-dir ${OCI_IMAGE_WORKINGDIR}" - fi - - if [ -n "${OCI_IMAGE_TAR_OUTPUT}" ]; then - sloci_options="$sloci_options --tar" - fi - - # options that always appear are required for a valid oci container image - # others are optional based on settings. - sloci-image $sloci_options \ - --arch ${OCI_IMAGE_ARCH} \ - --arch-variant "${OCI_IMAGE_SUBARCH}" \ - --entrypoint ${OCI_IMAGE_ENTRYPOINT} \ - --cmd "${OCI_IMAGE_ENTRYPOINT_ARGS}" \ - --author ${OCI_IMAGE_AUTHOR_EMAIL} \ - ${oci_image_user_options} \ - ${oci_image_label_options} \ - ${oci_image_env_options} \ - ${oci_image_working_dir_options} \ - ${oci_image_port_options} \ - ${IMAGE_ROOTFS} ${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci:${OCI_IMAGE_TAG} -}