2012-02-21 19 views
33

Tengo una aplicación web Django, y me gustaría comprobar si se está ejecutando en la pila Heroku (para la habilitación condicional de la depuración, etc.) ¿Hay alguna manera simple de hacer esto? Una variable de entorno, tal vez?¿Cómo puedo detectar el entorno de Heroku?

Sé que probablemente también pueda hacerlo al revés, es decir, que lo detecte si se está ejecutando en una máquina de desarrollo, pero eso simplemente "no suena bien".

Respuesta

21

Una ENV var parece ser la forma más obvia de hacerlo. O bien buscar una ENV var que sabe que existe, o configurar su propia:

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

más en: http://devcenter.heroku.com/articles/config-vars

+0

Gracias, no me había dado cuenta de que todavía se podían establecer variables de entorno. Esta parece ser la forma correcta de hacerlo. – aviraldg

+2

atajo: on_heroku = 'DYNO' en os.environ –

+2

NO use on_heroku = 'DYNO' en os.environ como sugiere tinchou. Esa variable de entorno no se establece durante ciertas acciones de buildpack, como cuando se ejecuta automáticamente collectstatic para una compilación django. Esto es casi imposible de depurar: es mucho mejor que uses la solución anterior. – patr1ck

16

Similar a lo que sugirió Neil, yo haría lo siguiente:

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

He visto a algunas personas usar if 'PORT' in os.environ: Pero lo desafortunado es que la variable PORT está presente cuando ejecuta foreman start localmente, por lo que no hay forma de distinguir entre las pruebas locales con el capataz y la implementación en Heroku.

También me gustaría recomendar el uso de uno de los env vars que:

  1. Heroku ha sacarlo de la caja (en lugar de establecer y la comprobación de su propio)
  2. es poco probable que se encuentran en su localidad ambiente

a la fecha de publicación, Heroku tiene las siguientes variables: Environ

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

Generalmente voy con if 'DYNO' in os.environ:, porque parece ser el más específico de Heroku (¿quién más usaría el término dyno, ¿verdad?).

Y también prefiero a formatearlo como una sentencia if-parte porque es más explícito:

if 'DYNO' in os.environ: 
    debug = False 
else: 
    debug = True 
+1

para la seguridad, probablemente debería ser 'DEBUG = False' de forma predeterminada si lo hace con seguridad. Algo como 'DEBUG = False; si no es 'DYNO' en os.environ: debug = True' ¿quizás? – crobar

0

Lea más sobre esto aquí: https://devcenter.heroku.com/articles/config-vars

Mi solución:

$ heroku config:set HEROKU=1 

Estas variables de entorno son persistentes, se mantendrán en el despliegue y en el reinicio de la aplicación, por lo que, a menos que necesite cambiar los valores, solo tendrá que configurarlos una vez.

Luego puede probar su presencia en su aplicación.:

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

En primer lugar establece la variable de entorno ON_HEROKU en heroku:

$ heroku config:set ON_HEROKU=1 

Luego, en settings.py

import os 

# define if on heroku environment 
ON_HEROKU = 'ON_HEROKU' in os.environ 
+0

Prefiero la solución 'DYNO' (o configurar esto en la interfaz de usuario web, no con' config: set') ya que esto será 'True' en' heroku local' también, lo que significa que no podemos usarlo para probar si se está ejecutando en localhost o no. – OJFord

+0

@OllieFord No obtengo 'DYNO' en' heroku local', así que tuve que agregar explícitamente 'DYNO = Dummy' en mi' .env' (Cualquier valor está bien ya que estamos comprobando solo la existencia del env. variable) –

-1

versión corta: verificación de que la zona horaria es 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)' 

Esto es más conservador que if tz=='UTC\n': si tiene dudas, suponga que estamos en producción. Tenga en cuenta que estamos guardando la zona horaria en una variable de entorno porque settings.py se puede ejecutar más de una vez. De hecho, el servidor de desarrollo lo ejecuta dos veces, y la segunda vez que la zona horaria del sistema ya es 'UTC' (o lo que sea que esté en settings.TIMEZONE).

Versión larga:

hacer absolutamente seguro de que nunca nos falte en Heroku con DEBUG=True, y que nunca ejecutar el servidor de desarrollo en Heroku incluso con DEBUG=False. De 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() 

Si realmente desea ejecutar el servidor de desarrollo en Heroku, sugiero agregar una variable de entorno que especifica la fecha en la que se puede hacer eso. Entonces solo proceda si esta fecha es hoy. De esta manera tendrá que cambiar esta variable antes de comenzar el trabajo de desarrollo, pero si olvida desarmarlo, al día siguiente todavía estará protegido contra la ejecución accidental de la producción. Por supuesto, si quiere ser superconservador, también puede especificar, por ejemplo, una ventana de 1 hora cuando se aplican excepciones.

Por último, si usted decidió adoptar el enfoque sugerido más arriba, mientras que usted está en él, también instalar Django-seguridad, añadir djangosecurity a INSTALLED_APPS, y añadir al final de su 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 
-1

DATABASE_URL variable de entorno

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

creo que es necesario para que la base de datos para su aplicación con:

heroku addons:create heroku-postgresql:hobby-dev 

pero es gratis y es probable que lo haga de todos modos.

Heroku hace que esta variable de entorno disponibles al ejecutar sus aplicaciones, en particular para el uso como:

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'), 
     } 
    } 

no es infalible como la variable puede ser definida localmente, pero es conveniente para los casos simples.

heroku run env 

también podrían mostrar otras variables posibles como:

  • DYNO_RAM
  • WEB_CONCURRENCY

pero no estoy seguro de si los documentados como DATABASE_URL.

+0

@Downvoters por favor explique para que pueda aprender y mejorar la información ;-) –

+0

La variable de entorno 'DATABASE_URL' se está volviendo más común y no la usa Heroku. Es cada vez menos probable que sea preciso a medida que pasa el tiempo. – Rebs

0

La manera más confiable sería establecer una variable de entorno como la anterior. Si eso no es posible, hay algunos signos que usted puede buscar en el sistema de archivos, pero pueden no ser/no son infalibles

  • casos heroku todos tienen el camino /app - los archivos y secuencias de comandos que se ejecutan también estará debajo de esto, para que pueda verificar la presencia del directorio y/o que los scripts se ejecuten debajo de él.

  • Hay un directorio vacío /etc/heroku

  • /etc/hosts puede tener algunos dominios relacionados heroku añadido ~ $ cat /etc/hosts <snip>.dyno.rt.heroku.com

Cualquiera de estos puede y puede cambiar en cualquier momento.

Tu kilometraje puede variar

Cuestiones relacionadas