diff --git a/dockerfiles/codejail-service.Dockerfile b/dockerfiles/codejail-service.Dockerfile index 9659658..34581b8 100644 --- a/dockerfiles/codejail-service.Dockerfile +++ b/dockerfiles/codejail-service.Dockerfile @@ -131,6 +131,13 @@ RUN useradd --no-create-home --shell /bin/false --uid $APP_UID --gid $APP_GID $A # Cloning git repo ADD https://github.com/${CODEJAIL_SERVICE_REPO}.git#${CODEJAIL_SERVICE_VERSION} /app +# Ensure the repository is owned by the app user +RUN chown -R ${APP_USER}:${APP_USER} /app + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + WORKDIR /app RUN python${APP_PY_VER} -m venv /venv && \ @@ -183,6 +190,12 @@ RUN apt-get update && \ RUN /venv/bin/pip-sync requirements/dev.txt RUN python${APP_PY_VER} -m compileall /venv /app +# Dev mode may run as root or as app user, configure git for root +RUN git config --global --add safe.directory /app + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] + ##### Production target ##### @@ -193,3 +206,9 @@ RUN python${APP_PY_VER} -m compileall /venv /app # Drop to unprivileged user for running service USER ${APP_USER} + +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /app + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] diff --git a/dockerfiles/commerce-coordinator.Dockerfile b/dockerfiles/commerce-coordinator.Dockerfile index a233a95..91b11a6 100644 --- a/dockerfiles/commerce-coordinator.Dockerfile +++ b/dockerfiles/commerce-coordinator.Dockerfile @@ -71,9 +71,21 @@ RUN mkdir -p /edx/var/log RUN curl -L https://github.com/edx/commerce-coordinator/archive/refs/heads/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/commerce-coordinator + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Code is owned by root so it cannot be modified by the application user. # So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/commerce-coordinator + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name commerce-coordinator -c /edx/app/commerce-coordinator/commerce_coordinator/docker_gunicorn_configuration.py --log-file - --max-requests=1000 commerce_coordinator.wsgi:application diff --git a/dockerfiles/course-discovery.Dockerfile b/dockerfiles/course-discovery.Dockerfile index b427be4..416871e 100644 --- a/dockerfiles/course-discovery.Dockerfile +++ b/dockerfiles/course-discovery.Dockerfile @@ -69,6 +69,16 @@ WORKDIR ${DISCOVERY_CODE_DIR} # Cloning git repo RUN curl -L https://github.com/openedx/course-discovery/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Create discovery user for running the app +RUN useradd -m --shell /bin/false discovery + +# Ensure the repository is owned by the discovery user +RUN chown -R discovery:discovery ${DISCOVERY_CODE_DIR} + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + RUN npm install --production && ./node_modules/.bin/bower install --allow-root --production && ./node_modules/.bin/webpack --config webpack.config.js --progress # Expose canonical Discovery port @@ -85,6 +95,12 @@ RUN pip install -r ${DISCOVERY_CODE_DIR}/requirements/production.txt RUN DISCOVERY_CFG=minimal.yml OPENEDX_ATLAS_PULL=true make pull_translations +USER discovery +# Configure git safe.directory as the discovery user +RUN git config --global --add safe.directory ${DISCOVERY_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD gunicorn --bind=0.0.0.0:8381 --workers 2 --max-requests=1000 -c course_discovery/docker_gunicorn_configuration.py course_discovery.wsgi:application FROM app AS dev @@ -104,6 +120,12 @@ RUN DISCOVERY_CFG=minimal.yml OPENEDX_ATLAS_PULL=true make pull_translations # Devstack related step for backwards compatibility RUN touch ${DISCOVERY_APP_DIR}/discovery_env +USER discovery +# Configure git safe.directory as the discovery user +RUN git config --global --add safe.directory ${DISCOVERY_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:8381; sleep 2; done ########################################################### diff --git a/dockerfiles/credentials.Dockerfile b/dockerfiles/credentials.Dockerfile index 88b6b75..cd64ffc 100644 --- a/dockerfiles/credentials.Dockerfile +++ b/dockerfiles/credentials.Dockerfile @@ -112,6 +112,13 @@ RUN mkdir -p /edx/var/log # Cloning git repo. This line is after the python requirements so that changes to the code will not bust the image cache ADD https://github.com/${CREDENTIALS_SERVICE_REPO}.git#${CREDENTIALS_SERVICE_VERSION} /edx/app/credentials/credentials +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/credentials/credentials + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Fetch the translations into the image once the Makefile is in place RUN make pull_translations @@ -128,6 +135,11 @@ RUN chown -R app:app /edx/app/credentials/credentials/credentials/static # Code is owned by root so it cannot be modified by the application user. So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/credentials/credentials + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name credentials -c /edx/app/credentials/credentials/credentials/docker_gunicorn_configuration.py --log-file - --max-requests=1000 credentials.wsgi:application @@ -150,4 +162,9 @@ RUN make pull_translations # Devstack related step for backwards compatibility, used in devstack's docker-compose.yml RUN touch ../credentials_env +# Configure git safe.directory for root user in dev +RUN git config --global --add safe.directory /edx/app/credentials/credentials + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:18150; sleep 2; done diff --git a/dockerfiles/ecommerce.Dockerfile b/dockerfiles/ecommerce.Dockerfile index 8ba70dd..4f616cc 100644 --- a/dockerfiles/ecommerce.Dockerfile +++ b/dockerfiles/ecommerce.Dockerfile @@ -46,6 +46,13 @@ RUN nodeenv ${ECOMMERCE_NODEENV_DIR} --node=16.14.0 --prebuilt && npm install -g # Set working directory to the root of the repo WORKDIR ${ECOMMERCE_CODE_DIR} +# Create ecommerce user for running the app +RUN useradd -m --shell /bin/false ecommerce + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Install JS requirements RUN curl -L -o package.json https://raw.githubusercontent.com/edx/ecommerce/2u/main/package.json RUN curl -L -o package-lock.json.txt https://raw.githubusercontent.com/edx/ecommerce/2u/main/package-lock.json @@ -69,6 +76,15 @@ RUN pip install -r ${ECOMMERCE_CODE_DIR}/requirements/production.txt # every time any bit of code is changed. RUN curl -L https://github.com/edx/ecommerce/archive/refs/heads/2u/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the ecommerce user +RUN chown -R ecommerce:ecommerce ${ECOMMERCE_CODE_DIR} + +USER ecommerce +# Configure git safe.directory as the ecommerce user +RUN git config --global --add safe.directory ${ECOMMERCE_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD gunicorn --bind=0.0.0.0:18130 --workers 2 --max-requests=1000 -c ecommerce/docker_gunicorn_configuration.py ecommerce.wsgi:application FROM app AS dev @@ -88,6 +104,15 @@ RUN touch ${ECOMMERCE_APP_DIR}/ecommerce_env # every time any bit of code is changed. RUN curl -L https://github.com/openedx/ecommerce/archive/refs/heads/2u/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the ecommerce user +RUN chown -R ecommerce:ecommerce ${ECOMMERCE_CODE_DIR} + RUN curl -L -o ${ECOMMERCE_CODE_DIR}/ecommerce/settings/devstack.py https://raw.githubusercontent.com/edx/devstack/master/py_configuration_files/ecommerce.py +USER ecommerce +# Configure git safe.directory as the ecommerce user +RUN git config --global --add safe.directory ${ECOMMERCE_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:18130; sleep 2; done diff --git a/dockerfiles/edx-analytics-dashboard.Dockerfile b/dockerfiles/edx-analytics-dashboard.Dockerfile index f371d82..70e791d 100644 --- a/dockerfiles/edx-analytics-dashboard.Dockerfile +++ b/dockerfiles/edx-analytics-dashboard.Dockerfile @@ -66,6 +66,13 @@ RUN pip install --no-cache-dir -r requirements/production.txt RUN curl -L https://github.com/edx/edx-analytics-dashboard/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user (when running with app user) +RUN chown -R app:app ${INSIGHTS_CODE_DIR} + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + RUN curl -L -o ${INSIGHTS_CODE_DIR}/analytics_dashboard/settings/devstack.py https://raw.githubusercontent.com/edx/devstack/master/py_configuration_files/analytics_dashboard.py RUN nodeenv ${INSIGHTS_NODEENV_DIR} --node=18.20.2 --prebuilt \ @@ -85,12 +92,22 @@ ENV DJANGO_SETTINGS_MODULE="analytics_dashboard.settings.devstack" # Backwards compatibility with devstack RUN touch "${INSIGHTS_APP_DIR}/insights_env" +# Configure git safe.directory (needed for git operations at runtime) +RUN git config --global --add safe.directory ${INSIGHTS_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:8110; sleep 2; done FROM app AS prod ENV DJANGO_SETTINGS_MODULE="analytics_dashboard.settings.production" +# Configure git safe.directory (needed for git operations at runtime) +RUN git config --global --add safe.directory ${INSIGHTS_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD gunicorn \ --pythonpath=/edx/app/insights/edx_analytics_dashboard/analytics_dashboard \ --timeout=300 \ diff --git a/dockerfiles/edx-analytics-data-api.Dockerfile b/dockerfiles/edx-analytics-data-api.Dockerfile index ed67e7d..88bafc4 100644 --- a/dockerfiles/edx-analytics-data-api.Dockerfile +++ b/dockerfiles/edx-analytics-data-api.Dockerfile @@ -81,8 +81,20 @@ RUN pip install -r ${ANALYTICS_API_CODE_DIR}/requirements/production.txt RUN curl -L https://github.com/edx/edx-analytics-data-api/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user (when running with app user) +RUN chown -R app:app ${ANALYTICS_API_CODE_DIR} + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # exec /edx/app/analytics_api/venvs/analytics_api/bin/gunicorn -c /edx/app/analytics_api/analytics_api_gunicorn.py analyticsdataserver.wsgi:application +# Configure git safe.directory (needed for git operations at runtime) +RUN git config --global --add safe.directory ${ANALYTICS_API_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD ["gunicorn" , "-b", "0.0.0.0:8100", "--pythonpath", "/edx/app/analytics_api/analytics_api","analyticsdataserver.wsgi:application"] FROM base AS dev @@ -98,9 +110,21 @@ RUN curl -L https://github.com/edx/edx-analytics-data-api/archive/refs/heads/mas RUN curl -L -o ${ANALYTICS_API_CODE_DIR}/analyticsdataserver/settings/devstack.py https://raw.githubusercontent.com/edx/devstack/master/py_configuration_files/analytics_data_api.py +# Ensure the repository is owned by the app user (when running with app user) +RUN chown -R app:app ${ANALYTICS_API_CODE_DIR} + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + ENV DJANGO_SETTINGS_MODULE "analyticsdataserver.settings.devstack" # Devstack related step for backwards compatibility RUN touch /edx/app/${ANALYTICS_API_SERVICE_NAME}/${ANALYTICS_API_SERVICE_NAME}_env +# Configure git safe.directory (needed for git operations at runtime) +RUN git config --global --add safe.directory ${ANALYTICS_API_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:8110; sleep 2; done diff --git a/dockerfiles/edx-exams.Dockerfile b/dockerfiles/edx-exams.Dockerfile index d1c0bf6..1054e28 100644 --- a/dockerfiles/edx-exams.Dockerfile +++ b/dockerfiles/edx-exams.Dockerfile @@ -93,6 +93,13 @@ RUN mkdir -p /edx/var/log # bust the image cache RUN curl -L https://github.com/edx/edx-exams/archive/refs/heads/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/edx-exams + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + FROM app as devstack ENV DJANGO_SETTINGS_MODULE edx_exams.settings.devstack @@ -109,5 +116,10 @@ ENV DJANGO_SETTINGS_MODULE edx_exams.settings.production # So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/edx-exams + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name edx-exams -c /edx/app/edx-exams/edx_exams/docker_gunicorn_configuration.py --log-file - --max-requests=1000 edx_exams.wsgi:application diff --git a/dockerfiles/edx-notes-api.Dockerfile b/dockerfiles/edx-notes-api.Dockerfile index 52cace9..24adc5b 100644 --- a/dockerfiles/edx-notes-api.Dockerfile +++ b/dockerfiles/edx-notes-api.Dockerfile @@ -84,6 +84,13 @@ RUN pip install --no-cache-dir -r requirements/pip.txt RUN curl -L https://github.com/openedx/edx-notes-api/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/notes + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + RUN mkdir -p /edx/var/log EXPOSE 8120 @@ -106,5 +113,10 @@ ENV DJANGO_SETTINGS_MODULE="notesserver.settings.yaml_config" USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/notes + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name notes -c /edx/app/notes/notesserver/docker_gunicorn_configuration.py --log-file - --max-requests=1000 notesserver.wsgi:application diff --git a/dockerfiles/edx-platform.Dockerfile b/dockerfiles/edx-platform.Dockerfile index 1e07f62..8cf77c6 100644 --- a/dockerfiles/edx-platform.Dockerfile +++ b/dockerfiles/edx-platform.Dockerfile @@ -317,8 +317,12 @@ FROM app-deps AS base # static directories throughout the file tree. COPY --from=translations /edx/app/edxapp/edx-platform /edx/app/edxapp/edx-platform -# Setting edx-platform directory as safe for git commands -RUN git config --global --add safe.directory /edx/app/edxapp/edx-platform +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/edxapp/edx-platform + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh # Production target, for use in all deployed environments (stage, prod, edge). @@ -326,6 +330,12 @@ FROM base AS production USER app +# Setting edx-platform directory as safe for git commands (as app user) +RUN git config --global --add safe.directory /edx/app/edxapp/edx-platform + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] + ENV EDX_PLATFORM_SETTINGS='docker-production' ENV SERVICE_VARIANT="${SERVICE_VARIANT}" ENV SERVICE_PORT="${SERVICE_PORT}" @@ -336,6 +346,14 @@ EXPOSE ${SERVICE_PORT} # Development target, e.g. for use in devstack. FROM base AS development +# Setting edx-platform directory as safe for git commands (inherited from app user in base) +USER app +RUN git config --global --add safe.directory /edx/app/edxapp/edx-platform +USER root + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] + RUN apt-get update && \ apt-get -y install --no-install-recommends \ # wget is used in Makefile for common_constraints.txt diff --git a/dockerfiles/enterprise-access.Dockerfile b/dockerfiles/enterprise-access.Dockerfile index 8dacd81..23e72a9 100644 --- a/dockerfiles/enterprise-access.Dockerfile +++ b/dockerfiles/enterprise-access.Dockerfile @@ -104,14 +104,31 @@ RUN mkdir -p /edx/var/log # Clone the source code RUN curl -L https://github.com/edx/enterprise-access/archive/refs/heads/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/enterprise-access + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Change user to app USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/enterprise-access + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] + # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name enterprise-access -c /edx/app/enterprise-access/enterprise_access/docker_gunicorn_configuration.py --log-file - --max-requests=1000 enterprise_access.wsgi:application FROM app AS devstack USER root + +# Configure git safe.directory as root in devstack +RUN git config --global --add safe.directory /edx/app/enterprise-access + RUN pip install -r requirements/dev.txt CMD gunicorn --workers=2 --name enterprise-access -c /edx/app/enterprise-access/enterprise_access/docker_gunicorn_configuration.py --log-file - --max-requests=1000 enterprise_access.wsgi:application diff --git a/dockerfiles/enterprise-catalog.Dockerfile b/dockerfiles/enterprise-catalog.Dockerfile index 2c6e2cf..c700172 100644 --- a/dockerfiles/enterprise-catalog.Dockerfile +++ b/dockerfiles/enterprise-catalog.Dockerfile @@ -76,10 +76,23 @@ RUN pip install -r requirements/production.txt # Cloning the repository RUN curl -L https://github.com/edx/enterprise-catalog/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/enterprise-catalog + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Code is owned by root so it cannot be modified by the application user. # So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/enterprise-catalog + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] + # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name enterprise_catalog -c /edx/app/enterprise-catalog/enterprise_catalog/docker_gunicorn_configuration.py --log-file - --max-requests=1000 enterprise_catalog.wsgi:application @@ -93,5 +106,10 @@ FROM app AS legacy_devapp EXPOSE 18160 EXPOSE 18161 USER root + +# Configure git safe.directory as root in devstack +RUN git config --global --add safe.directory /edx/app/enterprise-catalog + RUN pip install -r requirements/dev.txt +USER app CMD gunicorn --workers=2 --name enterprise_catalog -c /edx/app/enterprise-catalog/enterprise_catalog/docker_gunicorn_configuration.py --log-file - --max-requests=1000 enterprise_catalog.wsgi:application diff --git a/dockerfiles/enterprise-subsidy.Dockerfile b/dockerfiles/enterprise-subsidy.Dockerfile index a674b57..ce026fa 100644 --- a/dockerfiles/enterprise-subsidy.Dockerfile +++ b/dockerfiles/enterprise-subsidy.Dockerfile @@ -93,15 +93,32 @@ RUN mkdir -p /edx/var/log # cloning git repo RUN curl -L https://github.com/edx/enterprise-subsidy/archive/refs/heads/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/enterprise-subsidy + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Code is owned by root so it cannot be modified by the application user. # So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/enterprise-subsidy + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] + # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name enterprise-subsidy -c /edx/app/enterprise-subsidy/enterprise_subsidy/docker_gunicorn_configuration.py --log-file - --max-requests=1000 enterprise_subsidy.wsgi:application FROM app AS devstack USER root + +# Configure git safe.directory as root in devstack +RUN git config --global --add safe.directory /edx/app/enterprise-subsidy + RUN pip install -r requirements/dev.txt USER app CMD gunicorn --workers=2 --name enterprise-subsidy -c /edx/app/enterprise-subsidy/enterprise_subsidy/docker_gunicorn_configuration.py --log-file - --max-requests=1000 enterprise_subsidy.wsgi:application diff --git a/dockerfiles/git-safe-entrypoint.sh b/dockerfiles/git-safe-entrypoint.sh new file mode 100644 index 0000000..a4f2a91 --- /dev/null +++ b/dockerfiles/git-safe-entrypoint.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Entrypoint script to configure git safe.directory for the current user +# This handles cases where containers run with different UIDs in Kubernetes +set -e + +# Only configure git if it's available +if command -v git >/dev/null 2>&1; then + # Get the list of directories that might be git repositories + # This script assumes standard edX directory layouts + + # Common patterns for edX services + GIT_DIRS=( + "/edx/app/edxapp/edx-platform" + "/edx/app/discovery/discovery" + "/edx/app/ecommerce/ecommerce" + "/edx/app/xqueue/xqueue" + "/edx/app/credentials/credentials" + "/edx/app/enterprise-subsidy" + "/edx/app/enterprise-catalog" + "/edx/app/enterprise-access" + "/edx/app/commerce-coordinator" + "/edx/app/edx-exams" + "/edx/app/edx-notes-api" + "/edx/app/analytics_dashboard/analytics_dashboard" + "/edx/app/analytics_api/analytics_api" + "/edx/app/license_manager" + "/edx/app/portal-designer" + "/edx/app/program-intent-engagement" + "/edx/app/registrar" + "/app" + ) + + # Add each directory as safe if it exists + for dir in "${GIT_DIRS[@]}"; do + if [ -d "$dir/.git" ]; then + git config --global --add safe.directory "$dir" || true + fi + done +fi + +# Execute the original command +exec "$@" diff --git a/dockerfiles/license-manager.Dockerfile b/dockerfiles/license-manager.Dockerfile index 23f3549..54dfe10 100644 --- a/dockerfiles/license-manager.Dockerfile +++ b/dockerfiles/license-manager.Dockerfile @@ -97,18 +97,39 @@ RUN pip install --no-cache-dir -r requirements/production.txt RUN curl -L https://github.com/edx/license-manager/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 RUN curl -L -o license_manager/settings/devstack.py https://raw.githubusercontent.com/edx/devstack/master/py_configuration_files/license_manager.py +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/license_manager + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + RUN mkdir -p /edx/var/log # Code is owned by root so it cannot be modified by the application user. # So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/license_manager + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name license_manager -c /edx/app/license_manager/license_manager/docker_gunicorn_configuration.py --log-file - --max-requests=1000 license_manager.wsgi:application FROM app as dev USER root + +# Configure git safe.directory for root user in dev +RUN git config --global --add safe.directory /edx/app/license_manager + RUN pip install -r /edx/app/license_manager/requirements/dev.txt + +USER app + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD gunicorn --reload --workers=2 --name license_manager -c /edx/app/license_manager/license_manager/docker_gunicorn_configuration.py --log-file - --max-requests=1000 license_manager.wsgi:application @@ -117,5 +138,14 @@ FROM app as legacy_devapp EXPOSE 18170 EXPOSE 18171 USER root + +# Configure git safe.directory for root user in dev +RUN git config --global --add safe.directory /edx/app/license_manager + RUN pip install -r /edx/app/license_manager/requirements/dev.txt + +USER app + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD gunicorn --reload --workers=2 --name license_manager -c /edx/app/license_manager/license_manager/docker_gunicorn_configuration.py --log-file - --max-requests=1000 license_manager.wsgi:application diff --git a/dockerfiles/portal-designer.Dockerfile b/dockerfiles/portal-designer.Dockerfile index 24f1aae..ce48e0c 100644 --- a/dockerfiles/portal-designer.Dockerfile +++ b/dockerfiles/portal-designer.Dockerfile @@ -71,10 +71,22 @@ RUN mkdir -p /edx/var/log # Clone the application code RUN curl -L https://github.com/edx/portal-designer/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/designer + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Code is owned by root so it cannot be modified by the application user. # So we copy it before changing users. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/designer + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name designer -c /edx/app/designer/designer/docker_gunicorn_configuration.py --log-file - --max-requests=1000 designer.wsgi:application @@ -82,5 +94,13 @@ CMD gunicorn --workers=2 --name designer -c /edx/app/designer/designer/docker_gu FROM app AS devstack # Install dependencies as root and revert back to application user USER root + +# Configure git safe.directory for root user in dev +RUN git config --global --add safe.directory /edx/app/designer + RUN pip install -r /edx/app/designer/requirements/dev.txt USER app + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] +CMD python ./manage.py runserver 0.0.0.0:18808 diff --git a/dockerfiles/program-intent-engagement.Dockerfile b/dockerfiles/program-intent-engagement.Dockerfile index ee0978a..7c490c3 100644 --- a/dockerfiles/program-intent-engagement.Dockerfile +++ b/dockerfiles/program-intent-engagement.Dockerfile @@ -76,10 +76,22 @@ RUN pip install -r requirements/production.txt # Clone the repository RUN curl -L https://github.com/edx/program-intent-engagement/archive/refs/heads/main.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/program-intent-engagement + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + RUN mkdir -p /edx/var/log # Code is owned by root so it cannot be modified by the application user. USER app +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/program-intent-engagement + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] # Gunicorn 19 does not log to stdout or stderr by default. Once we are past gunicorn 19, the logging to STDOUT need not be specified. CMD gunicorn --workers=2 --name program-intent-engagement -c /edx/app/program-intent-engagement/program_intent_engagement/docker_gunicorn_configuration.py --log-file - --max-requests=1000 program_intent_engagement.wsgi:application diff --git a/dockerfiles/registrar.Dockerfile b/dockerfiles/registrar.Dockerfile index ebfaf31..842d6fd 100644 --- a/dockerfiles/registrar.Dockerfile +++ b/dockerfiles/registrar.Dockerfile @@ -57,6 +57,12 @@ ENV PATH="$REGISTRAR_VENV_DIR/bin:$PATH" ENV REGISTRAR_APP_DIR=${REGISTRAR_APP_DIR} ENV REGISTRAR_CODE_DIR=${REGISTRAR_CODE_DIR} +# Expose ports. +EXPOSE 18734 +EXPOSE 18735 + +RUN useradd -m --shell /bin/false app + # Working directory will be root of repo. WORKDIR ${REGISTRAR_CODE_DIR} @@ -68,10 +74,6 @@ RUN pip install --upgrade pip setuptools ENV REGISTRAR_CFG="${COMMON_CFG_DIR}/registrar.yml" -# Expose ports. -EXPOSE 18734 -EXPOSE 18735 - FROM app AS dev # fetching the requirement file that is needed @@ -84,8 +86,22 @@ RUN curl -L https://github.com/edx/registrar/archive/refs/heads/master.tar.gz | RUN curl -L -o ${REGISTRAR_CODE_DIR}/registrar/settings/devstack.py https://raw.githubusercontent.com/edx/devstack/master/py_configuration_files/registrar.py +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/registrar + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + ENV DJANGO_SETTINGS_MODULE registrar.settings.devstack +USER app + +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/registrar + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:18734; sleep 2; done FROM app AS prod @@ -98,6 +114,20 @@ RUN pip install --no-cache-dir -r ${REGISTRAR_CODE_DIR}/requirements/production. # cloning the repository after requirements installation RUN curl -L https://github.com/edx/registrar/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the app user +RUN chown -R app:app /edx/app/registrar + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + ENV DJANGO_SETTINGS_MODULE=registrar.settings.production +USER app + +# Configure git safe.directory as the app user +RUN git config --global --add safe.directory /edx/app/registrar + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD ["gunicorn", "--workers=2", "--name", "registrar", "-c", "/edx/app/registrar/registrar/docker_gunicorn_configuration.py", "--max-requests=1000", "registrar.wsgi:application"] diff --git a/dockerfiles/xqueue.Dockerfile b/dockerfiles/xqueue.Dockerfile index 016c044..f4afd99 100644 --- a/dockerfiles/xqueue.Dockerfile +++ b/dockerfiles/xqueue.Dockerfile @@ -54,6 +54,13 @@ RUN virtualenv -p python${PYTHON_VERSION} --always-copy ${XQUEUE_VENV_DIR} # Create placeholder file for devstack provisioning, if needed RUN touch ${XQUEUE_APP_DIR}/xqueue_env +# Create xqueue user for running the app +RUN useradd -m --shell /bin/false xqueue + +# Copy the entrypoint script that configures git safe.directory at runtime +COPY dockerfiles/git-safe-entrypoint.sh /usr/local/bin/git-safe-entrypoint.sh +RUN chmod +x /usr/local/bin/git-safe-entrypoint.sh + # Expose ports. EXPOSE 8040 @@ -66,10 +73,19 @@ RUN pip install -r ${XQUEUE_CODE_DIR}/requirements/dev.txt # cloning git repo RUN curl -L https://github.com/openedx/xqueue/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the xqueue user +RUN chown -R xqueue:xqueue ${XQUEUE_CODE_DIR} + RUN curl -L -o ${XQUEUE_CODE_DIR}/xqueue/devstack.py https://raw.githubusercontent.com/edx/devstack/master/py_configuration_files/xqueue.py ENV DJANGO_SETTINGS_MODULE xqueue.devstack +USER xqueue +# Configure git safe.directory as the xqueue user +RUN git config --global --add safe.directory ${XQUEUE_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD while true; do python ./manage.py runserver 0.0.0.0:8040; sleep 2; done FROM app AS production @@ -81,8 +97,17 @@ RUN pip install -r ${XQUEUE_APP_DIR}/requirements.txt # cloning git repo RUN curl -L https://github.com/openedx/xqueue/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 +# Ensure the repository is owned by the xqueue user +RUN chown -R xqueue:xqueue ${XQUEUE_CODE_DIR} + ENV DJANGO_SETTINGS_MODULE=xqueue.production +USER xqueue +# Configure git safe.directory as the xqueue user +RUN git config --global --add safe.directory ${XQUEUE_CODE_DIR} + +# Use entrypoint to handle runtime UID changes in Kubernetes +ENTRYPOINT ["/usr/local/bin/git-safe-entrypoint.sh"] CMD gunicorn \ --pythonpath=/edx/app/xqueue/xqueue \ --timeout=300 \