This is an automated email from the ASF dual-hosted git repository.
maximebeauchemin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new b3559f644c chore: simplify Dockerfile package install calls with bash
wrappers (#31034)
b3559f644c is described below
commit b3559f644c85d55b90357af80c6a606c97bebeba
Author: Maxime Beauchemin <[email protected]>
AuthorDate: Mon Dec 2 17:57:01 2024 -0800
chore: simplify Dockerfile package install calls with bash wrappers (#31034)
---
Dockerfile | 179 ++++++++++++++++++++++--------------------
docker/apt-install.sh | 51 ++++++++++++
docker/pip-install.sh | 64 +++++++++++++++
superset-websocket/Dockerfile | 2 +-
4 files changed, 211 insertions(+), 85 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 9b48d03963..9a89cef357 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -20,44 +20,38 @@
######################################################################
ARG PY_VER=3.10-slim-bookworm
-# if BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
+# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node
+# Arguments for build configuration
ARG NPM_BUILD_CMD="build"
+ARG BUILD_TRANSLATIONS="false" # Include translations in the final build
+ARG DEV_MODE="false" # Skip frontend build in dev mode
+ARG INCLUDE_CHROMIUM="true" # Include headless Chromium for alerts & reports
+ARG INCLUDE_FIREFOX="false" # Include headless Firefox if enabled
-# Include translations in the final build. The default supports en only to
-# reduce complexity and weight for those only using en
-ARG BUILD_TRANSLATIONS="false"
-
-# Used by docker-compose to skip the frontend build,
-# in dev we mount the repo and build the frontend inside docker
-ARG DEV_MODE="false"
-
-# Include headless browsers? Allows for alerts, reports & thumbnails, but
bloats the images
-ARG INCLUDE_CHROMIUM="true"
-ARG INCLUDE_FIREFOX="false"
-
-# Somehow we need python3 + build-essential on this side of the house to
install node-gyp
-RUN apt-get update -qq \
- && apt-get install \
- -yqq --no-install-recommends \
- build-essential \
- python3 \
- zstd
+# Install system dependencies required for node-gyp
+RUN --mount=type=bind,source=./docker,target=/docker \
+ /docker/apt-install.sh build-essential python3 zstd
+# Define environment variables for frontend build
ENV BUILD_CMD=${NPM_BUILD_CMD} \
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
-# NPM ci first, as to NOT invalidate previous steps except for when
package.json changes
-RUN
--mount=type=bind,target=/frontend-mem-nag.sh,src=./docker/frontend-mem-nag.sh \
- /frontend-mem-nag.sh
+# Run the frontend memory monitoring script
+RUN --mount=type=bind,source=./docker,target=/docker \
+ /docker/frontend-mem-nag.sh
WORKDIR /app/superset-frontend
-# Creating empty folders to avoid errors when running COPY later on
-RUN mkdir -p /app/superset/static/assets
-RUN
--mount=type=bind,target=./package.json,src=./superset-frontend/package.json \
-
--mount=type=bind,target=./package-lock.json,src=./superset-frontend/package-lock.json
\
+
+# Create necessary folders to avoid errors in subsequent steps
+RUN mkdir -p /app/superset/static/assets \
+ /app/superset/translations
+
+# Mount package files and install dependencies if not in dev mode
+RUN
--mount=type=bind,source=./superset-frontend/package.json,target=./package.json
\
+
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json
\
if [ "$DEV_MODE" = "false" ]; then \
npm ci; \
else \
@@ -66,33 +60,39 @@ RUN
--mount=type=bind,target=./package.json,src=./superset-frontend/package.json
# Runs the webpack build process
COPY superset-frontend /app/superset-frontend
-# This copies the .po files needed for translation
-RUN mkdir -p /app/superset/translations
+
+
+# Copy translation files
COPY superset/translations /app/superset/translations
+
+# Build the frontend if not in dev mode
RUN if [ "$DEV_MODE" = "false" ]; then \
BUILD_TRANSLATIONS=$BUILD_TRANSLATIONS npm run ${BUILD_CMD}; \
else \
echo "Skipping 'npm run ${BUILD_CMD}' in dev mode"; \
fi
-
-# Compiles .json files from the .po files, then deletes the .po files
+# Compile .json files from .po translations (if required) and clean up .po
files
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
npm run build-translation; \
else \
echo "Skipping translations as requested by build flag"; \
- fi
-RUN rm /app/superset/translations/*/LC_MESSAGES/*.po
-RUN rm /app/superset/translations/messages.pot
+ fi \
+ # removing translations files regardless
+ && rm -rf /app/superset/translations/*/LC_MESSAGES/*.po \
+ /app/superset/translations/messages.pot
+
+# Transition to Python base image
FROM python:${PY_VER} AS python-base
+RUN pip install --no-cache-dir --upgrade setuptools pip
+
######################################################################
# Final lean image...
######################################################################
FROM python-base AS lean
-# Include translations in the final build. The default supports en only to
-# reduce complexity and weight for those only using en
+# Build argument for including translations
ARG BUILD_TRANSLATIONS="false"
WORKDIR /app
@@ -104,9 +104,16 @@ ENV LANG=C.UTF-8 \
SUPERSET_HOME="/app/superset_home" \
SUPERSET_PORT=8088
-RUN mkdir -p ${PYTHONPATH} superset/static requirements superset-frontend
apache_superset.egg-info requirements \
+# Set up necessary directories and user
+RUN --mount=type=bind,source=./docker,target=/docker \
+ mkdir -p ${PYTHONPATH} \
+ superset/static \
+ requirements \
+ superset-frontend \
+ apache_superset.egg-info \
+ requirements \
&& useradd --user-group -d ${SUPERSET_HOME} -m --no-log-init --shell
/bin/bash superset \
- && apt-get update -qq && apt-get install -yqq --no-install-recommends \
+ && /docker/apt-install.sh \
curl \
libsasl2-dev \
libsasl2-modules-gssapi-mit \
@@ -117,58 +124,62 @@ RUN mkdir -p ${PYTHONPATH} superset/static requirements
superset-frontend apache
&& chown -R superset:superset ./* \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
+# Copy required files for Python build
COPY --chown=superset:superset pyproject.toml setup.py MANIFEST.in README.md ./
-# setup.py uses the version information in package.json
COPY --chown=superset:superset superset-frontend/package.json
superset-frontend/
COPY --chown=superset:superset requirements/base.txt requirements/
COPY --chown=superset:superset scripts/check-env.py scripts/
-RUN --mount=type=cache,target=/root/.cache/pip \
- apt-get update -qq && apt-get install -yqq --no-install-recommends \
- build-essential \
- && pip install --no-cache-dir --upgrade setuptools pip \
- && pip install --no-cache-dir -r requirements/base.txt \
- && apt-get autoremove -yqq --purge build-essential \
- && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
-# Copy the compiled frontend assets
+# Install Python dependencies using docker/pip-install.sh
+RUN --mount=type=bind,source=./docker,target=/docker \
+ --mount=type=cache,target=/root/.cache/pip \
+ /docker/pip-install.sh --requires-build-essential -r requirements/base.txt
+
+# Copy the compiled frontend assets from the node image
COPY --chown=superset:superset --from=superset-node
/app/superset/static/assets superset/static/assets
-## Lastly, let's install superset itself
+# Copy the main Superset source code
COPY --chown=superset:superset superset superset
-RUN --mount=type=cache,target=/root/.cache/pip \
- pip install --no-cache-dir -e .
-# Copy the .json translations from the frontend layer
+# Install Superset itself using docker/pip-install.sh
+RUN --mount=type=bind,source=./docker,target=/docker \
+ --mount=type=cache,target=/root/.cache/pip \
+ /docker/pip-install.sh -e .
+
+# Copy .json translations from the node image
COPY --chown=superset:superset --from=superset-node /app/superset/translations
superset/translations
-# Compile translations for the backend - this generates .mo files, then
deletes the .po files
+# Compile backend translations and clean up
COPY ./scripts/translations/generate_mo_files.sh ./scripts/translations/
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
./scripts/translations/generate_mo_files.sh \
- && chown -R superset:superset superset/translations \
- && rm superset/translations/messages.pot \
- && rm superset/translations/*/LC_MESSAGES/*.po; \
- else \
- echo "Skipping translations as requested by build flag"; \
- fi
+ && chown -R superset:superset superset/translations; \
+ fi \
+ && rm -rf superset/translations/messages.pot \
+ superset/translations/*/LC_MESSAGES/*.po
+# Add server run script
COPY --chmod=755 ./docker/run-server.sh /usr/bin/
-USER superset
+# Set user and healthcheck
+USER superset
HEALTHCHECK CMD curl -f "http://localhost:${SUPERSET_PORT}/health"
+# Expose port and set CMD
EXPOSE ${SUPERSET_PORT}
-
CMD ["/usr/bin/run-server.sh"]
+
######################################################################
# Dev image...
######################################################################
FROM lean AS dev
USER root
-RUN apt-get update -qq \
- && apt-get install -yqq --no-install-recommends \
+
+# Install dev dependencies
+RUN --mount=type=bind,source=./docker,target=/docker \
+ /docker/apt-install.sh \
libnss3 \
libdbus-glib-1-2 \
libgtk-3-0 \
@@ -176,46 +187,46 @@ RUN apt-get update -qq \
libasound2 \
libxtst6 \
git \
- pkg-config \
- && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/*
+ pkg-config
+# Install Playwright and its dependencies
RUN --mount=type=cache,target=/root/.cache/pip \
- pip install --no-cache-dir playwright
-RUN playwright install-deps
+ pip install playwright \
+ && playwright install-deps
+# Optionally install Chromium
RUN if [ "$INCLUDE_CHROMIUM" = "true" ]; then \
playwright install chromium; \
else \
- echo "Skipping translations in dev mode"; \
+ echo "Skipping Chromium installation in dev mode"; \
fi
-# Install GeckoDriver WebDriver
-ARG GECKODRIVER_VERSION=v0.34.0 \
- FIREFOX_VERSION=125.0.3
-
-RUN if [ "$INCLUDE_FIREFOX" = "true" ]; then \
- apt-get update -qq \
- && apt-get install -yqq --no-install-recommends wget bzip2 \
+# Install GeckoDriver WebDriver and Firefox (if required)
+ARG GECKODRIVER_VERSION=v0.34.0
+ARG FIREFOX_VERSION=125.0.3
+RUN --mount=type=bind,source=./docker,target=/docker \
+ if [ "$INCLUDE_FIREFOX" = "true" ]; then \
+ /docker/apt-install.sh wget bzip2 \
&& wget -q
https://github.com/mozilla/geckodriver/releases/download/${GECKODRIVER_VERSION}/geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz
-O - | tar xfz - -C /usr/local/bin \
&& wget -q
https://download-installer.cdn.mozilla.net/pub/firefox/releases/${FIREFOX_VERSION}/linux-x86_64/en-US/firefox-${FIREFOX_VERSION}.tar.bz2
-O - | tar xfj - -C /opt \
&& ln -s /opt/firefox/firefox /usr/local/bin/firefox \
&& apt-get autoremove -yqq --purge wget bzip2 && rm -rf
/var/[log,tmp]/* /tmp/* /var/lib/apt/lists/* /var/cache/apt/archives/*; \
+ else \
+ echo "Skipping Firefox installation in dev mode"; \
fi
-# Installing mysql client os-level dependencies in dev image only because GPL
-RUN apt-get install -yqq --no-install-recommends \
- default-libmysqlclient-dev \
- && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
+# Install MySQL client dependencies
+RUN --mount=type=bind,source=./docker,target=/docker \
+ /docker/apt-install.sh default-libmysqlclient-dev
+# Copy development requirements and install them
COPY --chown=superset:superset requirements/development.txt requirements/
-RUN --mount=type=cache,target=/root/.cache/pip \
- apt-get update -qq && apt-get install -yqq --no-install-recommends \
- build-essential \
- && pip install --no-cache-dir -r requirements/development.txt \
- && apt-get autoremove -yqq --purge build-essential \
- && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
+RUN --mount=type=bind,source=./docker,target=/docker \
+ --mount=type=cache,target=/root/.cache/pip \
+ /docker/pip-install.sh --requires-build-essential -r
requirements/development.txt
USER superset
+
######################################################################
# CI image...
######################################################################
diff --git a/docker/apt-install.sh b/docker/apt-install.sh
new file mode 100755
index 0000000000..bd9152bebb
--- /dev/null
+++ b/docker/apt-install.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+set -euo pipefail
+
+# Ensure this script is run as root
+if [[ $EUID -ne 0 ]]; then
+ echo "This script must be run as root" >&2
+ exit 1
+fi
+
+# Check for required arguments
+if [[ $# -lt 1 ]]; then
+ echo "Usage: $0 <package1> [<package2> ...]" >&2
+ exit 1
+fi
+
+# Colors for better logging (optional)
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+RESET='\033[0m'
+
+# Install packages with clean-up
+echo -e "${GREEN}Updating package lists...${RESET}"
+apt-get update -qq
+
+echo -e "${GREEN}Installing packages: $@${RESET}"
+apt-get install -yqq --no-install-recommends "$@"
+
+echo -e "${GREEN}Autoremoving unnecessary packages...${RESET}"
+apt-get autoremove -y
+
+echo -e "${GREEN}Cleaning up package cache and metadata...${RESET}"
+apt-get clean
+rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* /tmp/* /var/tmp/*
+
+echo -e "${GREEN}Installation and cleanup complete.${RESET}"
diff --git a/docker/pip-install.sh b/docker/pip-install.sh
new file mode 100755
index 0000000000..2defc7d1e7
--- /dev/null
+++ b/docker/pip-install.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+set -euo pipefail
+
+# Default flag
+REQUIRES_BUILD_ESSENTIAL=false
+USE_CACHE=true
+
+# Filter arguments
+ARGS=()
+for arg in "$@"; do
+ case "$arg" in
+ --requires-build-essential)
+ REQUIRES_BUILD_ESSENTIAL=true
+ ;;
+ --no-cache)
+ USE_CACHE=false
+ ;;
+ *)
+ ARGS+=("$arg")
+ ;;
+ esac
+done
+
+# Install build-essential if required
+if $REQUIRES_BUILD_ESSENTIAL; then
+ echo "Installing build-essential for package builds..."
+ apt-get update -qq \
+ && apt-get install -yqq --no-install-recommends build-essential
+fi
+
+# Choose whether to use pip cache
+if $USE_CACHE; then
+ echo "Using pip cache..."
+ pip install "${ARGS[@]}"
+else
+ echo "Disabling pip cache..."
+ pip install --no-cache-dir "${ARGS[@]}"
+fi
+
+# Remove build-essential if it was installed
+if $REQUIRES_BUILD_ESSENTIAL; then
+ echo "Removing build-essential to keep the image lean..."
+ apt-get autoremove -yqq --purge build-essential \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*
+fi
+
+echo "Python packages installed successfully."
diff --git a/superset-websocket/Dockerfile b/superset-websocket/Dockerfile
index 4cc2117f07..ac6e4a2999 100644
--- a/superset-websocket/Dockerfile
+++ b/superset-websocket/Dockerfile
@@ -12,7 +12,7 @@
# 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.
-FROM node:16-alpine as build
+FROM node:16-alpine AS build
WORKDIR /home/superset-websocket