├── captain-definition ├── gunicorn.conf.py ├── bin └── post_compile ├── README.md ├── pyproject.toml ├── LICENSE └── Dockerfile /captain-definition: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 2, 3 | "dockerfilePath": "./Dockerfile" 4 | } 5 | -------------------------------------------------------------------------------- /gunicorn.conf.py: -------------------------------------------------------------------------------- 1 | # Gunicorn configuration file 2 | # https://docs.gunicorn.org/en/stable/configure.html#configuration-file 3 | # https://docs.gunicorn.org/en/stable/settings.html 4 | # https://adamj.eu/tech/2021/12/29/set-up-a-gunicorn-configuration-file-and-test-it/ 5 | import multiprocessing 6 | 7 | max_requests = 1000 8 | max_requests_jitter = 50 9 | 10 | log_file = "-" 11 | 12 | bind = "0.0.0.0:80" 13 | workers = multiprocessing.cpu_count() * 2 + 1 14 | -------------------------------------------------------------------------------- /bin/post_compile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425 4 | set -euxo pipefail 5 | 6 | echo "Collect static files (part 1)..." 7 | python manage.py collectstatic --noinput 8 | 9 | echo "Compress files..." 10 | python manage.py compress --force 11 | 12 | echo "Collect static files (part 2)..." 13 | python manage.py collectstatic --noinput 14 | 15 | echo "Migrate database..." 16 | python manage.py migrate 17 | 18 | echo "Start gunicorn..." 19 | gunicorn project.wsgi --config="gunicorn.conf.py" 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-python-poetry-django 2 | 3 | This is a sample setup for Docker that includes Django installed with `poetry`. The `Dockerfile` is a multi-stage install which caches the installed dependencies so that subsequent deploys should take less time. For more details: https://alldjango.com/articles/serve-multiple-django-sites-from-one-cloud-server. 4 | 5 | ## Docker 6 | 7 | Sets up the server, installs dependencies, and starts up the webserver. 8 | 9 | ## CapRover 10 | 11 | PaaS which hosts the Docker container. 12 | 13 | ## Poetry 14 | 15 | Reproducible installs for Python dependencies. 16 | 17 | ## Django 18 | 19 | The web framework for perfectionists. 20 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | 2 | [tool.poetry] 3 | name = "docker-python-poetry-django" 4 | version = "0.1.0" 5 | description = "Example project that demonstrates Docker, Python, Poetry, and Django" 6 | authors = ["Your Name "] 7 | license = "MIT" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.10" 11 | Django = "^4" 12 | django-compressor = "^4" 13 | whitenoise = "^6" 14 | psycopg2-binary = "^3" 15 | gunicorn = "^20" 16 | 17 | [tool.poetry.dev-dependencies] 18 | pytest = "^7" 19 | pytest-django = "^4" 20 | poethepoet = "^0" 21 | black = "^22" 22 | isort = "^5" 23 | ruff = "^0" 24 | pywatchman = "^1" 25 | 26 | [tool.black] 27 | line-length = 88 28 | 29 | [tool.isort] 30 | profile = "black" 31 | multi_line_output = 3 32 | 33 | [tool.poe.tasks] 34 | r = "./manage.py runserver 0:8000" 35 | m = "./manage.py" 36 | mm = "./manage.py makemigrations" 37 | mi = "./manage.py migrate" 38 | md = ["mm", "mi"] 39 | t = "pytest" 40 | 41 | [build-system] 42 | requires = ["poetry-core>=1.0.0"] 43 | build-backend = "poetry.core.masonry.api" 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Adam Hill 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Creating a python base with shared environment variables 2 | FROM python:3.10.8-slim as python-base 3 | ENV PYTHONUNBUFFERED=1 \ 4 | PYTHONDONTWRITEBYTECODE=1 \ 5 | PIP_NO_CACHE_DIR=off \ 6 | PIP_DISABLE_PIP_VERSION_CHECK=on \ 7 | PIP_DEFAULT_TIMEOUT=100 \ 8 | POETRY_HOME="/opt/poetry" \ 9 | POETRY_VIRTUALENVS_IN_PROJECT=true \ 10 | POETRY_NO_INTERACTION=1 \ 11 | PYSETUP_PATH="/opt/pysetup" \ 12 | VENV_PATH="/opt/pysetup/.venv" 13 | 14 | ENV PATH="$POETRY_HOME/bin:$VENV_PATH/bin:$PATH" 15 | 16 | 17 | # builder-base is used to build dependencies 18 | FROM python-base as builder-base 19 | RUN apt-get update \ 20 | && apt-get install --no-install-recommends -y \ 21 | curl \ 22 | build-essential 23 | 24 | # Install Poetry - respects $POETRY_VERSION & $POETRY_HOME 25 | ENV POETRY_VERSION=1.2.2 26 | RUN curl -sSL https://install.python-poetry.org | python3 - 27 | 28 | # We copy our Python requirements here to cache them 29 | # and install only runtime deps using poetry 30 | WORKDIR $PYSETUP_PATH 31 | COPY ./poetry.lock ./pyproject.toml ./ 32 | RUN poetry install --only main 33 | 34 | 35 | # 'production' stage uses the clean 'python-base' stage and copies 36 | # in only our runtime deps that were installed in the 'builder-base' 37 | FROM python-base as production 38 | 39 | COPY --from=builder-base $VENV_PATH $VENV_PATH 40 | COPY . /app 41 | WORKDIR /app 42 | 43 | EXPOSE 80 44 | 45 | CMD ["sh", "/app/bin/post_compile"] 46 | --------------------------------------------------------------------------------