├── .gitignore ├── Dockerfile ├── Dockerfile-local ├── LICENSE ├── Pipfile ├── README.md ├── cfehome ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── deploy.ps1 ├── deploy.sh └── manage.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Pipfile.lock 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | 78 | # pyenv 79 | .python-version 80 | 81 | # celery beat schedule file 82 | celerybeat-schedule 83 | 84 | # SageMath parsed files 85 | *.sage.py 86 | 87 | # Environments 88 | .env 89 | .venv 90 | env/ 91 | venv/ 92 | ENV/ 93 | env.bak/ 94 | venv.bak/ 95 | 96 | # Spyder project settings 97 | .spyderproject 98 | .spyproject 99 | 100 | # Rope project settings 101 | .ropeproject 102 | 103 | # mkdocs documentation 104 | /site 105 | 106 | # mypy 107 | .mypy_cache/ 108 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Base Image 2 | FROM python:3.6 3 | 4 | # create and set working directory 5 | RUN mkdir /app 6 | WORKDIR /app 7 | 8 | # Add current directory code to working directory 9 | ADD . /app/ 10 | 11 | # set default environment variables 12 | ENV PYTHONUNBUFFERED 1 13 | ENV LANG C.UTF-8 14 | ENV DEBIAN_FRONTEND=noninteractive 15 | 16 | # set project environment variables 17 | # grab these via Python's os.environ 18 | # these are 100% optional here 19 | # $PORT is set by heroku 20 | ENV PORT=8888 21 | 22 | # Install system dependencies with OpenCV 23 | RUN apt-get update && apt-get install -y --no-install-recommends \ 24 | tzdata \ 25 | libopencv-dev \ 26 | build-essential \ 27 | libssl-dev \ 28 | libpq-dev \ 29 | libcurl4-gnutls-dev \ 30 | libexpat1-dev \ 31 | python3-setuptools \ 32 | python3-pip \ 33 | python3-dev \ 34 | python3-venv \ 35 | git \ 36 | && \ 37 | apt-get clean && \ 38 | rm -rf /var/lib/apt/lists/* 39 | 40 | # install environment dependencies 41 | RUN pip3 install --upgrade pip 42 | RUN pip3 install pipenv 43 | RUN pip3 install opencv-contrib-python 44 | 45 | # Install project dependencies 46 | RUN pipenv install --skip-lock --system --dev 47 | 48 | # EXPOSE 8888 49 | CMD gunicorn cfehome.wsgi:application --bind 0.0.0.0:$PORT -------------------------------------------------------------------------------- /Dockerfile-local: -------------------------------------------------------------------------------- 1 | # Base Image 2 | FROM python:3.6 3 | 4 | # create and set working directory 5 | RUN mkdir /app 6 | WORKDIR /app 7 | 8 | # Add current directory code to working directory 9 | ADD . /app/ 10 | 11 | # set default environment variables 12 | ENV PYTHONUNBUFFERED 1 13 | ENV LANG C.UTF-8 14 | ENV DEBIAN_FRONTEND=noninteractive 15 | 16 | # set project environment variables 17 | # grab these via Python's os.environ 18 | # these are 100% optional here 19 | ENV PORT=8888 20 | 21 | # Install system dependencies 22 | RUN apt-get update && apt-get install -y --no-install-recommends \ 23 | tzdata \ 24 | python3-setuptools \ 25 | python3-pip \ 26 | python3-dev \ 27 | python3-venv \ 28 | git \ 29 | && \ 30 | apt-get clean && \ 31 | rm -rf /var/lib/apt/lists/* 32 | 33 | 34 | # install environment dependencies 35 | RUN pip3 install --upgrade pip 36 | RUN pip3 install pipenv 37 | 38 | # Install project dependencies 39 | RUN pipenv install --skip-lock --system --dev 40 | 41 | EXPOSE 8888 42 | CMD gunicorn cfehome.wsgi:application --bind 0.0.0.0:$PORT -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Coding For Entrepreneurs 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. 22 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | 8 | [packages] 9 | django = "==2.2.4" 10 | gunicorn = "*" 11 | dj-database-url = "*" 12 | psycopg2-binary = "*" 13 | 14 | [requires] 15 | python_version = "3.6" 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Deploying Django on Docker to Heroku with OpenCV Image](https://static.codingforentrepreneurs.com/media/cfe-blog/deploy-django-on-docker-to-heroku-opencv/Django_On_Docker_to_Heroku_with_OpenCV.jpg)](https://www.codingforentrepreneurs.com/blog/deploy-django-on-docker-to-heroku-opencv) 2 | 3 | 4 | # Deploying Django on Docker to Heroku with OpenCV 5 | 6 | This repo is for the reference code from [this post](https://www.codingforentrepreneurs.com/blog/deploy-django-on-docker-to-heroku-opencv). 7 | 8 | 9 | Watch the tutorial on [youtube](https://youtu.be/1pZbuvbvYY8). 10 | -------------------------------------------------------------------------------- /cfehome/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/Django-on-Docker-with-Heroku-and-OpenCV/b9345797d2263fb5b03db11f4bfa5b2b7a0612f6/cfehome/__init__.py -------------------------------------------------------------------------------- /cfehome/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for cfehome project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.2.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.2/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'l2oxr&++e#&jrrfu35je90!z%h$em6v3x5*bv#4+m62z%js!n%' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | # DEBUG = True 27 | # DEBUG can be True/False or 1/0 28 | DEBUG = int(os.environ.get('DEBUG', default=1)) 29 | 30 | ALLOWED_HOSTS = ["*"] 31 | 32 | 33 | # Application definition 34 | 35 | INSTALLED_APPS = [ 36 | 'django.contrib.admin', 37 | 'django.contrib.auth', 38 | 'django.contrib.contenttypes', 39 | 'django.contrib.sessions', 40 | 'django.contrib.messages', 41 | 'django.contrib.staticfiles', 42 | ] 43 | 44 | MIDDLEWARE = [ 45 | 'django.middleware.security.SecurityMiddleware', 46 | 'django.contrib.sessions.middleware.SessionMiddleware', 47 | 'django.middleware.common.CommonMiddleware', 48 | 'django.middleware.csrf.CsrfViewMiddleware', 49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 50 | 'django.contrib.messages.middleware.MessageMiddleware', 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 52 | ] 53 | 54 | ROOT_URLCONF = 'cfehome.urls' 55 | 56 | TEMPLATES = [ 57 | { 58 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 59 | 'DIRS': [], 60 | 'APP_DIRS': True, 61 | 'OPTIONS': { 62 | 'context_processors': [ 63 | 'django.template.context_processors.debug', 64 | 'django.template.context_processors.request', 65 | 'django.contrib.auth.context_processors.auth', 66 | 'django.contrib.messages.context_processors.messages', 67 | ], 68 | }, 69 | }, 70 | ] 71 | 72 | WSGI_APPLICATION = 'cfehome.wsgi.application' 73 | 74 | 75 | # Database 76 | # https://docs.djangoproject.com/en/2.2/ref/settings/#databases 77 | 78 | DATABASES = { 79 | 'default': { 80 | 'ENGINE': 'django.db.backends.sqlite3', 81 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 82 | } 83 | } 84 | 85 | """ 86 | Heroku database settings. 87 | """ 88 | 89 | import dj_database_url 90 | db_from_env = dj_database_url.config() 91 | DATABASES['default'].update(db_from_env) 92 | DATABASES['default']['CONN_MAX_AGE'] = 500 93 | 94 | 95 | # Password validation 96 | # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators 97 | 98 | AUTH_PASSWORD_VALIDATORS = [ 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 101 | }, 102 | { 103 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 104 | }, 105 | { 106 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 107 | }, 108 | { 109 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 110 | }, 111 | ] 112 | 113 | 114 | # Internationalization 115 | # https://docs.djangoproject.com/en/2.2/topics/i18n/ 116 | 117 | LANGUAGE_CODE = 'en-us' 118 | 119 | TIME_ZONE = 'UTC' 120 | 121 | USE_I18N = True 122 | 123 | USE_L10N = True 124 | 125 | USE_TZ = True 126 | 127 | 128 | # Static files (CSS, JavaScript, Images) 129 | # https://docs.djangoproject.com/en/2.2/howto/static-files/ 130 | 131 | STATIC_URL = '/static/' 132 | -------------------------------------------------------------------------------- /cfehome/urls.py: -------------------------------------------------------------------------------- 1 | """cfehome URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | 19 | urlpatterns = [ 20 | path('admin/', admin.site.urls), 21 | ] 22 | -------------------------------------------------------------------------------- /cfehome/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for cfehome project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cfehome.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /deploy.ps1: -------------------------------------------------------------------------------- 1 | # build our local Docker image 2 | docker build -t dj-docker-to-heroku -f Dockerfile . 3 | 4 | 5 | # push a container to heroku 6 | heroku container:push web -a dj-docker 7 | 8 | 9 | # promote the container 10 | heroku container:release web -a dj-heroku-docker 11 | 12 | 13 | # run migrations 14 | heroku run python3 manage.py migrate -a dj-docker 15 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | # build our heroku-ready local Docker image 2 | docker build -t dj-docker-to-heroku -f Dockerfile . 3 | 4 | 5 | # push your directory container for the web process to heroku 6 | heroku container:push web -a dj-heroku-docker 7 | 8 | 9 | # promote the web process with your container 10 | heroku container:release web -a dj-heroku-docker 11 | 12 | 13 | # run migrations 14 | heroku run python3 manage.py migrate -a dj-heroku-docker 15 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cfehome.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | --------------------------------------------------------------------------------