From 537320a32d6e255af436074b7ca3ba8aa6ad411b Mon Sep 17 00:00:00 2001 From: "arthur.barr@uk.ibm.com" Date: Tue, 24 Jan 2023 16:54:58 +0000 Subject: [PATCH] Use build context instead of network during build The use of networks in the build process means that Podman cannot be used in rootless mode. This commit changes the build to use standard podman/docker build context. This makes the build simpler, but does introduce a pause at the beginning of the build, while the context is uploaded. This pause is reduced by dynamically creating the .dockerignore file, to prevent unnecessary large files from being uploaded. --- .dockerignore | 2 - .gitignore | 1 + Dockerfile-server | 68 ++++++++++++++++++++++----------- Makefile | 62 +++--------------------------- docs/building.md | 4 +- install-mq.sh => setup-image.sh | 39 +------------------ 6 files changed, 56 insertions(+), 120 deletions(-) delete mode 100644 .dockerignore rename install-mq.sh => setup-image.sh (73%) diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index d1824c6..0000000 --- a/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -downloads -.git \ No newline at end of file diff --git a/.gitignore b/.gitignore index 01381c3..3bf5454 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.dockerignore .DS_Store .vscode test/docker/coverage diff --git a/Dockerfile-server b/Dockerfile-server index dfa80f7..f14225d 100644 --- a/Dockerfile-server +++ b/Dockerfile-server @@ -1,4 +1,4 @@ -# © Copyright IBM Corporation 2015, 2022 +# © Copyright IBM Corporation 2015, 2023 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,33 +17,28 @@ ARG BASE_TAG=8.7-1031 ARG BUILDER_IMAGE=registry.access.redhat.com/ubi8/go-toolset ARG BUILDER_TAG=1.17.12-11 ARG GO_WORKDIR=/opt/app-root/src/go/src/github.com/ibm-messaging/mq-container -ARG MQ_URL="https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/9.3.2.0-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz" +ARG MQ_ARCHIVE="downloads/9.3.2.0-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz" + ############################################################################### # Build stage to build Go code ############################################################################### FROM $BUILDER_IMAGE:$BUILDER_TAG as builder -# The URL to download the MQ installer from in tar.gz format -# This assumes an archive containing the MQ Non-Install packages -ARG MQ_URL ARG IMAGE_REVISION="Not specified" ARG IMAGE_SOURCE="Not specified" ARG IMAGE_TAG="Not specified" ARG GO_WORKDIR +ARG MQ_ARCHIVE USER 0 -WORKDIR /opt/mqm -# Download and extract MQ files, to get the MQ client needed to compile. -# Only extract certain MQ files to make the build quicker -RUN curl --fail --location $MQ_URL | tar --extract --gunzip \ - && chown -R 1001:root /opt/mqm/* WORKDIR $GO_WORKDIR/ +ADD $MQ_ARCHIVE /opt/mqm +ENV CGO_CFLAGS="-I/opt/mqm/inc/" \ + CGO_LDFLAGS_ALLOW="-Wl,-rpath.*" \ + PATH="${PATH}:/opt/mqm/bin" COPY go.mod go.sum ./ COPY cmd/ ./cmd COPY internal/ ./internal COPY pkg/ ./pkg COPY vendor/ ./vendor -ENV CGO_CFLAGS="-I/opt/mqm/inc/" \ - CGO_LDFLAGS_ALLOW="-Wl,-rpath.*" \ - PATH="${PATH}:/opt/mqm/bin" RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \"main.ImageRevision=$IMAGE_REVISION\" -X \"main.ImageSource=$IMAGE_SOURCE\" -X \"main.ImageTag=$IMAGE_TAG\"" ./cmd/runmqserver/ \ && go build ./cmd/chkmqready/ \ && go build ./cmd/chkmqhealthy/ \ @@ -58,11 +53,44 @@ RUN go build -ldflags "-X \"main.ImageCreated=$(date --iso-8601=seconds)\" -X \" && go test -v ./internal/... \ && go vet ./cmd/... ./internal/... +############################################################################### +# Build stage to reduce MQ packages included using genmqpkg +############################################################################### +FROM $BASE_IMAGE:$BASE_TAG AS mq-redux +ARG BASE_IMAGE +ARG BASE_TAG +ARG MQ_ARCHIVE +WORKDIR /tmp/mq +ENV genmqpkg_inc32=0 \ + genmqpkg_incadm=1 \ + genmqpkg_incamqp=0 \ + genmqpkg_incams=1 \ + genmqpkg_inccbl=0 \ + genmqpkg_inccics=0 \ + genmqpkg_inccpp=0 \ + genmqpkg_incdnet=0 \ + genmqpkg_incjava=1 \ + genmqpkg_incjre=1 \ + genmqpkg_incman=0 \ + genmqpkg_incmqbc=0 \ + genmqpkg_incmqft=0 \ + genmqpkg_incmqsf=0 \ + genmqpkg_incmqxr=0 \ + genmqpkg_incnls=1 \ + genmqpkg_incras=1 \ + genmqpkg_incsamp=1 \ + genmqpkg_incsdk=0 \ + genmqpkg_inctls=1 \ + genmqpkg_incunthrd=0 \ + genmqpkg_incweb=1 +ADD $MQ_ARCHIVE /opt/mqm-noinstall +# Run genmqpkg to reduce the MQ packages included +RUN /opt/mqm-noinstall/bin/genmqpkg.sh -b /opt/mqm-redux + ############################################################################### # Main build stage, to build MQ image ############################################################################### FROM $BASE_IMAGE:$BASE_TAG AS mq-server -# The MQ packages to install - see install-mq.sh for default value ARG MQ_URL ARG BASE_IMAGE ARG BASE_TAG @@ -79,15 +107,14 @@ LABEL summary="IBM MQ Advanced Server" \ io.k8s.description="Simplify, accelerate and facilitate the reliable exchange of data with a security-rich messaging solution — trusted by the world’s most successful enterprises" \ base-image=$BASE_IMAGE \ base-image-release=$BASE_TAG -COPY install-mq.sh /usr/local/bin/ +COPY --from=mq-redux /opt/mqm-redux/ /opt/mqm/ +COPY setup-image.sh /usr/local/bin/ COPY install-mq-server-prereqs.sh /usr/local/bin/ -# Install MQ. To avoid a "text file busy" error here, we sleep before installing. RUN env \ - && mkdir /opt/mqm \ && chmod u+x /usr/local/bin/install-*.sh \ - && sleep 1 \ + && chmod u+x /usr/local/bin/setup-image.sh \ && install-mq-server-prereqs.sh \ - && install-mq.sh \ + && setup-image.sh \ && /opt/mqm/bin/security/amqpamcf \ && chown -R 1001:root /opt/mqm/* COPY --from=builder $GO_WORKDIR/runmqserver /usr/local/bin/ @@ -121,9 +148,6 @@ ENTRYPOINT ["runmqserver"] ############################################################################### # Use the Go toolset image, which already includes gcc and the MQ SDK FROM builder as cbuilder -# The URL to download the MQ installer from in tar.gz format -# This assumes an archive containing the MQ Non-Install packages -ARG MQ_URL USER 0 # Install the Apache Portable Runtime code (used for htpasswd hash checking) RUN yum --assumeyes --disableplugin=subscription-manager install apr-devel apr-util-openssl apr-util-devel diff --git a/Makefile b/Makefile index fbe42b8..67d4cc3 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# © Copyright IBM Corporation 2017, 2022 +# © Copyright IBM Corporation 2017, 2023 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -75,8 +75,6 @@ VOLUME_MOUNT_OPTIONS ?= :Z ############################################################################### # Other variables ############################################################################### -# Build doesn't work if BuildKit is enabled -DOCKER_BUILDKIT=0 # Lock Docker API version for compatibility with Podman and with the Docker version in Travis' Ubuntu Bionic DOCKER_API_VERSION=1.40 GO_PKG_DIRS = ./cmd ./internal ./test @@ -340,14 +338,16 @@ test-advancedserver-cover: test/docker/vendor coverage # Command to build the image # Args: imageName, imageTag, dockerfile, extraArgs, dockerfileTarget # If the ARCH variable has been changed from the default value (arch_go variable), then the `--platform` parameter is added -define build-mq-command +# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget +define build-mq + rm -f .dockerignore && echo ".git\ndownloads\n!downloads/$4" > .dockerignore $(COMMAND) build \ --tag $1:$2 \ --file $3 \ - $4 \ --build-arg IMAGE_REVISION="$(IMAGE_REVISION)" \ --build-arg IMAGE_SOURCE="$(IMAGE_SOURCE)" \ --build-arg IMAGE_TAG="$1:$2" \ + --build-arg MQ_ARCHIVE="downloads/$4" \ --label version=$(MQ_VERSION) \ --label name=$1 \ --label build-date=$(shell date +%Y-%m-%dT%H:%M:%S%z) \ @@ -362,57 +362,6 @@ define build-mq-command . endef -# Build using a separate container to host the MQ download files. -# To minimize the layers in the resulting image, the download files can't be part of the build context. -# The "docker build" command (and "podman build" on macOS) don't allow you to mount a directory into the build, so a -# separate container is used to host a web server. -# Note that for Podman, this means that you need to be using the "rootful" mode, because the rootless mode doesn't allow -# much control of networking, so the containers can't talk to each other. -define build-mq-using-web-server - $(COMMAND) network create $(BUILD_SERVER_NETWORK) - $(COMMAND) run \ - --rm \ - --name $(BUILD_SERVER_CONTAINER) \ - --network $(BUILD_SERVER_NETWORK) \ - --volume $(DOWNLOADS_DIR):/opt/app-root/src$(VOLUME_MOUNT_OPTIONS) \ - --detach \ - registry.access.redhat.com/ubi8/nginx-120 nginx -g "daemon off;" || ($(COMMAND) network rm $(BUILD_SERVER_NETWORK) && exit 1) - BUILD_SERVER_IP=$$($(COMMAND) inspect -f '{{ .NetworkSettings.Networks.$(BUILD_SERVER_NETWORK).IPAddress }}' $(BUILD_SERVER_CONTAINER)); \ - $(call build-mq-command,$1,$2,$3,--network build --build-arg MQ_URL=http://$$BUILD_SERVER_IP:8080/$4,$5) || ($(COMMAND) rm -f $(BUILD_SERVER_CONTAINER) && $(COMMAND) network rm $(BUILD_SERVER_NETWORK) && exit 1) - $(COMMAND) rm -f $(BUILD_SERVER_CONTAINER) - $(COMMAND) network rm $(BUILD_SERVER_NETWORK) -endef - -# When building with Docker, always use the web server build because you can't use bind-mounted volumes. -# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget -define build-mq-docker - $(call build-mq-using-web-server,$1,$2,$3,$4,$5) -endef - -# When building with Podman on macOS (Darwin), use the web server build because you can't use bind-mounted volumes with `podman build` on macOS -# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget -define build-mq-podman-Darwin - $(call build-mq-using-web-server,$1,$2,$3,$4,$5) -endef - -# When building with Podman on Linux, just pass the downloads directory as a volume -# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget -define build-mq-podman-Linux - $(call build-mq-command,$1,$2,$3,--volume $(DOWNLOADS_DIR):/var/downloads$(VOLUME_MOUNT_OPTIONS) --build-arg MQ_URL=file:///var/downloads/$4,$5) -endef - -# When building with Podman, just pass the downloads directory as a volume -# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget -define build-mq-podman - $(call build-mq-podman-$(shell uname -s),$1,$2,$3,$4,$5) -endef - -# Build an MQ image. The commands used are slightly different between Docker and Podman -# Args: imageName, imageTag, dockerfile, mqArchive, dockerfileTarget -define build-mq - $(call build-mq-$(COMMAND),$1,$2,$3,$4,$5) -endef - ############################################################################### # Build targets ############################################################################### @@ -610,7 +559,6 @@ fi ;\ .PHONY: update-release-information update-release-information: - sed -i.bak 's/ARG MQ_URL=.*-LinuxX64.tar.gz"/ARG MQ_URL="https:\/\/public.dhe.ibm.com\/ibmdl\/export\/pub\/software\/websphere\/messaging\/mqadv\/$(MQ_VERSION)-IBM-MQ-Advanced-for-Developers-Non-Install-LinuxX64.tar.gz"/g' Dockerfile-server && rm Dockerfile-server.bak $(eval MQ_VERSION_1=$(shell echo '${MQ_VERSION}' | rev | cut -c 3- | rev)) sed -i.bak 's/IBM_MQ_.*_LINUX_X86-64_NOINST.tar.gz/IBM_MQ_${MQ_VERSION_1}_LINUX_X86-64_NOINST.tar.gz/g' docs/building.md && rm docs/building.md.bak sed -i.bak 's/ibm-mqadvanced-server:.*-amd64/ibm-mqadvanced-server:$(MQ_VERSION)-amd64/g' docs/security.md diff --git a/docs/building.md b/docs/building.md index b462a11..b098c8c 100755 --- a/docs/building.md +++ b/docs/building.md @@ -4,7 +4,7 @@ You need to have the following tools installed: -* [Docker](https://www.docker.com/) 17.06.1 or later, or [Podman](https://podman.io) 1.0 or later (Podman 4.1 on macOS). If using Podman on macOS, the you need to be in "rootful" mode to allow the use of a network during builds. Run `podman machine init --rootful`. +* [Docker](https://www.docker.com/) 17.06.1 or later, or [Podman](https://podman.io) 1.0 or later (Podman 4.1 on macOS). * [GNU make](https://www.gnu.org/software/make/) If you are working in the Windows Subsystem for Linux, follow [this guide by Microsoft to set up Docker](https://blogs.msdn.microsoft.com/commandline/2017/12/08/cross-post-wsl-interoperability-with-docker/) first. @@ -44,4 +44,4 @@ You can use the environment variable `MQ_ARCHIVE_DEV` to specify an alternative ## Installed components -This image includes the core MQ server, Java, language packs, GSKit, and web server. This is configured in the `Generate MQ package in INSTALLATION_DIR` section [here](../install-mq.sh), with the configured options being picked up at build time. +This image includes the core MQ server, Java, language packs, GSKit, and web server. This is configured in the `mq-redux` build stage in `Dockerfile-server`. diff --git a/install-mq.sh b/setup-image.sh similarity index 73% rename from install-mq.sh rename to setup-image.sh index eb6af92..f565b81 100644 --- a/install-mq.sh +++ b/setup-image.sh @@ -1,6 +1,6 @@ #!/bin/bash # -*- mode: sh -*- -# © Copyright IBM Corporation 2015, 2022 +# © Copyright IBM Corporation 2015, 2023 # # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,43 +21,8 @@ set -ex test -f /usr/bin/rpm && RPM=true || RPM=false test -f /usr/bin/apt-get && UBUNTU=true || UBUNTU=false -# Download and extract the MQ unzippable server -DIR_TMP=/tmp/mq -mkdir -p ${DIR_TMP} -cd ${DIR_TMP} -curl --fail --location $MQ_URL | tar --extract --gunzip -ls -la ${DIR_TMP} - -# Generate MQ package in INSTALLATION_DIR -export genmqpkg_inc32=0 -export genmqpkg_incadm=1 -export genmqpkg_incamqp=0 -export genmqpkg_incams=1 -export genmqpkg_inccbl=0 -export genmqpkg_inccics=0 -export genmqpkg_inccpp=0 -export genmqpkg_incdnet=0 -export genmqpkg_incjava=1 -export genmqpkg_incjre=1 -export genmqpkg_incman=0 -export genmqpkg_incmqbc=0 -export genmqpkg_incmqft=0 -export genmqpkg_incmqsf=0 -export genmqpkg_incmqxr=0 -export genmqpkg_incnls=1 -export genmqpkg_incras=1 -export genmqpkg_incsamp=1 -export genmqpkg_incsdk=0 -export genmqpkg_inctls=1 -export genmqpkg_incunthrd=0 -export genmqpkg_incweb=1 -export INSTALLATION_DIR=/opt/mqm -${DIR_TMP}/bin/genmqpkg.sh -b ${INSTALLATION_DIR} -ls -la ${INSTALLATION_DIR} -rm -rf ${DIR_TMP} - # Accept the MQ license -${INSTALLATION_DIR}/bin/mqlicense -accept +/opt/mqm/bin/mqlicense -accept # Optional: Update the command prompt with the MQ version $UBUNTU && echo "mq:$(dspmqver -b -f 2)" > /etc/debian_chroot