# # Copyright (c) 2023 Red Hat, Inc. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # To transform into Brew-friendly Dockerfile: # 1. comment out lines with EXTERNAL_SOURCE=. and CONTAINER_SOURCE=/opt/app-root/src # 2. uncomment lines with EXTERNAL_SOURCE and CONTAINER_SOURCE pointing at $REMOTE_SOURCES and $REMOTE_SOURCES_DIR instead (Brew defines these paths) # 3. uncomment lines with RUN source .../cachito.env # 4. add Brew metadata # Stage 1 - Build nodejs skeleton #@follow_tag(registry.access.redhat.com/ubi9/nodejs-18:1) FROM registry.access.redhat.com/ubi9/nodejs-18:1-98 AS build # hadolint ignore=DL3002 USER 0 # Install isolated-vm dependencies # hadolint ignore=DL3041 RUN dnf install -y -q --allowerasing --nobest nodejs-devel nodejs-libs \ # already installed or installed as deps: openssl openssl-devel ca-certificates make cmake cpp gcc gcc-c++ zlib zlib-devel brotli brotli-devel python3 nodejs-packaging && \ dnf update -y && dnf clean all # Downstream sources ENV EXTERNAL_SOURCE=$REMOTE_SOURCES/upstream1/app ENV EXTERNAL_SOURCE_NESTED=$EXTERNAL_SOURCE/distgit/containers/rhdh-hub # /remote-source/ ENV CONTAINER_SOURCE=$REMOTE_SOURCES_DIR # Env vars ENV YARN=$CONTAINER_SOURCE/.yarn/releases/yarn-1.22.19.cjs WORKDIR $CONTAINER_SOURCE/ COPY $EXTERNAL_SOURCE_NESTED/.yarn ./.yarn COPY $EXTERNAL_SOURCE_NESTED/.yarnrc.yml ./ RUN chmod +x $YARN # Stage 2 - Install dependencies COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins/ ./dynamic-plugins/ COPY $EXTERNAL_SOURCE_NESTED/package.json $EXTERNAL_SOURCE_NESTED/yarn.lock ./ COPY $EXTERNAL_SOURCE_NESTED/packages/app/package.json ./packages/app/package.json COPY $EXTERNAL_SOURCE_NESTED/packages/backend/package.json ./packages/backend/package.json COPY $EXTERNAL_SOURCE_NESTED/plugins/scalprum-backend/package.json ./plugins/scalprum-backend/package.json COPY $EXTERNAL_SOURCE_NESTED/plugins/dynamic-plugins-info-backend/package.json ./plugins/dynamic-plugins-info-backend/package.json COPY $EXTERNAL_SOURCE_NESTED/plugins/auth-backend-module-oidc-provider/package.json ./plugins/auth-backend-module-oidc-provider/package.json # Downstream only - debugging # COPY $REMOTE_SOURCES/ ./ # hadolint ignore=SC2086 # RUN for d in $(find / -name ".npmrc" -o -name ".yarnrc" 2>/dev/null); do echo; echo "==== $d ===="; cat $d; done # # ls -la ./ upstream1 upstream1/app/ upstream1/app/distgit/containers/ upstream1/app/distgit/containers/rhdh-hub/ || true # # debug contents of /remote-source/ # echo "###### /tmp/tls-ca-bundle.pem ######>>"; cat /tmp/tls-ca-bundle.pem; echo "<<###### /tmp/tls-ca-bundle.pem ######" # echo "###### $CONTAINER_SOURCE/registry-ca.pem ######>>"; cat $CONTAINER_SOURCE/registry-ca.pem; echo "<<###### $CONTAINER_SOURCE/registry-ca.pem ######" # Downstream only - Cachito configuration # see https://docs.engineering.redhat.com/pages/viewpage.action?pageId=228017926#UpstreamSources(Cachito,ContainerFirst)-CachitoIntegrationfornpm COPY $REMOTE_SOURCES/upstream1/cachito.env \ $REMOTE_SOURCES/upstream1/app/registry-ca.pem \ $REMOTE_SOURCES/upstream1/app/distgit/containers/rhdh-hub/.npmrc \ ./ # registry=https://cachito-nexus.engineering.redhat.com/repository/cachito-yarn-814335/ # email=noreply@domain.local # always-auth=true # //cachito-nexus.engineering.redhat.com/repository/cachito-yarn-814335/:_auth=SHA-goes-here== # fetch-retries=5 # fetch-retry-factor=2 # strict-ssl=true # cafile="../../../registry-ca.pem" # NOTE: this is overridden to "/remote-source/registry-ca.pem" below # hadolint ignore=SC1091,SC2046 RUN \ # debug # cat $CONTAINER_SOURCE/cachito.env; \ # load envs source $CONTAINER_SOURCE/cachito.env; \ \ # load cert cert_path=$CONTAINER_SOURCE/registry-ca.pem; \ # debug # ls -la "${cert_path}"; \ npm config set cafile "${cert_path}"; $YARN config set cafile "${cert_path}" -g; \ \ # set longer timeouts # npm config set fetch-retry-maxtimeout 6000000; \ # npm config set fetch-retry-mintimeout 1000000; \ $YARN config set network-timeout 600000 -g; \ # set cachito as default registry $YARN config set registry $(npm config get registry) -g; \ \ # debug # ls -l /usr/; \ # set up node dir with common.gypi and unsafe-perms=true ln -s /usr/include/node/common.gypi /usr/common.gypi; $YARN config set nodedir /usr; $YARN config set unsafe-perm true; \ \ # add yarn to path via symlink ln -s $CONTAINER_SOURCE/$YARN /usr/local/bin/yarn # Downstream only - debug # RUN echo $PATH; ls -la /usr/local/bin/yarn; whereis yarn;which yarn; yarn --version; \ # cat $CONTAINER_SOURCE/.npmrc || true; \ # $YARN config list --verbose; npm config list; npm config list -l RUN $YARN install --frozen-lockfile --network-timeout 600000 # Stage 3 - Build packages COPY $EXTERNAL_SOURCE_NESTED ./ RUN git config --global --add safe.directory ./ # Upstream only # RUN rm app-config.yaml && mv app-config.example.yaml app-config.yaml # hadolint ignore=DL3059,DL4006,SC2086 RUN $YARN build --filter=backend && \ # Build dynamic plugins: yarn.lock files need to be present in order to transform to point to cachito URLs $YARN --cwd ./dynamic-plugins/imports export-dynamic --no-install && \ # Downstream only - replace registry refs with cachito ones cachitoRegistry=$(npm config get registry); echo "cachito registry: $cachitoRegistry"; \ for d in $(find . -name yarn.lock); do echo; echo "===== $d ====="; \ sed -i $d -r -e "s#(https://registry.yarnpkg.com|https://registry.npmjs.org)#${cachitoRegistry}#g"; \ grep resolved $d | head -1; echo "Total $(grep resolved $d | wc -l) resolution lines in $d"; \ done; \ # Already imported the packages above; need to `yarn install` on the `dist-dynamic` sub-folder for backend plugins $YARN --cwd ./dynamic-plugins/imports install-dynamic && \ $YARN export-dynamic -- --filter=./dynamic-plugins/wrappers/* && \ $YARN copy-dynamic-plugins dist # Downstream only - debug # hadolint ignore=SC3010,DL4006 RUN echo "=== Check for yarn.lock files that don't use cachito registry ===>"; \ for d in $(find . -name yarn.lock); do \ found=$(grep -E "yarnpkg.com|npmjs.org" $d | head -1); \ if [[ $found ]]; then echo;echo "$d : $found"; fi; \ done; \ echo "<=== Check for yarn.lock files that don't use cachito registry ===" # Downstream only - clean up dynamic plugins sources: # Only keep the dist sub-folder in the dynamic-plugins folder RUN find dynamic-plugins -maxdepth 1 -mindepth 1 -type d -not -name dist -exec rm -Rf {} \; # Stage 4 - Build the actual backend image and install production dependencies # Downstream only - files already exist, nothing to copy; next line for debugging only # RUN ls -l $CONTAINER_SOURCE/ $CONTAINER_SOURCE/packages/backend/dist/ ENV TARBALL_PATH=./packages/backend/dist RUN tar xzf $TARBALL_PATH/skeleton.tar.gz; tar xzf $TARBALL_PATH/bundle.tar.gz; \ rm -f $TARBALL_PATH/skeleton.tar.gz $TARBALL_PATH/bundle.tar.gz # Copy app-config files needed in runtime # Upstream only # COPY $EXTERNAL_SOURCE_NESTED/app-config*.yaml ./ # COPY $EXTERNAL_SOURCE_NESTED/dynamic-plugins.default.yaml ./ # Install production dependencies # hadolint ignore=DL3059 RUN $YARN install --frozen-lockfile --production --network-timeout 600000 # Stage 5 - Build the runner image #@follow_tag(registry.access.redhat.com/ubi9/nodejs-18-minimal:1) FROM registry.access.redhat.com/ubi9/nodejs-18-minimal:1-103 AS runner USER 0 ENV CONTAINER_SOURCE=/opt/app-root/src WORKDIR $CONTAINER_SOURCE/ # Downstream only - install techdocs dependencies using cachito sources COPY $REMOTE_SOURCES/upstream2 $REMOTE_SOURCES_DIR/upstream2/ # hadolint ignore=DL3013,DL3041,SC2086 RUN microdnf update -y && \ microdnf install -y python3.11 python3.11-pip python3.11-devel make cmake cpp gcc gcc-c++; \ ln -s /usr/bin/pip3.11 /usr/bin/pip3; \ ln -s /usr/bin/pip3.11 /usr/bin/pip; \ # ls -la $REMOTE_SOURCES_DIR/ $REMOTE_SOURCES_DIR/upstream2/ $REMOTE_SOURCES_DIR/upstream2/app/distgit/containers/rhdh-hub/docker/ || true; \ # cat $REMOTE_SOURCES_DIR/upstream2/cachito.env && \ # cachito.env contains path to cert: # export PIP_CERT=/remote-source/upstream2/app/package-index-ca.pem source $REMOTE_SOURCES_DIR/upstream2/cachito.env && \ # fix ownership for pip install folder mkdir -p /opt/app-root/src/.cache/pip && chown -R root:root /opt/app-root && \ # ls -ld /opt/ /opt/app-root /opt/app-root/src/ /opt/app-root/src/.cache /opt/app-root/src/.cache/pip || true; \ pushd $REMOTE_SOURCES_DIR/upstream2/app/distgit/containers/rhdh-hub/docker/ >/dev/null && \ set -xe; \ python3.11 -V; pip3.11 -V; \ pip3.11 install --no-cache-dir --upgrade pip setuptools pyyaml; \ pip3.11 install --no-cache-dir -r requirements.txt -r requirements-build.txt; mkdocs --version; \ popd >/dev/null; \ microdnf clean all; rm -fr $REMOTE_SOURCES_DIR/upstream2 # Downstream only - Make python3.11 the default python RUN alternatives --install /usr/bin/python python /usr/bin/python3.11 1 # Downstream only - copy from build, not cleanup stage COPY --from=build --chown=1001:1001 $REMOTE_SOURCES_DIR/ ./ # Downstream only - copy embedded dynamic plugins from $REMOTE_SOURCES_DIR COPY --from=build $REMOTE_SOURCES_DIR/dynamic-plugins/dist/ ./dynamic-plugins/dist/ # Copy script to gather dynamic plugins; copy embedded dynamic plugins to root folder; fix permissions COPY docker/install-dynamic-plugins.py docker/install-dynamic-plugins.sh ./ RUN chmod -R a+r ./dynamic-plugins/ ./install-dynamic-plugins.py; \ chmod -R a+rx ./install-dynamic-plugins.sh; \ rm -fr dynamic-plugins-root && cp -R dynamic-plugins/dist/ dynamic-plugins-root # Downstream only - fix for https://issues.redhat.com/browse/RHIDP-728 RUN mkdir /opt/app-root/src/.npm RUN chown -R 1001:1001 /opt/app-root/src/.npm # The fix-permissions script is important when operating in environments that dynamically use a random UID at runtime, such as OpenShift. # The upstream backstage image does not account for this and it causes the container to fail at runtime. RUN fix-permissions ./ # Switch to nodejs user USER 1001 # Temporary workaround to avoid triggering issue # https://github.com/backstage/backstage/issues/20644 ENV CHOKIDAR_USEPOLLING='1' CHOKIDAR_INTERVAL='10000' # To avoid running scripts when using `npm pack` to install dynamic plugins ENV NPM_CONFIG_ignore-scripts='true' ENTRYPOINT ["node", "packages/backend", "--config", "app-config.yaml", "--config", "app-config.example.yaml", "--config", "app-config.example.production.yaml"] # append Brew metadata here