Esta imagen de Docker ahora está en desuso. No hay necesidad de usarlo, solo puede usar Uvicorn con --workers .
Lea más al respecto a continuación.
Dockerfile respectivospython3.11 , latest (Dockerfile)python3.10 , (Dockerfile)python3.9 , (Dockerfile)python3.11-slim (Dockerfile)python3.10-slim (Dockerfile)python3.9-slim (Dockerfile) Estas etiquetas ya no son compatibles o mantenidas, se eliminan del repositorio de GitHub, pero las últimas versiones empujadas aún podrían estar disponibles en Docker Hub si alguien las ha estado tirando:
python3.9-alpine3.14python3.8python3.8-slimpython3.8-alpine3.10python3.7python3.7-alpine3.8python3.6python3.6-alpine3.8Las últimas etiquetas de fecha para estas versiones son:
python3.9-alpine3.14-2024-03-11python3.8-2024-11-02python3.8-slim-2024-11-02python3.8-alpine3.10-2024-03-11python3.7-2024-11-02python3.7-alpine3.8-2024-03-11python3.6-2022-11-25python3.6-alpine3.8-2022-11-25 Nota : Hay etiquetas para cada fecha de compilación. Si necesita "fijar" la versión de imagen de Docker que usa, puede seleccionar una de esas etiquetas. Eg tiangolo/uvicorn-gunicorn:python3.11-2024-11-02 .
Imagen de Docker con Uvicorn administrado por Gunicorn para aplicaciones web de alto rendimiento en Python con rendimiento automático.
Repo de Github : https://github.com/tiangolo/uvicorn-gunicorn-docker
Imagen de Docker Hub : https://hub.docker.com/r/tiangolo/uvicorn-gunicorn/
Las aplicaciones web de Python que se ejecutan con UVICORN (utilizando la especificación "ASGI" para aplicaciones web asíncronas de Python) han demostrado tener algunas de las mejores actuaciones, medidas por terceros de referencia.
El rendimiento alcanzable está a la par (y en muchos casos superior a) ir y nodo.js marcos.
Esta imagen tiene un mecanismo de ajuste automático incluido para comenzar una serie de procesos de trabajadores en función de los núcleos de CPU disponibles. De esa manera, puede agregar su código y obtener un alto rendimiento automáticamente, lo cual es útil en implementaciones simples .
Probablemente esté usando Kubernetes o herramientas similares. En ese caso, probablemente no necesite esta imagen (o ninguna otra imagen base similar ). Probablemente sea mejor construir una imagen Docker desde cero como se explica en los documentos de Fastapi en contenedores - Docker: construir una imagen de Docker para Fastapi, ese mismo proceso e ideas podrían aplicarse a otros marcos ASGI.
Si tiene un clúster de máquinas con Kubernetes , Docker Swarm Mode, Nomad u otro sistema complejo similar para administrar contenedores distribuidos en múltiples máquinas, entonces probablemente desee manejar la replicación a nivel de clúster en lugar de usar un administrador de procesos (como Gunicorn con trabajadores de Uvicorn) en cada contenedor, que es lo que hace esta imagen de Docker.
En esos casos (por ejemplo, con Kubernetes), probablemente querrá construir una imagen Docker desde cero , instalar sus dependencias y ejecutar un solo proceso UVICORN en lugar de esta imagen.
Por ejemplo, su Dockerfile podría parecer:
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD [ "uvicorn" , "app.main:app" , "--host" , "0.0.0.0" , "--port" , "80" ]Puede leer más sobre esto en la documentación de Fastapi sobre: Fastapi en contenedores: Docker, ya que las mismas ideas se aplicarían a otros marcos ASGI.
Si definitivamente desea tener varios trabajadores en un solo contenedor, Uvicorn ahora admite el manejo de subprocesos, incluido el reinicio de los muertos. Por lo tanto, no hay necesidad de que Gunicorn administre múltiples trabajadores en un solo contenedor.
Puede modificar el ejemplo Dockerfile desde arriba, agregando la opción --workers a Uvicorn, como:
FROM python:3.9
WORKDIR /code
COPY ./requirements.txt /code/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
COPY ./app /code/app
CMD [ "uvicorn" , "app.main:app" , "--host" , "0.0.0.0" , "--port" , "80" , "--workers" , "4" ]Eso es todo lo que necesitas. No necesitas esta imagen de Docker en absoluto. ?
Puede leer más sobre esto en los documentos de Fastapi sobre la implementación con Docker.
Uvicorn no tenía apoyo para administrar el procesamiento de trabajadores, incluido el reinicio de trabajadores muertos. Pero ahora lo hace.
Antes de eso, Gunicorn podría usarse como gerente de procesos, ejecutando trabajadores de Uvicorn. Esta complejidad adicional que ya no es necesaria.
El resto de este documento se mantiene por razones históricas, pero probablemente no lo necesite. ?
tiangolo/uvicorn-gunicornEsta imagen establecerá una configuración sensata basada en el servidor en el que se ejecuta (la cantidad de núcleos de CPU disponibles) sin hacer sacrificios.
Tiene valores predeterminados sensibles, pero puede configurarlo con variables de entorno o anular los archivos de configuración.
También hay una versión delgada. Si quieres una de esas, usa una de las etiquetas desde arriba.
Esta imagen fue creada para ser la imagen base para:
Pero podría usarse como la imagen base para ejecutar cualquier aplicación web de Python que use la especificación ASGI.
Si está creando una nueva aplicación web de Starlette , debe usar Tiangolo/Uvicorn-Gunicorn-Starlette .
Si está creando una nueva aplicación web Fastapi , debe usar Tiangolo/Uvicorn-Gunicorn-Fastapi .
Nota : Fastapi se basa en Starlette y agrega varias características encima. Útil para API y otros casos: validación de datos, conversión de datos, documentación con OpenAPI, inyección de dependencia, seguridad/autenticación y otros.
Nota : A menos que esté haciendo algo más avanzado técnicamente, probablemente debería usar Starlette con Tiangolo/Uvicorn-Gunicorn-Starlette o Fastapi con Tiangolo/Uvicorn-Gunicorn-Fastapi .
No necesitas clonar el repositorio de GitHub.
Puede usar esta imagen como imagen base para otras imágenes.
Suponiendo que tenga un archivo requirements.txt , podría tener un Dockerfile como este:
FROM tiangolo/uvicorn-gunicorn:python3.11
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /app Esperará un archivo en /app/app/main.py .
O de lo contrario, un archivo en /app/main.py .
Y esperará que contenga una app variable con su aplicación "ASGI".
Luego puede construir su imagen desde el directorio que tiene su Dockerfile , por ejemplo:
docker build -t myimage ./docker run -d --name mycontainer -p 80:80 myimageDebería poder verificarlo en la URL de su contenedor Docker, por ejemplo: http://192.168.99.100/ o http://127.0.0.1/ (o equivalente, usando su host Docker).
Probablemente también desee agregar cualquier dependencia para su aplicación y sujetarlas a una versión específica, probablemente incluyendo Uvicorn y Gunicorn.
De esta manera, puede asegurarse de que su aplicación siempre funcione como se esperaba.
Puede instalar paquetes con comandos pip en su Dockerfile , utilizando un requirements.txt o incluso usando poesía.
Y luego puede actualizar esas dependencias de manera controlada, ejecutando sus pruebas, asegurándose de que todo funcione, pero sin romper su aplicación de producción si alguna versión nueva no es compatible.
Aquí hay un pequeño ejemplo de una de las formas en que puede instalar sus dependencias asegurándose de tener una versión fijada para cada paquete.
Supongamos que tiene un proyecto administrado con poesía, por lo tanto, tiene dependencias de sus paquetes en un archivo pyproject.toml . Y posiblemente un archivo poetry.lock .
Entonces podría tener un Dockerfile usando el edificio de Docker Multi-Stage con:
FROM python:3.9 as requirements-stage
WORKDIR /tmp
RUN pip install poetry
COPY ./pyproject.toml ./poetry.lock* /tmp/
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
FROM tiangolo/uvicorn-gunicorn:python3.11
COPY --from=requirements-stage /tmp/requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./app /appEso lo hará:
./poetry.lock* (terminando con A * ), no se bloqueará si ese archivo aún no está disponible.Es importante copiar el código de la aplicación después de instalar las dependencias, de esa manera puede aprovechar el caché de Docker. De esa manera, no tendrá que instalar todo desde cero cada vez que actualice los archivos de su aplicación, solo cuando agrega nuevas dependencias.
Esto también se aplica para cualquier otra forma que use para instalar sus dependencias. Si usa un requirements.txt , copie solo e instale todas las dependencias en la parte superior del Dockerfile , y agregue el código de su aplicación después.
Estas son las variables de entorno que puede configurar en el contenedor para configurarlo y sus valores predeterminados:
MODULE_NAMEEl "módulo" (archivo) de Python para ser importado por Gunicorn, este módulo contendría la aplicación real en una variable.
Por defecto:
app.main si hay un archivo /app/app/main.py omain si hay un archivo /app/main.py Por ejemplo, si su archivo principal estaba en /app/custom_app/custom_main.py , podría configurarlo como:
docker run -d -p 80:80 -e MODULE_NAME= " custom_app.custom_main " myimageVARIABLE_NAMELa variable dentro del módulo Python que contiene la aplicación ASGI.
Por defecto:
appPor ejemplo, si su archivo principal de Python tiene algo como:
from fastapi import FastAPI
api = FastAPI ()
@ api . get ( "/" )
def read_root ():
return { "message" : "Hello world!" } En este caso, api sería la variable con la "aplicación ASGI". Podrías configurarlo como:
docker run -d -p 80:80 -e VARIABLE_NAME= " api " myimageAPP_MODULELa cadena con el módulo Python y el nombre de la variable pasaron a Gunicorn.
De forma predeterminada, establezca en función de las variables MODULE_NAME y VARIABLE_NAME :
app.main:app omain:appPuedes configurarlo como:
docker run -d -p 80:80 -e APP_MODULE= " custom_app.custom_main:api " myimageGUNICORN_CONFLa ruta a un archivo de configuración de Gunicorn Python.
Por defecto:
/app/gunicorn_conf.py si existe/app/app/gunicorn_conf.py si existe/gunicorn_conf.py (el valor predeterminado incluido)Puedes configurarlo como:
docker run -d -p 80:80 -e GUNICORN_CONF= " /app/custom_gunicorn_conf.py " myimagePuede usar el archivo de configuración de esta imagen como punto de partida para el suyo.
WORKERS_PER_COREEsta imagen verificará cuántos núcleos de CPU están disponibles en el servidor actual que ejecuta su contenedor.
Establecerá el número de trabajadores en el número de núcleos de CPU multiplicados por este valor.
Por defecto:
1Puedes configurarlo como:
docker run -d -p 80:80 -e WORKERS_PER_CORE= " 3 " myimage Si utilizara el valor 3 en un servidor con 2 núcleos de CPU, ejecutaría 6 procesos de trabajadores.
También puede usar valores de punto flotante.
Entonces, por ejemplo, si tiene un gran servidor (digamos, con 8 núcleos de CPU) que ejecuta varias aplicaciones, y tiene una aplicación ASGI que sabe que no necesitará alto rendimiento. Y no desea desperdiciar recursos del servidor. Podría hacer que use 0.5 trabajadores por núcleo de CPU. Por ejemplo:
docker run -d -p 80:80 -e WORKERS_PER_CORE= " 0.5 " myimageEn un servidor con 8 núcleos de CPU, esto haría que inicie solo 4 procesos de trabajadores.
Nota : Por defecto, si WORKERS_PER_CORE es 1 y el servidor tiene solo 1 núcleo de CPU, en lugar de iniciar 1 trabajador único, comenzará 2. Esto es para evitar el rendimiento incorrecto y las aplicaciones de bloqueo (aplicación del servidor) en máquinas pequeñas (máquina del servidor/nube/etc.). Esto se puede anular utilizando WEB_CONCURRENCY .
MAX_WORKERSEstablezca el número máximo de trabajadores para usar.
Puede usarlo para dejar que la imagen calcule el número de trabajadores automáticamente, pero asegurándose de que esté limitado a un máximo.
Esto puede ser útil, por ejemplo, si cada trabajador usa una conexión de base de datos y su base de datos tiene un límite máximo de conexiones abiertas.
Por defecto, no está configurado, lo que significa que es ilimitado.
Puedes configurarlo como:
docker run -d -p 80:80 -e MAX_WORKERS= " 24 " myimageEsto haría que la imagen comience en la mayoría de los 24 trabajadores, independientemente de cuántos núcleos de CPU están disponibles en el servidor.
WEB_CONCURRENCYAnular la definición automática del número de trabajadores.
Por defecto:
WORKERS_PER_CORE . Entonces, en un servidor con 2 núcleos, de forma predeterminada se establecerá en 2 .Puedes configurarlo como:
docker run -d -p 80:80 -e WEB_CONCURRENCY= " 2 " myimageEsto haría que la imagen inicie 2 procesos de trabajadores, independientemente de cuántos núcleos de CPU están disponibles en el servidor.
HOSTEl "anfitrión" utilizado por Gunicorn, la IP donde Gunicorn escuchará las solicitudes.
Es el host dentro del contenedor.
Entonces, por ejemplo, si establece esta variable en 127.0.0.1 , solo estará disponible dentro del contenedor, no en el host que lo ejecuta.
Se proporciona para completar, pero probablemente no debería cambiarlo.
Por defecto:
0.0.0.0PORTEl puerto del contenedor debe escuchar.
Si está ejecutando su contenedor en un entorno restrictivo que lo obliga a usar un puerto específico (como 8080 ), puede configurarlo con esta variable.
Por defecto:
80Puedes configurarlo como:
docker run -d -p 80:8080 -e PORT= " 8080 " myimageBINDEl anfitrión y el puerto reales pasaron a Gunicorn.
Por defecto, establezca en función HOST y PORT las variables.
Entonces, si no cambió nada, se establecerá de forma predeterminada para:
0.0.0.0:80Puedes configurarlo como:
docker run -d -p 80:8080 -e BIND= " 0.0.0.0:8080 " myimageLOG_LEVELEl nivel de registro para Gunicorn.
Uno de:
debuginfowarningerrorcritical Por defecto, configure en info .
Si necesita exprimir más registro de sacrificio de rendimiento, configúrelo en warning , por ejemplo:
Puedes configurarlo como:
docker run -d -p 80:8080 -e LOG_LEVEL= " warning " myimageWORKER_CLASSLa clase será utilizada por Gunicorn para los trabajadores.
Por defecto, establezca en uvicorn.workers.UvicornWorker .
El hecho de que use Uvicorn es lo que permite usar aplicaciones ASGI como Fastapi y Starlette, y eso también es lo que proporciona el máximo rendimiento.
Probablemente no deberías cambiarlo.
Pero si por alguna razón necesita usar el trabajador alternativo de Uvicorn: uvicorn.workers.UvicornH11Worker , puede configurarlo con esta variable de entorno.
Puedes configurarlo como:
docker run -d -p 80:8080 -e WORKER_CLASS= " uvicorn.workers.UvicornH11Worker " myimageTIMEOUTLos trabajadores en silencio por más de esto, muchos segundos son asesinados y reiniciados.
Lea más al respecto en los documentos de Gunicorn: Tiempo de espera.
Por defecto, establezca en 120 .
Observe que los marcos Uvicorn y ASGI como Fastapi y Starlette son asíncronos, no sincronizados. Por lo tanto, es probable que sea seguro tener tiempos de espera más altos que para los trabajadores de sincronización.
Puedes configurarlo como:
docker run -d -p 80:8080 -e TIMEOUT= " 20 " myimageKEEP_ALIVEEl número de segundos para esperar las solicitudes en una conexión Keep-Alive.
Lea más al respecto en los documentos de Gunicorn: Keepalive.
Por defecto, establezca en 2 .
Puedes configurarlo como:
docker run -d -p 80:8080 -e KEEP_ALIVE= " 20 " myimageGRACEFUL_TIMEOUTTiempo de espera para los trabajadores elegantes reinicie.
Lea más al respecto en los documentos de Gunicorn: Tiempo de tiempo elegante.
Por defecto, establezca en 120 .
Puedes configurarlo como:
docker run -d -p 80:8080 -e GRACEFUL_TIMEOUT= " 20 " myimageACCESS_LOGEl archivo de registro de acceso para escribir.
Por defecto "-" , que significa stdout (imprima en los registros de Docker).
Si desea deshabilitar ACCESS_LOG , configúrelo en un valor vacío.
Por ejemplo, puede deshabilitarlo con:
docker run -d -p 80:8080 -e ACCESS_LOG= myimageERROR_LOGEl archivo de registro de errores para escribir.
Por defecto "-" , que significa stderr (imprima en los registros de Docker).
Si desea deshabilitar ERROR_LOG , configúrelo en un valor vacío.
Por ejemplo, puede deshabilitarlo con:
docker run -d -p 80:8080 -e ERROR_LOG= myimageGUNICORN_CMD_ARGS Cualquier configuración de línea de comandos adicional para Gunicorn se puede pasar en la variable de entorno GUNICORN_CMD_ARGS .
Lea más al respecto en Gunicorn Docs: Configuración.
Estas configuraciones tendrán precedencia sobre las otras variables de entorno y cualquier archivo de configuración de Gunicorn.
Por ejemplo, si tiene un certificado TLS/SSL personalizado que desea usar, puede copiarlos en la imagen Docker o montarlos en el contenedor, y establecer --keyfile y --certfile a la ubicación de los archivos, por ejemplo:
docker run -d -p 80:8080 -e GUNICORN_CMD_ARGS= " --keyfile=/secrets/key.pem --certfile=/secrets/cert.pem " -e PORT=443 myimageNota : En lugar de manejar TLS/SSL usted mismo y configurarlo en el contenedor, se recomienda usar un "proxy de terminación TLS" como Traefik. Puede leer más al respecto en la documentación de Fastapi sobre HTTPS.
PRE_START_PATHEl camino donde encontrar el script previo al inicio.
De forma predeterminada, establezca en /app/prestart.sh .
Puedes configurarlo como:
docker run -d -p 80:8080 -e PRE_START_PATH= " /custom/script.sh " myimage La imagen incluye un archivo de configuración predeterminado de Gunicorn Python en /gunicorn_conf.py .
Utiliza las variables de entorno declaradas anteriormente para establecer todas las configuraciones.
Puede anularlo incluyendo un archivo en:
/app/gunicorn_conf.py/app/app/gunicorn_conf.py/gunicorn_conf.py/app/prestart.sh Si necesita ejecutar algo antes de comenzar la aplicación, puede agregar un archivo prestart.sh al directorio /app . La imagen detectará y ejecutará automáticamente antes de comenzar todo.
Por ejemplo, si desea agregar migraciones SQL alembic (con sqlalchemy), puede crear un archivo ./app/prestart.sh en su directorio de código (que será copiado por su Dockerfile ) con:
#! /usr/bin/env bash
# Let the DB start
sleep 10 ;
# Run migrations
alembic upgrade head Y esperaría 10 segundos para darle a la base de datos algo de tiempo para comenzar y luego ejecutar ese comando alembic .
Si necesita ejecutar un script de Python antes de comenzar la aplicación, puede hacer que el archivo /app/prestart.sh ejecute su script Python, con algo así como:
#! /usr/bin/env bash
# Run custom Python script before starting
python /app/my_custom_prestart_script.py Puede personalizar la ubicación del script Prestart con la variable de entorno PRE_START_PATH descrita anteriormente.
El programa predeterminado que se ejecuta es AT /start.sh . Hace todo lo descrito anteriormente.
También hay una versión para el desarrollo con relieve automática en vivo en:
/start-reload.shPara el desarrollo, es útil poder montar el contenido del código de aplicación dentro del contenedor como un "volumen de host" de Docker, para poder cambiar el código y probarlo en vivo, sin tener que construir la imagen cada vez.
En ese caso, también es útil ejecutar el servidor con la retargada automática en vivo, de modo que se reinicie automáticamente en cada cambio de código.
El script /start-reload.sh adicional ejecuta Uvicorn solo (sin Gunicorn) y en un solo proceso.
Es ideal para el desarrollo.
Por ejemplo, en lugar de ejecutar:
docker run -d -p 80:80 myimagePodrías correr:
docker run -d -p 80:80 -v $( pwd ) :/app myimage /start-reload.sh-v $(pwd):/app : significa que el directorio $(pwd) debe montarse como un volumen dentro del contenedor AT /app .$(pwd) : ejecuta pwd ("Directorio de trabajo de impresión") y lo pone como parte de la cadena./start-reload.sh : Agregar algo (como /start-reload.sh ) al final del comando, reemplaza el "comando" predeterminado con este. En este caso, reemplaza el valor predeterminado ( /start.sh ) con la alternativa de desarrollo /start-reload.sh . AS /start-reload.sh no se ejecuta con Gunicorn, cualquiera de las configuraciones que coloca en un archivo gunicorn_conf.py no se aplicará.
Pero estas variables de entorno funcionarán lo mismo que se describió anteriormente:
MODULE_NAMEVARIABLE_NAMEAPP_MODULEHOSTPORTLOG_LEVEL En resumen: probablemente no debería usar Alpine para proyectos de Python, sino que use las versiones de imagen slim Docker.
¿Quieres más detalles? ¿Continuar leyendo?
Alpine es más útil para otros idiomas donde construye un binario estático en una etapa de imagen de Docker (usando el edificio Docker de varias etapas) y luego copie a una imagen alpina simple, y luego simplemente ejecute ese binario. Por ejemplo, usando Go.
Pero para Python, ya que Alpine no usa las herramientas estándar utilizadas para construir extensiones de Python, al instalar paquetes, en muchos casos Python ( pip ) no encontrará un paquete instalable precompilado (una "rueda") para alpine. Y después de depurar muchos errores extraños, se dará cuenta de que debe instalar muchas herramientas adicionales y construir muchas dependencias solo para usar algunos de estos paquetes de Python comunes. ?
Esto significa que, aunque la imagen alpina original podría haber sido pequeña, termina con una imagen con un tamaño comparable al tamaño que habría obtenido si hubiera usado una imagen de Python estándar (basada en Debian) o en algunos casos aún más grande. ?
Y en todos esos casos, llevará mucho más tiempo construir, consumir muchos más recursos, construir dependencias durante más tiempo y también aumentar su huella de carbono, ya que está utilizando más tiempo y energía de CPU para cada construcción. ?
Si desea imágenes delgadas de Python, debe intentar usar las versiones slim que todavía se basan en Debian, pero que son más pequeñas. ?
Se prueban todas las etiquetas de imagen, configuraciones, variables de entorno y opciones de aplicación.
*.pyc con PYTHONDONTWRITEBYTECODE=1 y asegúrese de que los registros se impriman inmediatamente con PYTHONUNBUFFERED=1 . PR #192 por @estebanx64. EXPOSE los puertos 80 y 443 de forma predeterminada, ya que pueden personalizarse. PR #238 por @Tiangolo. --workers . PR #225 por @Tiangolo. issue-manager.yml . PR #237 por @Tiangolo.latest-changes . PR #236 por @Tiangolo.latest-changes.yml . PR #198 por @alejsdev.arm64 (por ejemplo, Mac M1). PR #195 por @Tiangolo. README.md . PR #197 por @alejsdev. Los aspectos más destacados de este lanzamiento son:
python3.6-2022-11-25 .slim . PR #40.WORKER_CLASSTIMEOUTKEEP_ALIVEGRACEFUL_TIMEOUTACCESS_LOGERROR_LOGGUNICORN_CMD_ARGSMAX_WORKERSpip Cache durante la instalación con --no-cache-dir . PR #13 por @PMAV99.PRE_START_PATH env su personalizado. PR #30.PRE_START_PATH env var. PR #12 por @mgfinch.tiangolo/uvicorn-gunicorn:python3.7-2019-10-15 . PR #15./dev/shm para mejorar el rendimiento. PR #9 por @wshayes./start-reload.sh , consulte la documentación actualizada. PR #6.WORKERS_PER_CORE de forma predeterminada en 1 , ya que muestra tener el mejor rendimiento en puntos de referencia.WEB_CONCURRENCY , hasta un mínimo de 2 trabajadores. Esto es para evitar aplicaciones de mal rendimiento y bloqueo (aplicación del servidor) en máquinas pequeñas (máquina del servidor/nube/etc.). Esto se puede anular utilizando WEB_CONCURRENCY . Esto se aplica, por ejemplo, en el caso en que WORKERS_PER_CORE se establece en 1 (el valor predeterminado) y el servidor tiene solo 1 CPU Core. PR #5./start.sh ejecutar independientemente, leer y generar variables de entorno predeterminadas utilizadas. Y eliminar /entrypoint.sh ya que no modifica nada en el sistema, solo lee variables de entorno. PR #4./app/prestart.sh . Este proyecto tiene licencia bajo los términos de la licencia MIT.