# Global arguments ARG PYTHON_VERSION=3.10.12 ARG APP_HOME="/app" ARG VENV_PATH="/opt/.venv" ############################################################################################## # ______ _ _ _ # | ___ \ (_) | | | # | |_/ /_ _ _| | __| | # | ___ \ | | | | |/ _` | # | |_/ / |_| | | | (_| | # \____/ \__,_|_|_|\__,_| # # ASCII font used https://patorjk.com/software/taag/#p=display&f=Doom&t=Build #--------------------------------------------------------------------------------------------- # Build stage ############################################################################################## FROM python:${PYTHON_VERSION} as build # Install Poetry ENV POETRY_VERSION=1.5.1 ENV POETRY_NO_INTERACTION=1 ENV POETRY_HOME="/opt/poetry" ENV PATH="${POETRY_HOME}/bin:${PATH}" ENV POETRY_CACHE_DIR=/tmp/poetry_cache RUN curl -sSL https://install.python-poetry.org | python3 - # Set a directory for virtual environment. Setting `VIRTUAL_ENV` and `PATH` environment # variables has the effect of activating the virtual environment for all subsequent # poetry and python commands. # More on this here: https://github.com/python-poetry/poetry/issues/263#issuecomment-1404129650 ARG VENV_PATH RUN python -m venv ${VENV_PATH} ENV VIRTUAL_ENV=${VENV_PATH} ENV PATH="${VENV_PATH}/bin:${PATH}" # Install dependencies. Also, it's safe to remove poetry cache. COPY poetry.lock pyproject.toml ./ # `--without dev` is preferred for production, but production still needs dev dependencies (debug-toolbar for example) RUN poetry install --no-root && rm -rf ${POETRY_CACHE_DIR} ############################################################################################## # ______ # | ___ \ # | |_/ / __ _ ___ ___ # | ___ \/ _` / __|/ _ \ # | |_/ / (_| \__ \ __/ # \____/ \__,_|___/\___| #--------------------------------------------------------------------------------------------- # # Base # ############################################################################################## FROM ubuntu:23.04 as base ARG PYTHON_VERSION ENV PYTHONUNBUFFERED=1 \ # Prevents Python from creating .pyc files PYTHONDONTWRITEBYTECODE=1 RUN apt-get update && apt-get install --no-install-recommends -y \ build-essential \ zlib1g-dev \ libncurses5-dev \ libgdbm-dev \ libnss3-dev \ libssl-dev \ libreadline-dev \ libffi-dev \ libsqlite3-dev \ wget \ libbz2-dev \ ca-certificates \ sudo \ adduser \ && apt-get clean && rm -rf /var/lib/apt/lists/* RUN wget https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz \ && tar -xf Python-${PYTHON_VERSION}.tgz \ && cd /Python-${PYTHON_VERSION} \ && chmod +x ./configure \ && ./configure --enable-optimizations \ && sudo make -j ${nproc} \ && sudo make install \ && rm -rf /Python-${PYTHON_VERSION} \ && rm -rf /Python-${PYTHON_VERSION}.tgz # Create a symlink to python3 as python RUN ln -s /usr/local/bin/python3 /usr/local/bin/python ############################################################################################## # ______ _ _ # | _ \ | | | | # | | | |_____ _____| | ___ _ __ _ __ ___ ___ _ __ | |_ # | | | / _ \ \ / / _ \ |/ _ \| '_ \| '_ ` _ \ / _ \ '_ \| __| # | |/ / __/\ V / __/ | (_) | |_) | | | | | | __/ | | | |_ # |___/ \___| \_/ \___|_|\___/| .__/|_| |_| |_|\___|_| |_|\__| # | | # |_| #--------------------------------------------------------------------------------------------- # # Development stage # ############################################################################################## FROM base as development ARG VENV_PATH ARG APP_HOME ENV PYTHONUNBUFFERED=1 \ # Prevents Python from creating .pyc files PYTHONDONTWRITEBYTECODE=1 # Install required system dependencies RUN apt-get update && apt-get install --no-install-recommends -y \ gettext \ vim \ htop \ libpq-dev \ libxml2-dev \ # Cleaning up unused files && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && rm -rf /var/lib/apt/lists/* # Create django user, will own the Django app RUN adduser --disabled-login --group --system django # Copy virtual environment from the build stage and add to it PATH, activate venv COPY --from=build --chown=django:django ${VENV_PATH} ${VENV_PATH} ENV VIRTUAL_ENV=${VENV_PATH} ENV PATH="${VENV_PATH}/bin:${PATH}" # Copy application code. It's important to select WORKDIR here for code to work. WORKDIR $APP_HOME COPY --chown=django:django . ${APP_HOME} COPY --chown=django:django ./docker/local/django/entrypoint /entrypoint RUN sed -i 's/\r$//g' /entrypoint RUN chmod +x /entrypoint COPY --chown=django:django ./docker/local/django/start /start-webapp RUN sed -i 's/\r$//g' /start-webapp RUN chmod +x /start-webapp COPY --chown=django:django ./docker/local/django/celery/worker/start /start-celeryworker RUN sed -i 's/\r$//g' /start-celeryworker RUN chmod +x /start-celeryworker COPY --chown=django:django ./docker/local/django/celery/beat/start /start-celerybeat RUN sed -i 's/\r$//g' /start-celerybeat RUN chmod +x /start-celerybeat # Create media folder for file uploads. RUN mkdir -p ${APP_HOME}/apex/media # Make django owner of the WORKDIR directory as well. RUN chown -R django:django ${APP_HOME} ENTRYPOINT ["/entrypoint"] EXPOSE 8000 ############################################################################################## # ______ _ _ _ # | ___ \ | | | | (_) # | |_/ / __ ___ __| |_ _ ___| |_ _ ___ _ __ # | __/ '__/ _ \ / _` | | | |/ __| __| |/ _ \| '_ \ # | | | | | (_) | (_| | |_| | (__| |_| | (_) | | | | # \_| |_| \___/ \__,_|\__,_|\___|\__|_|\___/|_| |_| #--------------------------------------------------------------------------------------------- # # Production stage. It uses Python image and runtime dependencies build on the `build` stage. # ############################################################################################## FROM base as production ARG VENV_PATH ARG APP_HOME ENV PYTHONUNBUFFERED=1 \ # Prevents Python from creating .pyc files PYTHONDONTWRITEBYTECODE=1 USER root RUN apt-get update && apt-get install --no-install-recommends -y \ gnupg \ libmemcached-dev \ graphviz \ libpq-dev \ libxml2-dev \ mime-support \ # Cleaning up unused files && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && rm -rf /var/lib/apt/lists/* # Create an unprivilaged user to run celery as advised in the docs. Celery should never run as root on production. # Additionally, the user must have access to a shell and must be created with a home directory. RUN groupadd celery RUN useradd -N -M --system -s /bin/bash -G celery celery # Create django user, will own the Django app RUN adduser --disabled-login --group --system django COPY --chown=django:django ./docker/production/django/sysctl.conf /etc/sysctl.conf COPY --chown=django:django ./docker/production/django/custom.conf /etc/security/limits.d/custom.conf # Copy virtual environment from the build stage and add to it PATH, activate venv COPY --from=build --chown=django:django ${VENV_PATH} ${VENV_PATH} ENV VIRTUAL_ENV=${VENV_PATH} ENV PATH="${VENV_PATH}/bin:${PATH}" # Copy application code. It's important to select WORKDIR here for code to work. WORKDIR $APP_HOME COPY --chown=django:django . ${APP_HOME} # Make django an owner of the WORKDIR directory as well. RUN chown -R django:django ${APP_HOME} COPY --chown=django:django ./docker/production/django/start /start-webapp RUN sed -i 's/\r$//g' /start-webapp RUN chmod +x /start-webapp COPY --chown=django:django ./docker/production/django/celery/worker/start /start-celeryworker RUN sed -i 's/\r$//g' /start-celeryworker RUN chmod +x /start-celeryworker COPY --chown=django:django ./docker/production/django/celery/beat/start /start-celerybeat RUN sed -i 's/\r$//g' /start-celerybeat RUN chmod +x /start-celerybeat COPY --chown=django:django ./docker/production/django/uwsgi.ini uwsgi.ini EXPOSE 8080