Как я могу обнаружить окружающую среду Heroku? - PullRequest
36 голосов
/ 21 февраля 2012

У меня есть веб-приложение Django, и я хотел бы проверить, работает ли оно в стеке Heroku (для условного включения отладки и т. Д.). Есть ли простой способ сделать это? Возможно, переменная окружения?

Я знаю, что, вероятно, я могу сделать это и наоборот - то есть он может определить, работает ли он на компьютере разработчика, но это просто "не звучит правильно".

Ответы [ 7 ]

21 голосов
/ 22 февраля 2012

ENV var кажется наиболее очевидным способом сделать это. Либо найдите ENV-переменную, которая, как вы знаете, существует, либо установите свою собственную:

on_heroku = False
if 'YOUR_ENV_VAR' in os.environ:
  on_heroku = True

больше по адресу: http://devcenter.heroku.com/articles/config-vars

17 голосов
/ 04 октября 2013

Подобно тому, что предложил Нейл, я бы сделал следующее:

debug = True
if 'SOME_ENV_VAR' in os.environ:
    debug = False

Я видел, как некоторые люди используют if 'PORT' in os.environ: Но, к сожалению, переменная PORT присутствует, когда вы запускаете foreman start локально, поэтому нет никакого способа отличить локальное тестирование с помощью мастера и развертывание на Heroku.

Я бы также рекомендовал использовать один из вариантов env, который:

  1. Heroku имеет из коробки (вместо настройки и проверки для себя)
  2. вряд ли можно найти в вашей локальной среде

На дату публикации Heroku имеет следующие переменные окружения:

['PATH', 'PS1', 'COLUMNS', 'TERM', 'PORT', 'LINES', 'LANG', 'SHLVL', 'LIBRARY_PATH', 'PWD', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'DYNO', 'PYTHONHASHSEED', 'PYTHONUNBUFFERED', 'PYTHONHOME', 'HOME', '_']

Я обычно говорю с if 'DYNO' in os.environ:, потому что он, кажется, наиболее специфичен для Heroku (кто еще использовал бы термин dyno, верно?).

И я также предпочитаю форматировать его как оператор if-else, потому что он более явный:

if 'DYNO' in os.environ:
    debug = False
else:
    debug = True
11 голосов
/ 27 ноября 2013

Сначала установите переменную окружения ON_HEROKU на героку:

$ heroku config:set ON_HEROKU=1

Затем в settings.py

import os

# define if on heroku environment
ON_HEROKU = 'ON_HEROKU' in os.environ
1 голос
/ 18 января 2017

Самый надежный способ - установить переменную окружения, как указано выше. Если это невозможно, есть несколько признаков, которые вы можете искать в файловой системе, но они не могут быть / не являются надежными

  • Все экземпляры Heroku имеют путь /app - файлы и скрипты, которые работают, также будут находиться под этим, так что вы можете проверить наличие каталога и / или то, что скрипты запускаются из-под это.

  • Существует пустой каталог /etc/heroku

  • /etc/hosts может быть добавлено несколько доменов, связанных с heroku ~ $ cat /etc/hosts <snip>.dyno.rt.heroku.com

Любой из них может и может измениться в любой момент .

Ваш пробег может варьироваться

0 голосов

DATABASE_URL переменная окружения

in_heroku = False
if 'DATABASE_URL' in os.environ:
    in_heroku = True

Я думаю, вам нужно включить базу данных для вашего приложения с:

heroku addons:create heroku-postgresql:hobby-dev

, но это бесплатно искорее всего, то, что вы собираетесь делать.

Heroku делает эту переменную среды доступной при запуске своих приложений, в частности, для использования в качестве:

import dj_database_url
if in_heroku:
    DATABASES = {'default': dj_database_url.config()}
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

Не надежно, поскольку эта переменная может быть определена локально, но удобно для простых случаев.

heroku run env

может также показывать другие возможные переменные, такие как:

  • DYNO_RAM
  • WEB_CONCURRENCY

но я не уверен, документированы ли они как DATABASE_URL.

0 голосов
/ 22 апреля 2014

Короткая версия: проверьте, что часовой пояс UTC / GMT:

if not 'ORIGINAL_TIMEZONE' in os.environ:
    f = os.popen('date +%Z')
    tz = f.read().upper()
    os.environ['ORIGINAL_TIMEZONE']=tz


tz = os.environ['ORIGINAL_TIMEZONE']
if tz != '' and (not 'utc' in tz.lower()) and (not 'gmt' in tz.lower()):
    print 'Definitely not running on Heroku (or in production in general)'
else:
    print 'Assume that we are running on Heroku (or in production in general)'

Это более консервативно, чем if tz=='UTC\n': если вы сомневаетесь, предположим, что мы находимся в производстве,Обратите внимание, что мы сохраняем часовой пояс в переменную окружения, потому что settings.py может выполняться более одного раза.Фактически сервер разработки выполняет его дважды, и во второй раз системный часовой пояс уже имеет значение «UTC» (или что-то еще в settings.TIMEZONE).

Длинная версия:

, обеспечивающая полную уверенность в том, что мы никогда не будем работать на Heroku с DEBUG=True, и что мы никогда не запускаем сервер разработки на Heroku даже с DEBUG=False,От settings.py:

RUNNING_DEV_SERVER = (len(sys.argv) > 1) and (sys.argv[1] == 'runserver')

DEBUG = RUNNING_DEV_SERVER

TEMPLATE_DEBUG = DEBUG

# Detect the timezone
if not 'ORIGINAL_TIMEZONE' in os.environ:
    f = os.popen('date +%Z')
    tz = f.read().upper()
    os.environ['ORIGINAL_TIMEZONE']=tz
    print ('DEBUG: %d, RUNNING_DEV_SERVER: %d, system timezone: %s ' % (DEBUG, RUNNING_DEV_SERVER, tz))


if not (DEBUG or RUNNING_DEV_SERVER):
    SECRET_KEY = os.environ['SECRET_KEY']
else:
    print 'Running in DEBUG MODE! Hope this is not in production!'

    SECRET_KEY = 'DEBUG_INSECURE_SECRET_KEY_ae$kh(7b%$+a fcw_bdnzl#)$t88x7h2-p%eg_ei5m=w&2p-)1+'

    # But what if we are idiots and are still somehow running with DEBUG=True in production?!
    # 1. Make sure SECRET_KEY is not set
    assert not SECRET_KEY in os.environ
    # 2. Make sure the timezone is not UTC or GMT (indicating production)

    tz = os.environ['ORIGINAL_TIMEZONE']
    assert tz != '' and (not 'UTC' in tz) and (not 'GMT' in tz)

    # 3. Look for environment variables suggesting we are in PROD
    for key in os.environ:
        for red_flag in ['heroku', 'amazon', 'aws', 'prod', 'gondor']:
            assert not red_flag in key.lower()
            assert not red_flag in os.environ[key].lower()

Если вы действительно хотите запустить сервер разработки на Heroku, я предлагаю вам добавить переменную среды, указывающую дату, когда вы можете это сделать.Тогда продолжайте, только если эта дата сегодня.Таким образом, вам придется изменить эту переменную перед началом разработки, но если вы забудете сбросить ее, на следующий день вы все равно будете защищены от случайного запуска в производстве.Конечно, если вы хотите быть сверхконсервативным, вы также можете указать, скажем, 1-часовой интервал, когда применяются исключения.

Наконец, если вы решили принять предложенный выше подход, пока вы находитесь вэто, также установите django-security, добавьте djangosecurity к INSTALLED_APPS и добавьте в конец вашего settings.py:

if not (DEBUG or RUNNING_DEV_SERVER):
    ### Security
    SECURE_SSL_REDIRECT = True
    SECURE_CONTENT_TYPE_NOSNIFF = True

    SECURE_HSTS_SECONDS = 86400000
    SECURE_HSTS_INCLUDE_SUBDOMAINS = True
    SECURE_BROWSER_XSS_FILTER = True

    SESSION_COOKIE_SECURE = True
    SESSION_COOKIE_HTTPONLY = True
    CSRF_COOKIE_HTTPONLY = True # May have problems with Ajax
    CSRF_COOKIE_SECURE = True
0 голосов
/ 01 ноября 2013

Подробнее об этом здесь: https://devcenter.heroku.com/articles/config-vars

Мое решение:

$ heroku config:set HEROKU=1

Эти переменные среды являются постоянными - они останутся на месте при развертывании и перезапуске приложений - поэтому, если вам не нужно изменять значения, вам нужно установить их только один раз.

Тогда вы можете проверить его наличие в вашем приложении.

>>> 'HEROKU' in os.environ
True
...