commit 6f7e4a7f09d706076d07599591a09545e528aae7 Author: Eugene Zamriy Date: Sat Apr 8 18:38:10 2023 +0300 Initial commit: implemented MSVSphere 9.1 default image building diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d1e97a8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Eugene Zamriy, Softline.ru. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa57cc4 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# Inferit MSVSphere Docker images + +This project contains configuration files and tools for building +[official MSVSphere Docker](https://hub.docker.com/r/inferit/msvsphere) images. + + +## Build requirements + +In order to build an MSVSphere Docker image you need an MSVSphere system with +the following packages installed: + +```shell +$ sudo dnf install -y anaconda-tui lorax tar +``` + +You may also need to change SELinux mode to permissive. + + +## Usage + +The [build-image.sh](build-image.sh) tool must be executed from a root user +shell. See it's `--help` for a list of supported arguments. + +Here is an MSVSphere 9 default image build example: + +```shell +$ sudo ./build-image.sh --release 9 --type default --output ./result +``` + +The result will be a built rootfs-tarball, a generated Dockerfile and +corresponding build logs: + +```shell +$ ls result/9-default/ -1 +Dockerfile +logs +msvsphere-9-default.tar.xz +``` + + +## References + +* Docker documentation: [Create a base image](https://docs.docker.com/build/building/base-images/) +* RHEL System Design Guide: [Kickstart Reference guide](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/system_design_guide/kickstart-script-file-format-reference_system-design-guide) +* Opencontainers [image-spec annotations/labels](https://github.com/opencontainers/image-spec/blob/master/annotations.md) + + +## License + +Licensed under the MIT license, see the [LICENSE](LICENSE) file for details. + + +## Authors + +* [Eugene Zamriy](https://github.com/ezamriy) diff --git a/build-image.sh b/build-image.sh new file mode 100755 index 0000000..55538ac --- /dev/null +++ b/build-image.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +set -eo pipefail + +ARCH="$(uname -m)" +IMAGE_TYPE='default' +RELEASE='9' +BASE_DIR='./result' +PROGRAM_DIR="$(dirname -- "$0")" +VERSION='0.0.1' + +show_usage() { + echo -e 'Generates an MSVSphere container image RootFS and Dockerfile\n' + echo -e 'Usage: build-image.sh [OPTION]...\n' + echo ' -h, --help show this message and exit' + echo " -r, --release RELEASE target MSVSphere release, default is ${RELEASE}" + echo ' -t, --type TYPE image type, supported values are: default.' + echo " Default value is '${IMAGE_TYPE}'" + echo " -o, --output DIR output directory path, default is ${BASE_DIR}" + echo ' -v, --version show program version and exit' +} + +log_error() { + echo "ERROR : ${1}" >&2 +} + +gen_dockerfile() { + local -r image_name="${1}" + local -r build_date="$(date --rfc-3339=seconds --utc)" + echo 'FROM scratch' + echo "ADD ${image_name} /" + echo '' + # see https://github.com/opencontainers/image-spec/blob/master/annotations.md for details + echo "LABEL org.opencontainers.image.title=\"MSVSphere ${RELEASE} ${ARCH} ${IMAGE_TYPE} image\"" + echo 'LABEL org.opencontainers.image.vendor="MSVSphere"' + echo 'LABEL org.opencontainers.image.licenses="MIT"' + echo "LABEL org.opencontainers.image.created=\"${build_date}\"" + echo 'LABEL org.opencontainers.image.authors="Eugene Zamriy "' + echo 'LABEL org.opencontainers.image.source="https://git.inferitos.ru/msvsphere/docker-images"' + echo '' + # + case "${IMAGE_TYPE}" in + default) + echo 'CMD ["/bin/bash"]' + ;; + *) + log_error "unsupported image type ${IMAGE_TYPE}" + exit 1 + ;; + esac +} + +collect_logs() { + local -r logs_dir="${1}/logs" + mkdir "${logs_dir}" + if [[ -d anaconda ]]; then + mv anaconda "${logs_dir}/" + fi + mv ./*.log "${logs_dir}/" +} + +main() { + local -r image_name="msvsphere-${RELEASE}-${IMAGE_TYPE}.tar.xz" + local -r ks_file="${PROGRAM_DIR}/kickstarts/msvsphere-${RELEASE}-${IMAGE_TYPE}.ks" + local -r project="MSVSphere ${RELEASE} ${IMAGE_TYPE} Docker image" + local -r result_dir="${BASE_DIR%%/}/${RELEASE}-${IMAGE_TYPE}" + local -r docker_file="${result_dir}/Dockerfile" + if [[ -d "${result_dir}" ]]; then + log_error "directory ${result_dir} is already exist, please remove it first" + exit 1 + elif [[ ! -f "${ks_file}" ]]; then + log_error "kickstart file ${ks_file} is not found" + exit 1 + fi + # generate RootFS tarball + livemedia-creator --no-virt --make-tar \ + --project "${project}" \ + --releasever "${RELEASE}" \ + --image-name "${image_name}" \ + --ks "${ks_file}" \ + --resultdir "${result_dir}" \ + --anaconda-arg "--nosave all" + # generate Dockerfile and save build logs + gen_dockerfile "${image_name}" >"${docker_file}" + collect_logs "${result_dir}" +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + ARGS=() + while [[ $# -gt 0 ]]; do + case ${1} in + -h | --help) + show_usage + exit 0 + ;; + -t | --type) + case "${2}" in + default) + IMAGE_TYPE="${2}" + ;; + *) + log_error "unsupported image type '${2}'" + exit 2 + ;; + esac + shift + shift + ;; + -o | --output) + if [[ -z "${2}" ]]; then + log_error 'output directory path is required' + exit 2 + fi + BASE_DIR="${2}" + shift + shift + ;; + -v | --version) + echo "${VERSION}" + exit 0 + ;; + -*) + log_error "unknown option ${1}" + exit 2 + ;; + *) + ARGS+=("${1}") + shift + ;; + esac + done + main +fi diff --git a/kickstarts/msvsphere-9-default.ks b/kickstarts/msvsphere-9-default.ks new file mode 100644 index 0000000..9a7c5b7 --- /dev/null +++ b/kickstarts/msvsphere-9-default.ks @@ -0,0 +1,107 @@ +# MSVSphere 9 default Docker image kickstart file + +# TODO: change to the kickstart repo URL when we have it +url --url https://rsync.inferitos.ru/msvsphere/9/BaseOS/$basearch/os/ +repo --name=BaseOS --baseurl=https://rsync.inferitos.ru/msvsphere/9/BaseOS/$basearch/os/ +repo --name=AppStream --baseurl=https://rsync.inferitos.ru/msvsphere/9/AppStream/$basearch/os/ + +lang C.UTF-8 +keyboard us +timezone --nontp --utc UTC + +network --activate --bootproto=dhcp --device=link --onboot=on +selinux --disabled + +bootloader --disabled +zerombr +clearpart --all --initlabel +autopart --fstype=ext4 --type=plain --nohome --noboot --noswap + +rootpw --lock --plaintext msvsphere + +shutdown + +%packages --excludedocs --nocore --instLangs=en --excludeWeakdeps +sphere-release +bash +binutils +coreutils-single +crypto-policies-scripts +curl-minimal +findutils +hostname +iputils +glibc-minimal-langpack +less +libcurl-minimal +rootfiles +tar +vim-minimal +yum +xz +-dosfstools +-e2fsprogs +-gnupg2-smime +-hyperv* +-kernel +-langpacks-* +-langpacks-en +-libss +-open-vm-tools +-pinentry +-qemu-guest-agent +-subscription-manager +-trousers +-xfsprogs +-xkeyboard-config +%end + +# NOTE: add --log=/root/anaconda-post.log for debugging +%post --erroronfail +# generate build time file for compatibility with CentOS +/bin/date +%Y%m%d_%H%M > /etc/BUILDTIME + +# Change format of the RPM database from Berkeley DB to a new SQLite format +rpmdb --rebuilddb + +# set DNF infra variable to container for compatibility with CentOS +echo 'container' > /etc/dnf/vars/infra + +# import MSVSphere PGP key +rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-MSVSphere-9 + +# install only C.UTF-8 locale files, see +# https://fedoraproject.org/wiki/Changes/Glibc_locale_subpackaging for details +LANG="C.utf8" +echo "%_install_langs $LANG" > /etc/rpm/macros.image-language-conf + +# https://bugzilla.redhat.com/show_bug.cgi?id=1727489 +echo 'LANG="C.UTF-8"' > /etc/locale.conf + +# force each container to have a unique machine-id +> /etc/machine-id + +# create tmp directories because there is no tmpfs support in Docker +umount /run +systemd-tmpfiles --create --boot + +# disable login prompt, mounts and fix: https://bugzilla.redhat.com/show_bug.cgi?id=1472439 +systemctl mask systemd-remount-fs.service \ + dev-hugepages.mount \ + sys-fs-fuse-connections.mount \ + systemd-logind.service \ + getty.target \ + console-getty.service + +KEEPLANG=en_US +for dir in locale i18n; do + find /usr/share/${dir} -mindepth 1 -maxdepth 1 -type d -not \( -name "${KEEPLANG}" -o -name POSIX \) -exec rm -rfv {} + +done + +# remove unnecessary files +rm -f /var/lib/dnf \ + /run/nologin +rm -fr /var/log/* \ + /tmp/* /tmp/.* \ + /boot || true +%end