diff --git a/cookiecutter-django-ida/{{cookiecutter.repo_name}}/.github/workflows/docker-publish.yml b/cookiecutter-django-ida/{{cookiecutter.repo_name}}/.github/workflows/docker-publish.yml index de7890c9..d1f75536 100644 --- a/cookiecutter-django-ida/{{cookiecutter.repo_name}}/.github/workflows/docker-publish.yml +++ b/cookiecutter-django-ida/{{cookiecutter.repo_name}}/.github/workflows/docker-publish.yml @@ -15,8 +15,14 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Build and Push docker image + - name: Build and Push prod docker image env: DOCKERHUB_PASSWORD: ${% raw %}{{ secrets.DOCKERHUB_PASSWORD }}{% endraw %} DOCKERHUB_USERNAME: ${% raw %}{{ secrets.DOCKERHUB_USERNAME }}{% endraw %} run : make github_docker_push + + - name: Build and Push dev docker image + env: + DOCKERHUB_PASSWORD: ${% raw %}{{ secrets.DOCKERHUB_PASSWORD }}{% endraw %} + DOCKERHUB_USERNAME: ${% raw %}{{ secrets.DOCKERHUB_USERNAME }}{% endraw %} + run : make github_docker_push_dev diff --git a/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Dockerfile b/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Dockerfile index 0cec6457..df9ec918 100644 --- a/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Dockerfile +++ b/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Dockerfile @@ -1,67 +1,85 @@ FROM ubuntu:focal as app -MAINTAINER sre@edx.org +ENV DEBIAN_FRONTEND noninteractive +# System requirements. +RUN apt update && \ + apt-get install -qy \ + curl \ + gettext \ + # required by bower installer + git \ + language-pack-en \ + build-essential \ + python3.8-dev \ + python3-virtualenv \ + python3.8-distutils \ + libmysqlclient-dev \ + libssl-dev \ + # mysqlclient >= 2.2.0 requires pkg-config. + pkg-config \ + libcairo2-dev && \ + rm -rf /var/lib/apt/lists/* + +# Use UTF-8. +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 -# 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 +ARG COMMON_APP_DIR="/edx/app" +ARG COMMON_CFG_DIR="/edx/etc" +ARG COOKIECUTTER_SERVICE_NAME={{cookiecutter.repo_name}} +ARG COOKIECUTTER_PROJECT_NAME={{cookiecutter.project_name}} +ARG COOKIECUTTER_APP_DIR="${COMMON_APP_DIR}/${COOKIECUTTER_SERVICE_NAME}" +ARG COOKIECUTTER_VENV_DIR="${COMMON_APP_DIR}/${COOKIECUTTER_SERVICE_NAME}/venvs/${COOKIECUTTER_SERVICE_NAME}" +ARG COOKIECUTTER_CODE_DIR="${COOKIECUTTER_APP_DIR}/${COOKIECUTTER_PROJECT_NAME}" +ARG COOKIECUTTER_NODEENV_DIR="${COOKIECUTTER_APP_DIR}/nodeenvs/${COOKIECUTTER_SERVICE_NAME}" -# python3-pip; install pip to install application requirements.txt files +ENV PATH "${COOKIECUTTER_VENV_DIR}/bin:${COOKIECUTTER_NODEENV_DIR}/bin:$PATH" +ENV COOKIECUTTER_CFG "/edx/etc/${COOKIECUTTER_SERVICE_NAME}.yml" +ENV COOKIECUTTER_CODE_DIR "${COOKIECUTTER_CODE_DIR}" +ENV COOKIECUTTER_APP_DIR "${COOKIECUTTER_APP_DIR}" -# libmysqlclient-dev; to install header files needed to use native C implementation for -# MySQL-python for performance gains. +RUN virtualenv -p python3.8 --always-copy ${COOKIECUTTER_VENV_DIR} -# libssl-dev; # mysqlclient wont install without this. +# No need to activate IDA venv as it is already in path +RUN pip install nodeenv -# python3-dev; to install header files for python extensions; much wheel-building depends on this +RUN nodeenv ${COOKIECUTTER_NODEENV_DIR} --node=16.14.0 --prebuilt && npm install -g npm@8.5.x -# gcc; for compiling python extensions distributed with python packages like mysql-client +# Working directory will be root of repo. +WORKDIR ${COOKIECUTTER_CODE_DIR} -# If you add a package here please include a comment above describing what it is used for -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -qy install --no-install-recommends \ - language-pack-en locales \ - python3.8 python3-dev python3-pip \ - # The mysqlclient Python package has install-time dependencies - libmysqlclient-dev libssl-dev pkg-config \ - gcc +# Copy over repository +COPY . . +RUN npm install --production && ./node_modules/.bin/bower install --allow-root --production && ./node_modules/.bin/webpack --config webpack.config.js --progress -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/* +# Expose canonical Cookie Cutter port +EXPOSE {{cookiecutter.port}} -RUN ln -s /usr/bin/python3 /usr/bin/python +FROM app as prod -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 {{cookiecutter.project_name}}.settings.production +ENV DJANGO_SETTINGS_MODULE "${COOKIECUTTER_SERVICE_NAME}.settings.production" -EXPOSE {{cookiecutter.port}} -RUN useradd -m --shell /bin/false app +RUN pip install -r ${COOKIECUTTER_CODE_DIR}/requirements/production.txt -WORKDIR /edx/app/{{cookiecutter.repo_name}} +CMD gunicorn --bind=0.0.0.0:{{cookiecutter.port}} --workers 2 --max-requests=1000 -c ${COOKIECUTTER_CODE_DIR}/docker_gunicorn_configuration.py ${COOKIECUTTER_PROJECT_NAME}.wsgi:application -# Copy the requirements explicitly even though we copy everything below -# this prevents the image cache from busting unless the dependencies have changed. -COPY requirements/production.txt /edx/app/{{cookiecutter.repo_name}}/requirements/production.txt +FROM app as dev -# Dependencies are installed as root so they cannot be modified by the application user. -RUN pip install -r requirements/production.txt +ENV DJANGO_SETTINGS_MODULE "${COOKIECUTTER_SERVICE_NAME}.settings.devstack" -RUN mkdir -p /edx/var/log +RUN pip install -r ${COOKIECUTTER_CODE_DIR}/requirements/django.txt +RUN pip install -r ${COOKIECUTTER_CODE_DIR}/requirements/local.txt -# Code is owned by root so it cannot be modified by the application user. -# So we copy it before changing users. -USER app +# Devstack related step for backwards compatibility +RUN touch ${COOKIECUTTER_APP_DIR}/${COOKIECUTTER_SERVICE_NAME}_env -# 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 {{cookiecutter.repo_name}} -c /edx/app/{{cookiecutter.repo_name}}/{{cookiecutter.project_name}}/docker_gunicorn_configuration.py --log-file - --max-requests=1000 {{cookiecutter.project_name}}.wsgi:application +CMD while true; do python ./manage.py runserver 0.0.0.0:{{cookiecutter.port}}; sleep 2; done -# This line is after the requirements so that changes to the code will not -# bust the image cache -COPY . /edx/app/{{cookiecutter.repo_name}} +########################################################### +# Define k8s target +FROM prod as kubernetes +ENV COOKIECUTTER_SETTINGS='kubernetes' +ENV DJANGO_SETTINGS_MODULE="${COOKIECUTTER_SERVICE_NAME}.settings.$COOKIECUTTER_SETTINGS" \ No newline at end of file diff --git a/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Makefile b/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Makefile index 44960eb9..00637d0f 100644 --- a/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Makefile +++ b/cookiecutter-django-ida/{{cookiecutter.repo_name}}/Makefile @@ -182,11 +182,17 @@ db-shell: # Run the app shell as root, enter the app's database docker attach {{cookiecutter.project_name}}.$* github_docker_build: - docker build . -f Dockerfile --target app -t openedx/{{cookiecutter.repo_name}} + docker build . -f Dockerfile --target prod -t openedx/{{cookiecutter.repo_name}} + +github_docker_build_dev: + docker build . -f Dockerfile --target dev -t openedx/{{cookiecutter.repo_name}}-dev github_docker_tag: github_docker_build docker tag openedx/{{cookiecutter.repo_name}} openedx/{{cookiecutter.repo_name}}:${GITHUB_SHA} +github_docker_tag_dev: github_docker_build_dev + docker tag openedx/{{cookiecutter.repo_name}}-dev openedx/{{cookiecutter.repo_name}}-dev:${GITHUB_SHA} + github_docker_auth: echo "$$DOCKERHUB_PASSWORD" | docker login -u "$$DOCKERHUB_USERNAME" --password-stdin @@ -194,6 +200,10 @@ github_docker_push: github_docker_tag github_docker_auth ## push to docker hub docker push 'openedx/{{cookiecutter.repo_name}}:latest' docker push "openedx/{{cookiecutter.repo_name}}:${GITHUB_SHA}" +github_docker_push_dev: github_docker_tag_dev github_docker_auth ## push to docker hub + docker push 'openedx/{{cookiecutter.repo_name}}-dev:latest' + docker push "openedx/{{cookiecutter.repo_name}}-dev:${GITHUB_SHA}" + selfcheck: ## check that the Makefile is well-formed @echo "The Makefile is well-formed."