From 35164951e21ebbb053df798fbdb4438017c71d23 Mon Sep 17 00:00:00 2001 From: Zaiming Shi Date: Tue, 16 Nov 2021 23:18:30 +0100 Subject: [PATCH] feat(docker): add flexible docker build The defulat docker build (e.g. make emqx-docker) is based on alpine image and it builds EMQ X from source code. This is not flexible enough when we want to quickly run some tests in a docker container. The new docker build (e.g. make emqx-docker-testing) by default takes the built zip package, and extract it in a very primitive base image such as ubuntu:20.04 and centos:8 --- Makefile | 15 +++++++- build | 62 ++++++++++++++++++++++++++------ deploy/docker/Dockerfile.testing | 43 ++++++++++++++++++++++ 3 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 deploy/docker/Dockerfile.testing diff --git a/Makefile b/Makefile index 4b15adfc7..1f8f17bbd 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ export OTP_VSN ?= $(shell $(CURDIR)/scripts/get-otp-vsn.sh) export PKG_VSN ?= $(shell $(CURDIR)/pkg-vsn.sh) export EMQX_DESC ?= EMQ X export EMQX_CE_DASHBOARD_VERSION ?= v4.3.3 -export DOCKERFILE=deploy/docker/Dockerfile +export DOCKERFILE := deploy/docker/Dockerfile +export DOCKERFILE_TESTING := deploy/docker/Dockerfile.testing ifeq ($(OS),Windows_NT) export REBAR_COLOR=none endif @@ -155,6 +156,18 @@ endef ALL_ZIPS = $(REL_PROFILES) $(foreach zt,$(ALL_ZIPS),$(eval $(call gen-docker-target,$(zt)))) +## emqx-docker-testing +## emqx-ee-docker-testing +## is to directly copy a unzipped zip-package to a +## base image such as ubuntu20.04. Mostly for testing +.PHONY: $(REL_PROFILES:%=%-docker-testing) +define gen-docker-target-testing +$1-docker-testing: $(COMMON_DEPS) + @$(BUILD) $1 docker-testing +endef +ALL_ZIPS = $(REL_PROFILES) +$(foreach zt,$(ALL_ZIPS),$(eval $(call gen-docker-target-testing,$(zt)))) + .PHONY: run run: $(PROFILE) quickrun diff --git a/build b/build index 9375dfc8c..50997f76c 100755 --- a/build +++ b/build @@ -124,26 +124,63 @@ make_zip() { (cd "${tard}" && zip -qr - emqx) > "${zipball}" } +## This function builds the default docker image based on alpine:3.14 (by default) make_docker() { - EMQX_RUNNER_IMAGE='alpine:3.14' - EMQX_RUNNER_IMAGE_COMPACT="$(echo $EMQX_RUNNER_IMAGE | tr -d ':')" + EMQX_RUNNER_IMAGE="${EMQX_RUNNER_IMAGE:-alpine:3.14}" + EMQX_RUNNER_IMAGE_COMPACT="$(echo "$EMQX_RUNNER_IMAGE" | tr -d ':')" EMQX_BUILDER="${EMQX_BUILDER:-ghcr.io/emqx/emqx-builder/4.4-2:${OTP_VSN}-${EMQX_RUNNER_IMAGE_COMPACT}}" - - ## Build Docker image - echo "DOCKER BUILD: Build Docker image." - echo "DOCKER BUILD: docker repo -> emqx/$PROFILE " - echo "DOCKER BUILD: build version -> $PKG_VSN." - echo "DOCKER BUILD: build from -> $EMQX_BUILDER." - echo "DOCKER BUILD: runner from -> $EMQX_RUNNER_IMAGE." - + set -x docker build --no-cache --pull \ --build-arg BUILD_FROM="${EMQX_BUILDER}" \ --build-arg RUN_FROM="${EMQX_RUNNER_IMAGE}" \ --build-arg EMQX_NAME="$PROFILE" \ - --tag "emqx/$PROFILE:$PKG_VSN" \ + --tag "emqx/$PROFILE:${PKG_VSN}" \ -f "${DOCKERFILE}" . } +## This function accepts any base docker image, +## a emqx zip-image, and a image tag (for the image to be built), +## to build a docker image which runs EMQ X +## +## Export below variables to quickly build an image +## +## Name Default Example +## --------------------------------------------------------------------- +## EMQX_BASE_IMAGE current os centos:7 +## EMQX_ZIP_PACKAGE _packages/ /tmp/emqx-4.4.0-otp23.3.4.9-3-centos7-amd64.zip +## EMQX_IMAGE_TAG emqx/emqx: emqx/emqx:testing-tag +## +make_docker_testing() { + if [ -z "${EMQX_BASE_IMAGE:-}" ]; then + case "$SYSTEM" in + ubuntu20*) + EMQX_BASE_IMAGE="ubuntu:20.04" + ;; + centos8) + EMQX_BASE_IMAGE="centos:8" + ;; + *) + echo "Unsupported testing base image for $SYSTEM" + exit 1 + ;; + esac + fi + EMQX_IMAGE_TAG="${EMQX_IMAGE_TAG:-emqx/$PROFILE:${PKG_VSN}-otp${OTP_VSN}-${SYSTEM}}" + local defaultzip + defaultzip="_packages/${PROFILE}/${PROFILE}-${PKG_VSN}-otp${OTP_VSN}-${SYSTEM}-${ARCH}.zip" + local zip="${EMQX_ZIP_PACKAGE:-$defaultzip}" + if [ ! -f "$zip" ]; then + log "ERROR: $zip not built?" + exit 1 + fi + set -x + docker build \ + --build-arg BUILD_FROM="${EMQX_BASE_IMAGE}" \ + --build-arg EMQX_ZIP_PACKAGE="${zip}" \ + --tag "$EMQX_IMAGE_TAG" \ + -f "${DOCKERFILE_TESTING}" . +} + log "building artifact=$ARTIFACT for profile=$PROFILE" case "$ARTIFACT" in @@ -167,6 +204,9 @@ case "$ARTIFACT" in docker) make_docker ;; + docker-testing) + make_docker_testing + ;; *) log "Unknown artifact $ARTIFACT" exit 1 diff --git a/deploy/docker/Dockerfile.testing b/deploy/docker/Dockerfile.testing new file mode 100644 index 000000000..02490272d --- /dev/null +++ b/deploy/docker/Dockerfile.testing @@ -0,0 +1,43 @@ +ARG BUILD_FROM +FROM ${BUILD_FROM} + +## all we need is the unzip command +RUN if command -v yum; then yum update -y && yum install -y unzip; fi +RUN if command -v apt-get; then apt-get update -y && apt-get install unzip; fi + +ARG EMQX_ZIP_PACKAGE +COPY ${EMQX_ZIP_PACKAGE} /opt/emqx.zip +RUN unzip -q /opt/emqx.zip -d /opt/ && rm /opt/emqx.zip + +COPY deploy/docker/docker-entrypoint.sh /usr/bin/ +RUN ln -s /opt/emqx/bin/* /usr/local/bin/ + +WORKDIR /opt/emqx + +RUN adduser -u 1000 emqx +RUN echo "emqx ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers + +RUN chgrp -Rf emqx /opt/emqx && chmod -Rf g+w /opt/emqx \ + && chown -Rf emqx /opt/emqx + +USER emqx + +VOLUME ["/opt/emqx/log", "/opt/emqx/data", "/opt/emqx/etc"] + +# emqx will occupy these port: +# - 1883 port for MQTT +# - 8081 for mgmt API +# - 8083 for WebSocket/HTTP +# - 8084 for WSS/HTTPS +# - 8883 port for MQTT(SSL) +# - 11883 port for internal MQTT/TCP +# - 18083 for dashboard +# - 4369 epmd (Erlang-distrbution port mapper daemon) listener (deprecated) +# - 4370 default Erlang distrbution port +# - 5369 for gen_rpc port mapping +# - 6369 6370 for distributed node +EXPOSE 1883 8081 8083 8084 8883 11883 18083 4369 4370 5369 6369 6370 + +ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] + +CMD ["/opt/emqx/bin/emqx", "foreground"]