diff --git a/build.assets/Dockerfile b/build.assets/Dockerfile index 3ea95530efde6..4ab637440417c 100644 --- a/build.assets/Dockerfile +++ b/build.assets/Dockerfile @@ -7,6 +7,12 @@ # teleport built on any newer Ubuntu version will not run on Centos 7 because # of this. +# GRPC_NODE_PLUGIN_BINARY_TYPE has to be defined above the first FROM as it's +# used in another FROM instruction. See the comment for grpc_node_plugin image +# for more details. +# Valid values are "prebuilt" and "compiled". +ARG GRPC_NODE_PLUGIN_BINARY_TYPE + ## LIBFIDO2 ################################################################### # Build libfido2 separately for isolation, speed and flexibility. @@ -50,6 +56,33 @@ RUN git clone --depth=1 https://github.com/Yubico/libfido2.git -b 1.12.0 && \ make install && \ make clean +## GRPC_NODE_PLUGIN ########################################################### + +# grpc_node_plugin is built only on arm64. +# +# To generate JS protofiles, we need the grpc-tools npm package. Unfortunately, +# it doesn't ship with a prebuilt grpc_node_plugin binary for Linux arm64. [1] +# +# We have to build it from source. Cloning all submodules takes a lot of time +# and bandwith so we build the binary in a separate image. +# +# [1] https://github.com/grpc/grpc-node/issues/1405#issuecomment-1282201879 + +FROM buildpack-deps:18.04 AS grpc_node_plugin +RUN apt-get update && \ + apt-get install -y --no-install-recommends cmake +COPY teleterm_linux_arm64.toolchain.cmake ./linux_arm64.toolchain.cmake +RUN git clone --depth=1 --branch=grpc-tools@1.11.2 https://github.com/grpc/grpc-node.git && \ + mv linux_arm64.toolchain.cmake grpc-node/packages/grpc-tools/. && \ + cd grpc-node && \ + git submodule update --init --recursive && \ + cd packages/grpc-tools && \ + cmake -DCMAKE_TOOLCHAIN_FILE=linux_arm64.toolchain.cmake . && \ + cmake --build . --target clean && cmake --build . --target grpc_node_plugin -- -j 12 && \ + mv grpc_node_plugin ../../../. && \ + cd ../../.. && \ + rm -rf grpc-node + ## BUILDBOX ################################################################### # # Image layers are ordered according to how slow that layer takes to build and @@ -119,6 +152,8 @@ RUN apt-get -y update && \ python3-setuptools \ python3-wheel \ pkg-config \ + # Used during tag builds to build the RPM package of Connect. + rpm \ shellcheck \ softhsm2 \ sudo \ @@ -173,16 +208,16 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --pr # user. USER root -# Install Nodejs +# Install Node.js ARG NODE_VERSION ENV NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${BUILDARCH}.tar.xz" ENV NODE_PATH="/usr/local/lib/nodejs-linux" ENV PATH="$PATH:${NODE_PATH}/bin" RUN export NODE_ARCH=$(if [ "$BUILDARCH" = "amd64" ]; then echo "x64"; else echo "arm64"; fi) && \ - export NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" && \ - mkdir -p ${NODE_PATH} && \ - curl -o /tmp/nodejs.tar.xz -L ${NODE_URL} && \ - tar -xJf /tmp/nodejs.tar.xz -C /usr/local/lib/nodejs-linux --strip-components=1 + export NODE_URL="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" && \ + mkdir -p ${NODE_PATH} && \ + curl -o /tmp/nodejs.tar.xz -L ${NODE_URL} && \ + tar -xJf /tmp/nodejs.tar.xz -C /usr/local/lib/nodejs-linux --strip-components=1 RUN corepack enable yarn # Install Go. @@ -240,6 +275,8 @@ RUN (git clone https://github.com/gogo/protobuf.git ${GOPATH}/src/github.com/gog git reset --hard ${GOGO_PROTO_TAG} && \ make install) ENV PROTO_INCLUDE "/usr/local/include":"/go/src":"/go/src/github.com/gogo/protobuf/protobuf":"${GOGOPROTO_ROOT}":"${GOGOPROTO_ROOT}/protobuf" +# Install protoc-gen-go for lib/teleterm as #17267 and #17302 were not backported to v10. +RUN go install github.com/golang/protobuf/protoc-gen-go@v1.4.3 # Install addlicense. RUN go install github.com/google/addlicense@v1.0.0 @@ -261,7 +298,7 @@ RUN BIN="/usr/local/bin" && \ chmod +x "${BIN}/buf" # Copy libfido2 libraries. -# Do this last to take better advantage of the multi-stage build. +# Do this near the end to take better advantage of the multi-stage build. COPY --from=libfido2 /usr/local/include/ /usr/local/include/ COPY --from=libfido2 /usr/local/lib/pkgconfig/ /usr/local/lib/pkgconfig/ COPY --from=libfido2 \ @@ -276,5 +313,22 @@ RUN cd /usr/local/lib && \ ldconfig COPY pkgconfig/buildbox/ / +# Install JS gRPC tools +RUN (npm install --global grpc_tools_node_protoc_ts@5.0.1) + +FROM buildbox AS grpc_node_plugin_binary_prebuilt +ONBUILD RUN (npm install --global grpc-tools@1.11.2) + +FROM buildbox AS grpc_node_plugin_binary_compiled +COPY --from=grpc_node_plugin grpc_node_plugin ./grpc_node_plugin +ONBUILD RUN npm install --global --ignore-scripts grpc-tools@1.11.2 && \ + mv grpc_node_plugin $(npm root -g)/grpc-tools/bin/. && \ + # grpc-tools needs protoc but we already install it a couple of steps above. + ln -s $(which protoc) $(npm root -g)/grpc-tools/bin/protoc + +# A "conditional" FROM like this breaks up the number of steps in the progress bar of the given +# image, so let's use it at the end. This way the progress bar for buildbox stays mostly untouched. +FROM grpc_node_plugin_binary_${GRPC_NODE_PLUGIN_BINARY_TYPE} as buildbox + VOLUME ["/go/src/github.com/gravitational/teleport"] EXPOSE 6600 2379 2380 diff --git a/build.assets/Makefile b/build.assets/Makefile index ce9383b340261..26a95b7db7621 100644 --- a/build.assets/Makefile +++ b/build.assets/Makefile @@ -127,6 +127,7 @@ buildbox: --build-arg GOLANG_VERSION=$(GOLANG_VERSION) \ --build-arg RUST_VERSION=$(RUST_VERSION) \ --build-arg NODE_VERSION=$(NODE_VERSION) \ + --build-arg GRPC_NODE_PLUGIN_BINARY_TYPE=$(GRPC_NODE_PLUGIN_BINARY_TYPE) \ --build-arg PROTOC_VER=$(PROTOC_VER) \ --build-arg GOGO_PROTO_TAG=$(GOGO_PROTO_TAG) \ --build-arg LIBBPF_VERSION=$(LIBBPF_VERSION) \ @@ -214,33 +215,17 @@ buildbox-arm-fips: buildbox-fips --cache-from $(BUILDBOX_ARM_FIPS) \ --tag $(BUILDBOX_ARM_FIPS) -f Dockerfile-arm-fips . -# -# Builds a Docker buildbox which has tools needed to install grpc-tools npm package on arm64. -# See the `grpc-teleterm` target in the main Makefile for more details. -# -.PHONY:buildbox-teleterm -buildbox-teleterm: buildbox - @if [[ $${DRONE} == "true" ]] && ! docker inspect --type=image $(BUILDBOX_TELETERM) 2>&1 >/dev/null; then docker pull $(BUILDBOX_TELETERM) || true; fi; - docker build \ - --build-arg BUILDBOX_VERSION=$(BUILDBOX_VERSION) \ - --build-arg NODE_VERSION=$(NODE_VERSION) \ - --build-arg BUILDARCH=$(RUNTIME_ARCH) \ - --build-arg GRPC_NODE_PLUGIN_BINARY_TYPE=$(GRPC_NODE_PLUGIN_BINARY_TYPE) \ - --cache-from $(BUILDBOX) \ - --cache-from $(BUILDBOX_TELETERM) \ - --tag $(BUILDBOX_TELETERM) -f Dockerfile-teleterm . - CONNECT_VERSION ?= $(VERSION) ifeq ($(CONNECT_VERSION),) CONNECT_VERSION := $(BUILDBOX_VERSION)-dev endif # -# Builds Teleport Connect inside the buildbox-teleterm container. +# Builds Teleport Connect inside the buildbox container. # .PHONY:teleterm -teleterm: buildbox-teleterm - docker run $(DOCKERFLAGS) $(NOROOT) $(BUILDBOX_TELETERM) \ +teleterm: buildbox + docker run $(DOCKERFLAGS) $(NOROOT) $(BUILDBOX) \ bash -c "cd $(SRCDIR) && export CONNECT_TSH_BIN_PATH=\$$PWD/../teleport/build/tsh && yarn install --frozen-lockfile && yarn build-term && yarn package-term -c.extraMetadata.version=$(CONNECT_VERSION)" # Builds webassets inside Docker. @@ -253,16 +238,9 @@ ui: buildbox .PHONY: grpc grpc: buildbox docker run \ - $(DOCKERFLAGS) -e CLANG_FORMAT=/usr/bin/clang-format-10 -t $(BUILDBOX) \ + $(DOCKERFLAGS) -t $(BUILDBOX) \ make -C /go/src/github.com/gravitational/teleport grpc/host -# grpc-teleterm generates GRPC stubs for Teleterm from inside buildbox-teleterm -.PHONY: grpc-teleterm -grpc-teleterm: buildbox-teleterm - docker run \ - $(DOCKERFLAGS) -e CLANG_FORMAT=/usr/bin/clang-format-10 -t $(BUILDBOX_TELETERM) \ - make -C /go/src/github.com/gravitational/teleport grpc-teleterm/host - # protos-up-to-date checks if GRPC stubs are up to date from inside the buildbox .PHONY: protos-up-to-date protos-up-to-date: buildbox @@ -381,14 +359,6 @@ enter/centos7: buildbox docker run $(DOCKERFLAGS) -ti $(NOROOT) \ -e HOME=$(SRCDIR)/build.assets -w $(SRCDIR) $(BUILDBOX_CENTOS7) /bin/bash -# -# Starts shell inside the teleterm container -# -.PHONY:enter/teleterm -enter/teleterm: buildbox-teleterm - docker run $(DOCKERFLAGS) -ti $(NOROOT) \ - -e HOME=$(SRCDIR)/build.assets -w $(SRCDIR) $(BUILDBOX_TELETERM) /bin/bash - # # Create a Teleport package using the build container. # Don't use this target directly; call named Makefile targets like release-amd64.