diff --git a/.github/workflows/push-credentials-image.yaml b/.github/workflows/push-credentials-image.yaml new file mode 100644 index 0000000..f565249 --- /dev/null +++ b/.github/workflows/push-credentials-image.yaml @@ -0,0 +1,59 @@ +name: Build and Push Credentials Image + +on: + workflow_dispatch: + inputs: + branch: + description: "Target branch from which the source dockerfile from image will be sourced" + + schedule: + - cron: "0 4 * * 1-5" # UTC Time + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + + steps: + - name: Get tag name + id: get-tag-name + uses: actions/github-script@v5 + with: + script: | + const tagName = "${{ github.event.inputs.branch }}" || 'latest'; + console.log('Will use tag: ' + tagName); + return tagName; + result-encoding: string + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Build and push Dev Docker image + uses: docker/build-push-action@v6 + with: + file: ./dockerfiles/credentials.Dockerfile + push: true + target: dev + tags: edxops/credentials-dev:${{ steps.get-tag-name.outputs.result }} + platforms: linux/amd64,linux/arm64 + + - name: Send failure notification + if: failure() + uses: dawidd6/action-send-mail@v3 + with: + server_address: email-smtp.us-east-1.amazonaws.com + server_port: 465 + username: ${{secrets.edx_smtp_username}} + password: ${{secrets.edx_smtp_password}} + subject: Push Image to docker.io/edxops failed in credentials + to: team-cosmonauts@edx.org + from: github-actions + body: Push Image to docker.io/edxops for credentials failed! For details see "github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/push-edx-notes-api-image.yaml b/.github/workflows/push-edx-notes-api-image.yaml new file mode 100644 index 0000000..8ad2558 --- /dev/null +++ b/.github/workflows/push-edx-notes-api-image.yaml @@ -0,0 +1,58 @@ +name: Build and Push Edx Notes Api Image + +on: + workflow_dispatch: + inputs: + branch: + description: "Target branch from which the source dockerfile from image will be sourced" + + schedule: + - cron: "0 4 * * 1-5" # UTC Time + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + + steps: + - name: Get tag name + id: get-tag-name + uses: actions/github-script@v5 + with: + script: | + const tagName = "${{ github.event.inputs.branch }}" || 'latest'; + return tagName; + result-encoding: string + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Build and push Dev Docker image + uses: docker/build-push-action@v6 + with: + file: ./dockerfiles/edx-notes-api.Dockerfile + push: true + target: dev + tags: edxops/edx-notes-api-dev:${{ steps.get-tag-name.outputs.result }} + platforms: linux/amd64,linux/arm64 + + - name: Send failure notification + if: failure() + uses: dawidd6/action-send-mail@v3 + with: + server_address: email-smtp.us-east-1.amazonaws.com + server_port: 465 + username: ${{secrets.edx_smtp_username}} + password: ${{secrets.edx_smtp_password}} + subject: Push Image to docker.io/edxops failed in Edx Notes Api + to: team-aurora@edx.org + from: github-actions + body: Push Image to docker.io/edxops for Edx Notes Api failed! For details see "github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/push-edx-platform-images.yml b/.github/workflows/push-edx-platform-images.yml new file mode 100644 index 0000000..f68926f --- /dev/null +++ b/.github/workflows/push-edx-platform-images.yml @@ -0,0 +1,70 @@ +name: Push edx-platform Docker Images + +on: + workflow_dispatch: + inputs: + branch: + description: "Target branch from which the source dockerfile from image will be sourced" + + schedule: + - cron: "0 4 * * 1-5" # UTC Time + +jobs: + push: + runs-on: ubuntu-22.04 + + strategy: + matrix: + variant: + - { tag: 'lms-dev', port: '18000', target: 'development' } + - { tag: 'cms-dev', port: '18000', target: 'development' } + - { tag: 'cms', port: '18010', target: 'production'} + - { tag: 'lms', port: '18010', target: 'production' } + + steps: + - name: Get tag name + id: get-tag-name + uses: actions/github-script@v5 + with: + script: | + const tagName = "${{ github.event.inputs.branch }}" || 'latest'; + console.log('Will use tag: ' + tagName); + return tagName; + result-encoding: string + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Build and push Dev Docker image + uses: docker/build-push-action@v6 + with: + file: ./dockerfiles/edx-platform.Dockerfile + push: true + platforms: linux/amd64,linux/arm64 + target: ${{ matrix.variant.target }} + build-args: | + SERVICE_VARIANT: ${{ matrix.variant.tag }} + SERVICE_PORT: ${{ matrix.variant.port }} + tags: edxops/${{matrix.variant.tag}}:${{ steps.get-tag-name.outputs.result }} + + - name: Send failure notification + if: failure() + uses: dawidd6/action-send-mail@v3 + with: + server_address: email-smtp.us-east-1.amazonaws.com + server_port: 465 + username: ${{secrets.edx_smtp_username}} + password: ${{secrets.edx_smtp_password}} + subject: Push Image to docker.io/edxops failed in edx-platform + to: arch-bom@edx.org + from: github-actions + body: Push Image to docker.io/edxops for edx-platform failed! For details see "github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/push-program-intent-engagement-image.yaml b/.github/workflows/push-program-intent-engagement-image.yaml new file mode 100644 index 0000000..7ecd972 --- /dev/null +++ b/.github/workflows/push-program-intent-engagement-image.yaml @@ -0,0 +1,58 @@ +name: Build and Push Program Intent Engagement Image + +on: + workflow_dispatch: + inputs: + branch: + description: "Target branch from which the source dockerfile from image will be sourced" + + schedule: + - cron: "0 4 * * 1-5" # UTC Time + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + + steps: + - name: Get tag name + id: get-tag-name + uses: actions/github-script@v5 + with: + script: | + const tagName = "${{ github.event.inputs.branch }}" || 'latest'; + console.log('Will use tag: ' + tagName); + return tagName; + result-encoding: string + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Build and push Dev Docker image + uses: docker/build-push-action@v6 + with: + file: ./dockerfiles/program-intent-engagement.Dockerfile + push: true + target: app + tags: edxops/program-intent-engagement-dev:${{ steps.get-tag-name.outputs.result }} + + - name: Send failure notification + if: failure() + uses: dawidd6/action-send-mail@v3 + with: + server_address: email-smtp.us-east-1.amazonaws.com + server_port: 465 + username: ${{secrets.edx_smtp_username}} + password: ${{secrets.edx_smtp_password}} + subject: Push Image to docker.io/edxops failed in Program Intent Engagement + to: team-cosmonauts@edx.org + from: github-actions + body: Push Image to docker.io/edxops for Program Intent Engagement failed! For details see "github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/dockerfiles/credentials.Dockerfile b/dockerfiles/credentials.Dockerfile new file mode 100644 index 0000000..71ecafb --- /dev/null +++ b/dockerfiles/credentials.Dockerfile @@ -0,0 +1,111 @@ +FROM ubuntu:focal as base + +# System requirements +# - git; Used to pull in particular requirements from github rather than pypi, +# and to check the sha of the code checkout. +# - language-pack-en locales; ubuntu locale support so that system utilities have a consistent +# language and time zone. +# - python; ubuntu doesnt ship with python, so this is the python we will use to run the application +# - python3-pip; install pip to install application requirements.txt files +# - libssl-dev; # mysqlclient wont install without this. +# - libmysqlclient-dev; to install header files needed to use native C implementation for +# MySQL-python for performance gains. +# - wget; to download a watchman binary archive +# - unzip; to unzip a watchman binary archive +# - pkg-config; mysqlclient>=2.2.0 requires pkg-config (https://github.com/PyMySQL/mysqlclient/issues/620) + +# If you add a package here please include a comment above describing what it is used for +RUN apt-get update && \ + apt-get install -y software-properties-common && \ + apt-add-repository -y ppa:deadsnakes/ppa && apt-get update && \ + apt-get upgrade -qy && apt-get install language-pack-en locales gettext git \ + python3.11-dev python3.11-venv libmysqlclient-dev libssl-dev build-essential wget unzip pkg-config curl -qy && \ + rm -rf /var/lib/apt/lists/* + +# Create Python env +ENV VIRTUAL_ENV=/edx/app/credentials/venvs/credentials +RUN python3.11 -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" + +# Create Node env +RUN pip install nodeenv +ENV NODE_ENV=/edx/app/credentials/nodeenvs/credentials +RUN nodeenv $NODE_ENV --node=18.17.1 --prebuilt +ENV PATH="$NODE_ENV/bin:$PATH" +RUN npm install -g npm@9.x.x + +RUN locale-gen en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 +ENV DJANGO_SETTINGS_MODULE credentials.settings.production +ENV OPENEDX_ATLAS_PULL true +ENV CREDENTIALS_CFG "minimal.yml" + +EXPOSE 18150 +RUN useradd -m --shell /bin/false app + +# Install watchman +RUN wget https://github.com/facebook/watchman/releases/download/v2023.11.20.00/watchman-v2023.11.20.00-linux.zip +RUN unzip watchman-v2023.11.20.00-linux.zip +RUN mkdir -p /usr/local/{bin,lib} /usr/local/var/run/watchman +RUN cp watchman-v2023.11.20.00-linux/bin/* /usr/local/bin +RUN cp watchman-v2023.11.20.00-linux/lib/* /usr/local/lib +RUN chmod 755 /usr/local/bin/watchman +RUN chmod 2777 /usr/local/var/run/watchman + +# Now install credentials +WORKDIR /edx/app/credentials/credentials + +# fetching the requirement files that are needed +RUN mkdir -p requirements +RUN curl -L -o requirements/pip_tools.txt https://raw.githubusercontent.com/openedx/credentials/master/requirements/pip_tools.txt +RUN curl -L -o requirements/production.txt https://raw.githubusercontent.com/openedx/credentials/master/requirements/production.txt + +# Dependencies are installed as root so they cannot be modified by the application user. +RUN pip install -r requirements/pip_tools.txt +RUN pip install -r requirements/production.txt + +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 +RUN curl -L https://github.com/openedx/credentials/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 + +# Fetch the translations into the image once the Makefile's in place +RUN make pull_translations + +# Install dependencies in node_modules directory +RUN npm install --no-save +ENV NODE_BIN=/edx/app/credentials/credentials/node_modules +ENV PATH="$NODE_BIN/.bin:$PATH" +# Run webpack +RUN webpack --config webpack.config.js + +# Change static folder owner to application user. +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 + +# 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 + +# We don't switch back to the app user for devstack because we need devstack users to be +# able to update requirements and generally run things as root. +FROM base as dev +USER root +ENV DJANGO_SETTINGS_MODULE credentials.settings.devstack +RUN pip install -r /edx/app/credentials/credentials/requirements/dev.txt +RUN make pull_translations + +# Temporary compatibility hack while devstack is supporting +# both the old `edxops/credentials` image and this image: +# Add in a dummy ../credentials_env file. +# The credentials_env file was originally needed for sourcing to get +# environment variables like DJANGO_SETTINGS_MODULE, but now we just set +# those variables right in the Dockerfile. +RUN touch ../credentials_env + +CMD while true; do python ./manage.py runserver 0.0.0.0:18150; sleep 2; done diff --git a/dockerfiles/edx-notes-api.Dockerfile b/dockerfiles/edx-notes-api.Dockerfile new file mode 100644 index 0000000..9097c34 --- /dev/null +++ b/dockerfiles/edx-notes-api.Dockerfile @@ -0,0 +1,94 @@ +FROM ubuntu:focal as app + +# Packages installed: +# git; Used to pull in particular requirements from github rather than pypi, +# and to check the sha of the code checkout. + +# language-pack-en locales; ubuntu locale support so that system utilities have a consistent +# language and time zone. + +# python3.8-dev; to install python 3.8 +# python3-venv; installs venv module required to create virtual environments + +# libssl-dev; # mysqlclient wont install without this. + +# libmysqlclient-dev; to install header files needed to use native C implementation for +# MySQL-python for performance gains. + +# If you add a package here please include a comment above describing what it is used for + +RUN apt-get update && \ + apt-get install -y software-properties-common && \ + apt-add-repository -y ppa:deadsnakes/ppa && \ + apt-get update && apt-get upgrade -qy && \ + apt-get install \ + language-pack-en \ + locales \ + git \ + libmysqlclient-dev \ + pkg-config \ + libssl-dev \ + build-essential \ + python3.8-dev \ + python3.8-distutils \ + python3-virtualenv -qy && \ + rm -rf /var/lib/apt/lists/* + + +RUN locale-gen en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + + +# ENV variables lifetime is bound to the container whereas ARGS variables lifetime is bound to the image building process only +# Also ARGS provide us an option of compatibility of Path structure for Tutor and other OpenedX installations +ARG COMMON_CFG_DIR "/edx/etc" +ARG COMMON_APP_DIR="/edx/app" +ARG NOTES_VENV_DIR="${COMMON_APP_DIR}/venvs/notes" + +ENV PATH="$NOTES_VENV_DIR/bin:$PATH" + +RUN useradd -m --shell /bin/false app + +# Install curl +RUN apt-get update && apt-get install -y curl + +RUN mkdir -p requirements + +RUN virtualenv -p python3.8 --always-copy ${NOTES_VENV_DIR} + +RUN pip install --upgrade pip setuptools + +RUN curl -L -o requirements/base.txt https://raw.githubusercontent.com/openedx/edx-notes-api/master/requirements/base.txt +RUN curl -L -o requirements/pip.txt https://raw.githubusercontent.com/openedx/edx-notes-api/master/requirements/pip.txt + +RUN pip install --no-cache-dir -r requirements/base.txt +RUN pip install --no-cache-dir -r requirements/pip.txt + +RUN mkdir -p /edx/var/log + +EXPOSE 8120 + +FROM app as dev + +ENV DJANGO_SETTINGS_MODULE "notesserver.settings.devstack" + +# Backwards compatibility with devstack +RUN touch "${COMMON_APP_DIR}/edx_notes_api_env" + +RUN curl -L https://github.com/openedx/edx-notes-api/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 + +CMD while true; do python ./manage.py runserver 0.0.0.0:8120; sleep 2; done + +FROM app as production + +ENV EDXNOTES_CONFIG_ROOT /edx/etc +ENV DJANGO_SETTINGS_MODULE "notesserver.settings.yaml_config" + +RUN curl -L https://github.com/openedx/edx-notes-api/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 + +USER app + +# 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 new file mode 100644 index 0000000..774c522 --- /dev/null +++ b/dockerfiles/edx-platform.Dockerfile @@ -0,0 +1,201 @@ +FROM ubuntu:focal AS minimal-system + +ARG DEBIAN_FRONTEND=noninteractive +ARG SERVICE_VARIANT +ARG SERVICE_PORT + +# Env vars: paver +# We intentionally don't use paver in this Dockerfile, but Devstack may invoke paver commands +# during provisioning. Enabling NO_PREREQ_INSTALL tells paver not to re-install Python +# requirements for every paver command, potentially saving a lot of developer time. +ARG NO_PREREQ_INSTALL='1' + +# Env vars: locale +ENV LANG='en_US.UTF-8' +ENV LANGUAGE='en_US:en' +ENV LC_ALL='en_US.UTF-8' + +# Env vars: configuration +ENV CONFIG_ROOT='/edx/etc' +ENV LMS_CFG="$CONFIG_ROOT/lms.yml" +ENV CMS_CFG="$CONFIG_ROOT/cms.yml" + +# Env vars: path +ENV VIRTUAL_ENV="/edx/app/edxapp/venvs/edxapp" +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" +ENV PATH="/edx/app/edxapp/edx-platform/node_modules/.bin:${PATH}" +ENV PATH="/edx/app/edxapp/edx-platform/bin:${PATH}" +ENV PATH="/edx/app/edxapp/nodeenv/bin:${PATH}" + +WORKDIR /edx/app/edxapp/edx-platform + +# Create user before assigning any directory ownership to it. +RUN useradd -m --shell /bin/false app + +# Use debconf to set locales to be generated when the locales apt package is installed later. +RUN echo "locales locales/default_environment_locale select en_US.UTF-8" | debconf-set-selections +RUN echo "locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8" | debconf-set-selections + +# Setting up ppa deadsnakes to get python 3.11 +RUN apt-get update && \ + apt-get install -y software-properties-common && \ + apt-add-repository -y ppa:deadsnakes/ppa + +# Install requirements that are absolutely necessary +RUN apt-get update && \ + apt-get -y dist-upgrade && \ + apt-get -y install --no-install-recommends \ + curl \ + python3-pip \ + python3.11 \ + # python3-dev: required for building mysqlclient python package + python3.11-dev \ + python3.11-venv \ + libpython3.11 \ + libpython3.11-stdlib \ + libmysqlclient21 \ + # libmysqlclient-dev: required for building mysqlclient python package + libmysqlclient-dev \ + pkg-config \ + libssl1.1 \ + libxmlsec1-openssl \ + # lynx: Required by https://github.com/openedx/edx-platform/blob/b489a4ecb122/openedx/core/lib/html_to_text.py#L16 + lynx \ + ntp \ + git \ + build-essential \ + gettext \ + gfortran \ + graphviz \ + locales \ + swig \ + && \ + apt-get clean all && \ + rm -rf /var/lib/apt/* + +RUN mkdir -p /edx/var/edxapp +RUN mkdir -p /edx/etc +RUN chown app:app /edx/var/edxapp + +# The builder-production stage is a temporary stage that installs required packages and builds the python virtualenv, +# installs nodejs and node_modules. +# The built artifacts from this stage are then copied to the base stage. +FROM minimal-system AS builder-production + +RUN apt-get update && \ + apt-get -y install --no-install-recommends \ + libssl-dev \ + libffi-dev \ + libfreetype6-dev \ + libgeos-dev \ + libgraphviz-dev \ + libjpeg8-dev \ + liblapack-dev \ + libpng-dev \ + libsqlite3-dev \ + libxml2-dev \ + libxmlsec1-dev \ + libxslt1-dev + +# Setup python virtual environment +# It is already 'activated' because $VIRTUAL_ENV/bin was put on $PATH +RUN python3.11 -m venv "${VIRTUAL_ENV}" + +# Install python requirements +# Requires copying over requirements files, but not entire repository +RUN mkdir -p requirements/edx +RUN curl -L -o requirements/pip.txt https://raw.githubusercontent.com/openedx/edx-platform/master/requirements/pip.txt +RUN curl -L -o requirements/edx/base.txt https://raw.githubusercontent.com/openedx/edx-platform/master/requirements/edx/base.txt + + +RUN pip install -r requirements/pip.txt +RUN pip install -r requirements/edx/base.txt + +# Install node and npm +RUN nodeenv /edx/app/edxapp/nodeenv --node=18.19.0 --prebuilt +RUN npm install -g npm@10.5.x + +# This script is used by an npm post-install hook. +# We copy it into the image now so that it will be available when we run `npm install` in the next step. +# The script itself will copy certain modules into some uber-legacy parts of edx-platform which still use RequireJS. +RUN mkdir scripts +RUN curl -L -o scripts/copy-node-modules.sh https://raw.githubusercontent.com/openedx/edx-platform/master/scripts/copy-node-modules.sh + +# Install node modules +RUN curl -L -o package.json https://raw.githubusercontent.com/openedx/edx-platform/master/package.json +RUN curl -L -o package-lock.json https://raw.githubusercontent.com/openedx/edx-platform/master/package-lock.json + + +RUN chmod +x scripts/copy-node-modules.sh +RUN npm set progress=false && npm ci + +# The builder-development stage is a temporary stage that installs python modules required for development purposes +# The built artifacts from this stage are then copied to the development stage. +FROM builder-production AS builder-development + +RUN curl -L -o requirements/edx/development.txt https://raw.githubusercontent.com/openedx/edx-platform/master/requirements/edx/development.txt + +RUN pip install -r requirements/edx/development.txt + +# base stage +FROM minimal-system AS base + +# Copy python virtual environment, nodejs and node_modules +COPY --from=builder-production /edx/app/edxapp/venvs/edxapp /edx/app/edxapp/venvs/edxapp +COPY --from=builder-production /edx/app/edxapp/nodeenv /edx/app/edxapp/nodeenv +COPY --from=builder-production /edx/app/edxapp/edx-platform/node_modules /edx/app/edxapp/edx-platform/node_modules + +# Copy over remaining parts of repository (including all code) + +RUN curl -L https://github.com/openedx/edx-platform/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 + +# Install Python requirements again in order to capture local projects +RUN pip install -e . + +# Setting edx-platform directory as safe for git commands +RUN git config --global --add safe.directory /edx/app/edxapp/edx-platform + +# Production target +FROM base AS production + +USER app + +ENV EDX_PLATFORM_SETTINGS='docker-production' +ENV SERVICE_VARIANT="${SERVICE_VARIANT}" +ENV SERVICE_PORT="${SERVICE_PORT}" +ENV DJANGO_SETTINGS_MODULE="${SERVICE_VARIANT}.envs.$EDX_PLATFORM_SETTINGS" +EXPOSE ${SERVICE_PORT} + +CMD gunicorn \ + -c /edx/app/edxapp/edx-platform/${SERVICE_VARIANT}/docker_${SERVICE_VARIANT}_gunicorn.py \ + --name ${SERVICE_VARIANT} \ + --bind=0.0.0.0:${SERVICE_PORT} \ + --max-requests=1000 \ + --access-logfile \ + - ${SERVICE_VARIANT}.wsgi:application + +# Development target +FROM base AS development + +RUN apt-get update && \ + apt-get -y install --no-install-recommends \ + # wget is used in Makefile for common_constraints.txt + wget \ + && \ + apt-get clean all && \ + rm -rf /var/lib/apt/* + +COPY --from=builder-development /edx/app/edxapp/venvs/edxapp /edx/app/edxapp/venvs/edxapp + +RUN ln -s "$(pwd)/lms/envs/devstack-experimental.yml" "$LMS_CFG" +RUN ln -s "$(pwd)/cms/envs/devstack-experimental.yml" "$CMS_CFG" +# Temporary compatibility hack while devstack is supporting both the old `edxops/edxapp` image and this image. +# * Add in a dummy ../edxapp_env file +# * devstack sets /edx/etc/studio.yml as CMS_CFG. +RUN ln -s "$(pwd)/cms/envs/devstack-experimental.yml" "/edx/etc/studio.yml" +RUN touch ../edxapp_env + +ENV EDX_PLATFORM_SETTINGS='devstack_docker' +ENV SERVICE_VARIANT="${SERVICE_VARIANT}" +EXPOSE ${SERVICE_PORT} +CMD ./manage.py ${SERVICE_VARIANT} runserver 0.0.0.0:${SERVICE_PORT} diff --git a/dockerfiles/program-intent-engagement.Dockerfile b/dockerfiles/program-intent-engagement.Dockerfile new file mode 100644 index 0000000..25787d8 --- /dev/null +++ b/dockerfiles/program-intent-engagement.Dockerfile @@ -0,0 +1,99 @@ +FROM ubuntu:focal as app +MAINTAINER sre@edx.org + + +# Packages installed: + +# language-pack-en locales; ubuntu locale support so that system utilities have a consistent +# language and time zone. + +# python; ubuntu doesnt ship with python, so this is the python we will use to run the application + +# python3-pip; install pip to install application requirements.txt files + +# libmysqlclient-dev; to install header files needed to use native C implementation for +# MySQL-python for performance gains. + +# pkg-config; mysqlclient>=2.2.0 requires pkg-config (https://github.com/PyMySQL/mysqlclient/issues/620) + +# libssl-dev; # mysqlclient wont install without this. + +# python3-dev; to install header files for python extensions; much wheel-building depends on this + +# gcc; for compiling python extensions distributed with python packages like mysql-client + +# ENV variables for Python 3.12 support +ARG PYTHON_VERSION=3.12 +ENV TZ=UTC +ENV TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive + +# software-properties-common is needed to setup Python 3.12 env +RUN apt-get update && \ + apt-get install -y software-properties-common && \ + apt-add-repository -y ppa:deadsnakes/ppa + +# If you add a package here please include a comment above describing what it is used for +RUN apt-get update && apt-get -qy install --no-install-recommends \ + language-pack-en \ + locales \ + # libmysqlclient-dev header files needed to use native C implementation for MySQL-python for performance gains. + libmysqlclient-dev \ + # mysqlclient>=2.2.0 requires pkg-config (https://github.com/PyMySQL/mysqlclient/issues/620) + pkg-config \ + # mysqlclient wont install without libssl-dev + libssl-dev \ + build-essential \ + gcc \ + curl \ + python3-pip \ + python${PYTHON_VERSION} \ + python${PYTHON_VERSION}-dev \ + python${PYTHON_VERSION}-distutils + + +# need to use virtualenv pypi package with Python 3.12 +RUN pip install --upgrade pip setuptools +RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python${PYTHON_VERSION} +RUN pip install virtualenv + +RUN pip install --upgrade pip setuptools +# delete apt package lists because we do not need them inflating our image +RUN rm -rf /var/lib/apt/lists/* + +RUN ln -s /usr/bin/python3 /usr/bin/python + +# Setup zoneinfo for Python 3.12 +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN locale-gen en_US.UTF-8 +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 +ENV DJANGO_SETTINGS_MODULE program_intent_engagement.settings.production + +EXPOSE 18781 +RUN useradd -m --shell /bin/false app + +WORKDIR /edx/app/program-intent-engagement + +# Create required directories for requirements +RUN mkdir -p requirements + +ARG INTENT_MANAGEMENT_VENV_DIR="/edx/app/venvs/program-intent-management" +RUN virtualenv -p python${PYTHON_VERSION} --always-copy ${INTENT_MANAGEMENT_VENV_DIR} + +# Dependencies are installed as root so they cannot be modified by the application user. +RUN curl -L -o requirements/production.txt https://raw.githubusercontent.com/edx/program-intent-engagement/main/requirements/production.txt +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 + +RUN mkdir -p /edx/var/log + +# Code is owned by root so it cannot be modified by the application user. +USER app + +# 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 0ff55fe..1581234 100644 --- a/dockerfiles/registrar.Dockerfile +++ b/dockerfiles/registrar.Dockerfile @@ -61,9 +61,7 @@ ENV REGISTRAR_CODE_DIR ${REGISTRAR_CODE_DIR} # Working directory will be root of repo. WORKDIR ${REGISTRAR_CODE_DIR} -# cloning git repo -RUN curl -L https://github.com/edx/registrar/archive/refs/heads/master.tar.gz | tar -xz --strip-components=1 - +RUN mkdir -p requirements RUN virtualenv -p python${PYTHON_VERSION} --always-copy ${REGISTRAR_VENV_DIR} @@ -77,7 +75,13 @@ EXPOSE 18735 FROM app as dev -RUN pip install --no-cache-dir -r requirements/devstack.txt +# fetching the requirement file that is needed +RUN curl -L -o requirements/devstack.txt https://raw.githubusercontent.com/edx/registrar/master/requirements/devstack.txt + +RUN pip install --no-cache-dir -r ${REGISTRAR_CODE_DIR}/requirements/devstack.txt + +# 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 ENV DJANGO_SETTINGS_MODULE registrar.settings.devstack @@ -85,7 +89,13 @@ CMD while true; do python ./manage.py runserver 0.0.0.0:18734; sleep 2; done FROM app as prod -RUN pip install --no-cache-dir -r ${REGISTRAR_CODE_DIR}/requirements/production.txt +# fetching the requirement file that is needed +RUN curl -L -o requirements/production.txt https://raw.githubusercontent.com/edx/registrar/master/requirements/production.txt + +RUN pip install --no-cache-dir -r ${REGISTRAR_CODE_DIR}/requirements/production.txt + +# 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 ENV DJANGO_SETTINGS_MODULE registrar.settings.production