Giter VIP home page Giter VIP logo

tiangolo / uwsgi-nginx-docker Goto Github PK

View Code? Open in Web Editor NEW
634.0 17.0 286.0 319 KB

Docker image with uWSGI and Nginx for applications in Python (as Flask) in a single container.

Home Page: https://hub.docker.com/r/tiangolo/uwsgi-nginx/

License: Apache License 2.0

Python 58.05% Shell 17.49% Dockerfile 24.46%
uwsgi-nginx docker-image python-application uwsgi nginx python web web-app webapp server

uwsgi-nginx-docker's Introduction

Test Deploy

Supported tags and respective Dockerfile links

Deprecated tags

🚨 These tags are no longer supported or maintained, they are removed from the GitHub repository, but the last versions pushed might still be available in Docker Hub if anyone has been pulling them:

  • python3.8-alpine
  • python3.6
  • python2.7

The last date tags for these versions are:

  • python3.8-alpine-2024-03-11
  • python3.6-2022-11-25
  • python2.7-2022-11-25

Note: There are tags for each build date. If you need to "pin" the Docker image version you use, you can select one of those tags. E.g. tiangolo/uwsgi-nginx:python3.7-2019-09-28.

uwsgi-nginx

Docker image with uWSGI and Nginx for web applications in Python (as Flask) in a single container.

Description

This Docker image allows you to create Python web applications that run with uWSGI and Nginx in a single container.

The combination of uWSGI with Nginx is a common way to deploy Python web applications like Flask and Django. It is widely used in the industry and would give you decent performance. (*)

This image was created to be the base image for tiangolo/uwsgi-nginx-flask but could be used as the base image for any other (WSGI-based) Python web application, like Django.

* Note on performance and features

If you are starting a new project, you might benefit from a newer and faster framework based on ASGI instead of WSGI (Flask and Django are WSGI-based).

You could use an ASGI framework like:

FastAPI, or Starlette, would give you about 800% (8x) the performance achievable with this image (tiangolo/uwsgi-nginx). You can see the third-party benchmarks here.

Also, if you want to use new technologies like WebSockets it would be easier (and possible) with a newer framework based on ASGI, like FastAPI or Starlette. As the standard ASGI was designed to be able to handle asynchronous code like the one needed for WebSockets.

If you need a WSGI-based application (like Flask or Django)

If you need to use an older WSGI-based framework like Flask or Django (instead of something based on ASGI) and you need to have the best performance possible, you can use the alternative image: tiangolo/meinheld-gunicorn.

tiangolo/meinheld-gunicorn will give you about 400% (4x) the performance of this image.


GitHub repo: https://github.com/tiangolo/uwsgi-nginx-docker

Docker Hub image: https://hub.docker.com/r/tiangolo/uwsgi-nginx/

🚨 WARNING: You Probably Don't Need this Docker Image

You are probably using Kubernetes or similar tools. In that case, you probably don't need this image (or any other similar base image). You are probably better off building a Docker image from scratch.


If you have a cluster of machines with Kubernetes, Docker Swarm Mode, Nomad, or other similar complex system to manage distributed containers on multiple machines, then you will probably want to handle replication at the cluster level instead of using a process manager in each container that starts multiple worker processes, which is what this Docker image does.

In those cases (e.g. using Kubernetes) you would probably want to build a Docker image from scratch, installing your dependencies, and running a single process instead of this image.

For example, using Gunicorn you could have a file app/gunicorn_conf.py with:

# Gunicorn config variables
loglevel = "info"
errorlog = "-"  # stderr
accesslog = "-"  # stdout
worker_tmp_dir = "/dev/shm"
graceful_timeout = 120
timeout = 120
keepalive = 5
threads = 3

And then you could have a Dockerfile with:

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 ["gunicorn", "--conf", "app/gunicorn_conf.py", "--bind", "0.0.0.0:80", "app.main:app"]

You can read more about these ideas in the FastAPI documentation about: FastAPI in Containers - Docker as the same ideas would apply to other web applications in containers.

When to Use this Docker Image

A Simple App

You could want a process manager running multiple worker processes in the container if your application is simple enough that you don't need (at least not yet) to fine-tune the number of processes too much, and you can just use an automated default, and you are running it on a single server, not a cluster.

Docker Compose

You could be deploying to a single server (not a cluster) with Docker Compose, so you wouldn't have an easy way to manage replication of containers (with Docker Compose) while preserving the shared network and load balancing.

Then you could want to have a single container with a process manager starting several worker processes inside, as this Docker image does.

Prometheus and Other Reasons

You could also have other reasons that would make it easier to have a single container with multiple processes instead of having multiple containers with a single process in each of them.

For example (depending on your setup) you could have some tool like a Prometheus exporter in the same container that should have access to each of the requests that come.

In this case, if you had multiple containers, by default, when Prometheus came to read the metrics, it would get the ones for a single container each time (for the container that handled that particular request), instead of getting the accumulated metrics for all the replicated containers.

Then, in that case, it could be simpler to have one container with multiple processes, and a local tool (e.g. a Prometheus exporter) on the same container collecting Prometheus metrics for all the internal processes and exposing those metrics on that single container.


Read more about it all in the FastAPI documentation about: FastAPI in Containers - Docker, as the same concepts apply to other web applications in containers.

How to use

You don't have to clone this repo.

You can use this image as a base image for other images.

Assuming you have a file requirements.txt, you could have a Dockerfile like this:

FROM tiangolo/uwsgi-nginx:python3.11

COPY ./requirements.txt /app/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt

COPY ./app /app

# Your Dockerfile code...
  • By default it will try to find a uWSGI config file in /app/uwsgi.ini.

  • That uwsgi.ini file will make it try to run a Python file in /app/main.py.

If you are building a Flask web application you should use instead tiangolo/uwsgi-nginx-flask.

Advanced usage

Custom app directory

If you need to use a directory for your app different than /app, you can override the uWSGI config file path with an environment variable UWSGI_INI, and put your custom uwsgi.ini file there.

For example, if you needed to have your application directory in /application instead of /app, your Dockerfile would look like:

FROM tiangolo/uwsgi-nginx:python3.11

ENV UWSGI_INI /application/uwsgi.ini

COPY ./application /application
WORKDIR /appapplication

And your uwsgi.ini file in ./application/uwsgi.ini would contain:

[uwsgi]
wsgi-file=/application/main.py

Note: it's important to include the WORKDIR option, otherwise uWSGI will start the application in /app.

Custom uWSGI process number

By default, the image starts with 2 uWSGI processes running. When the server is experiencing a high load, it creates up to 16 uWSGI processes to handle it on demand.

If you need to configure these numbers you can use environment variables.

The starting number of uWSGI processes is controlled by the variable UWSGI_CHEAPER, by default set to 2.

The maximum number of uWSGI processes is controlled by the variable UWSGI_PROCESSES, by default set to 16.

Have in mind that UWSGI_CHEAPER must be lower than UWSGI_PROCESSES.

So, if, for example, you need to start with 4 processes and grow to a maximum of 64, your Dockerfile could look like:

FROM tiangolo/uwsgi-nginx:python3.11

ENV UWSGI_CHEAPER 4
ENV UWSGI_PROCESSES 64

COPY ./app /app

Custom max upload size

In this image, Nginx is configured to allow unlimited upload file sizes. This is done because by default a simple Python server would allow that, so that's the simplest behavior a developer would expect.

If you need to restrict the maximum upload size in Nginx, you can add an environment variable NGINX_MAX_UPLOAD and assign a value corresponding to the standard Nginx config client_max_body_size.

For example, if you wanted to set the maximum upload file size to 1 MB (the default in a normal Nginx installation), you would need to set the NGINX_MAX_UPLOAD environment variable to the value 1m. Then the image would take care of adding the corresponding configuration file (this is done by the entrypoint.sh).

So, your Dockerfile would look something like:

FROM tiangolo/uwsgi-nginx:python3.11

ENV NGINX_MAX_UPLOAD 1m

COPY ./app /app

Custom listen port

By default, the container made from this image will listen on port 80.

To change this behavior, set the LISTEN_PORT environment variable.

You might also need to create the respective EXPOSE Docker instruction.

You can do that in your Dockerfile, it would look something like:

FROM tiangolo/uwsgi-nginx:python3.11

ENV LISTEN_PORT 8080

EXPOSE 8080

COPY ./app /app

Custom /app/prestart.sh

If you need to run anything before starting the app, you can add a file prestart.sh to the directory /app. The image will automatically detect and run it before starting everything.

For example, if you want to add database migrations that are run on startup (e.g. with Alembic, or Django migrations), before starting the app, you could create a ./app/prestart.sh file in your code directory (that will be copied by your Dockerfile) with:

#! /usr/bin/env bash

# Let the DB start
sleep 10;
# Run migrations
alembic upgrade head

and it would wait 10 seconds to give the database some time to start and then run that alembic command (you could update that to run Django migrations or any other tool you need).

If you need to run a Python script before starting the app, you could make the /app/prestart.sh file run your Python script, with something like:

#! /usr/bin/env bash

# Run custom Python script before starting
python /app/my_custom_prestart_script.py

Note: The image uses . to run the script (as in . /app/prestart.sh), so for example, environment variables would persist. If you don't understand the previous sentence, you probably don't need it.

Custom Nginx processes number

By default, Nginx will start one "worker process".

If you want to set a different number of Nginx worker processes you can use the environment variable NGINX_WORKER_PROCESSES.

You can use a specific single number, e.g.:

ENV NGINX_WORKER_PROCESSES 2

or you can set it to the keyword auto and it will try to autodetect the number of CPUs available and use that for the number of workers.

For example, using auto, your Dockerfile could look like:

FROM tiangolo/uwsgi-nginx:python3.11

ENV NGINX_WORKER_PROCESSES auto

COPY ./app /app

Custom Nginx maximum connections per worker

By default, Nginx will start with a maximum limit of 1024 connections per worker.

If you want to set a different number you can use the environment variable NGINX_WORKER_CONNECTIONS, e.g:

ENV NGINX_WORKER_CONNECTIONS 2048

It cannot exceed the current limit on the maximum number of open files. See how to configure it in the next section.

Custom Nginx maximum open files

The number connections per Nginx worker cannot exceed the limit on the maximum number of open files.

You can change the limit of open files with the environment variable NGINX_WORKER_OPEN_FILES, e.g.:

ENV NGINX_WORKER_OPEN_FILES 2048

Customizing Nginx additional configurations

If you need to configure Nginx further, you can add *.conf files to /etc/nginx/conf.d/ in your Dockerfile.

Just have in mind that the default configurations are created during startup in a file at /etc/nginx/conf.d/nginx.conf and /etc/nginx/conf.d/upload.conf. So you shouldn't overwrite them. You should name your *.conf file with something different than nginx.conf or upload.conf, for example: custom.conf.

Note: if you are customizing Nginx, maybe copying configurations from a blog or a StackOverflow answer, have in mind that you probably need to use the configurations specific to uWSGI, instead of those for other modules, like for example, ngx_http_fastcgi_module.

Overriding Nginx configuration completely

If you need to configure Nginx even further, completely overriding the defaults, you can add a custom Nginx configuration to /app/nginx.conf.

It will be copied to /etc/nginx/nginx.conf and used instead of the generated one.

Have in mind that, in that case, this image won't generate any of the Nginx configurations, it will only copy and use your configuration file.

That means that all the environment variables described above that are specific to Nginx won't be used.

It also means that it won't use additional configurations from files in /etc/nginx/conf.d/*.conf, unless you explicitly have a section in your custom file /app/nginx.conf with:

include /etc/nginx/conf.d/*.conf;

If you want to add a custom /app/nginx.conf file but don't know where to start from, you can use the nginx.conf used for the tests and customize it or modify it further.

Technical details

The combination of uWSGI with Nginx is a common way to deploy Python web applications.

Roughly:

  • Nginx is a web server, it takes care of the HTTP connections and also can serve static files directly and more efficiently.

  • uWSGI is an application server, that's what runs your Python code and it talks with Nginx.

  • Your Python code has the actual web application, and is run by uWSGI.

This image takes advantage of already slim and optimized existing Docker images (based on Debian as recommended by Docker) and implements Docker best practices.

It uses the official Python Docker image, installs uWSGI and on top of that, with the least amount of modifications, adds the official Nginx image (as of 2016-02-14).

And it controls all these processes with Supervisord.


There's the rule of thumb that you should have "one process per container".

That helps, for example, isolating an app and its database in different containers.

But if you want to have a "micro-services" approach you may want to have more than one process in one container if they are all related to the same "service", and you may want to include your Flask code, uWSGI and Nginx in the same container (and maybe run another container with your database).

That's the approach taken in this image.


This image has a default sample "Hello World" app in the container's /app directory using the example in the uWSGI documentation.

You probably want to override it or delete it in your project.

It is there in case you run this image by itself and not as a base image for your own Dockerfile, so that you get a sample app without errors.

🚨 Alpine Python Warning

In short: You probably shouldn't use Alpine for Python projects, instead use the slim Docker image versions.


Do you want more details? Continue reading 👇

Alpine is more useful for other languages where you build a static binary in one Docker image stage (using multi-stage Docker building) and then copy it to a simple Alpine image, and then just execute that binary. For example, using Go.

But for Python, as Alpine doesn't use the standard tooling used for building Python extensions, when installing packages, in many cases Python (pip) won't find a precompiled installable package (a "wheel") for Alpine. And after debugging lots of strange errors you will realize that you have to install a lot of extra tooling and build a lot of dependencies just to use some of these common Python packages. 😩

This means that, although the original Alpine image might have been small, you end up with a an image with a size comparable to the size you would have gotten if you had just used a standard Python image (based on Debian), or in some cases even larger. 🤯

And in all those cases, it will take much longer to build, consuming much more resources, building dependencies for longer, and also increasing its carbon footprint, as you are using more CPU time and energy for each build. 🌳

If you want slim Python images, you should instead try and use the slim versions that are still based on Debian, but are smaller. 🤓

Tests

All the image tags, configurations, environment variables and application options are tested.

Updates

Updates are announced in the releases.

You can click the "watch" button at the top right and select "Releases only" to receive an email notification when there's a new release.

Release Notes

Latest Changes

Features

  • 🔧 Avoid creating unnecessary *.pyc files with PYTHONDONTWRITEBYTECODE=1 and ensure logs are printed immediately with PYTHONUNBUFFERED=1. PR #208 by @estebanx64.

Internal

  • 🔧 Add GitHub templates for discussions and issues, and security policy. PR #203 by @alejsdev.
  • 🔧 Update latest-changes.yml. PR #201 by @alejsdev.

2.1.0

Features

  • ✨ Add support for multiarch builds, including ARM (e.g. Mac M1). PR #200 by @tiangolo.

Refactors

Upgrades

Docs

Internal

2.0.0

Highlights of this release:

  • Support for Python 3.10, 3.11, and 3.9.
  • Deprecation of Python 3.6 and 2.7.
    • The last Python 3.6 and 2.7 images are available in Docker Hub, but they won't be updated or maintained anymore.
    • The last images with a date tag are python3.6-2022-11-25 and python2.7-2022-11-25.
  • Upgraded versions of all the dependencies.
  • Small improvements and fixes.

Features

  • ✨ Add support for Python 3.11. PR #171 by @tiangolo.
  • ✨ Add support for Python 3.10 and upgrade uWSGI to 2.0.20. PR #127 by @tiangolo.
  • ⬆️ Update pip install command with flag --no-cache-dir to reduce disk used. PR #120 by @tiangolo.
  • ✨ Quit Supervisor on errors, to allow orchestrators to handle it. PR #110 by @tiangolo.
  • ✨ Add Python 3.9. PR #101 by @sjadema.

Breaking Changes

Upgrades

  • ⬆️ Upgrade Nginx to the latest version 1.23.2, and Debian to bullseye. PR #163 by @tiangolo.
  • ⬆️ Bump uwsgi from 2.0.20 to 2.0.21. PR #159 by @dependabot[bot].
  • ⬆ Upgrade Nginx to version 1.21.6 and Alpine to version 3.13. PR #148 by @haley-comet.
  • ⬆ Upgrade Nginx to the latest version of the official images. PR #107 by @tiangolo.

Docs

  • 📝 Add note to discourage Alpine with Python. PR #124 by @tiangolo.
  • 📝 Add Kubernetes warning, when to use this image. PR #122 by @tiangolo.
  • ✏️ Fix typo duplicate "Note" in Readme. PR #121 by @tiangolo.
  • 🐛 Fix broken link to TechEmpower benchmarks. PR #96 by @tiangolo.

Internal

1.4.0

  • Add GitHub Sponsors button.
  • Add new image for Python 3.8, and new image for Python 3.8 on Alpine. PR #83.
  • Upgrade Nginx to latest version, 1.17.10, based on latest Debian, Buster. PR #82.
  • Remove support for Python 3.5. PR #81.

1.3.0

  • This is the last version to support:
    • Debian Stretch (before upgrading to Buster).
    • Python 3.5.
    • Alpine 3.7, 3.8, 3.9 (before upgrading to Alpine 3.11).
    • Alpine in older versions of Python, 2.7 and 3.6 (Before upgrading to Python 3.8).
    • If you need any of those, make sure to use a tag for the build date 2020-05-04.
  • Refactor build set up:
    • Re-use code and configs.
    • Migrate to GitHub Actions.
    • Simplify tests.
    • PR #78.
  • Migrate Travis to .com, update badge. PR #77.

1.2.0

  • 2019-10-14:

    • Refactor and simplify test scripts. PR #66.
  • 2019-09-28:

    • Refactor build scripts and add image tags for each build date, like tiangolo/uwsgi-nginx:python3.7-2019-09-28. PR #65.
  • Upgrade Travis. PR #60.

1.1.0

1.0.0

  • 2019-05-04:

    • Add Alpine Linux 3.9. PR #55 by evilgoldfish.
    • Build images using Travis matrix to improve development/testing speed. Needed for some recent PRs. PR #58.
  • 2019-02-02:

    • The Nginx configurations are generated dynamically from the entrypoint, instead of modifying pre-existing files. PR #50.
    • Support for a completely custom /app/nginx.conf file that overrides the generated one. PR #51.
  • 2018-11-23: New Alpine 3.8 images for Python 2.7, Python 3.6 and Python 3.7 (Python 3.7 temporarily disabled). Thanks to philippfreyer in PR #45

  • 2018-09-22: New Python 3.7 versions, standard and Alpine based. Thanks to desaintmartin in this PR.

  • 2018-06-22: You can now use NGINX_WORKER_CONNECTIONS to set the maximum number of Nginx worker connections and NGINX_WORKER_OPEN_FILES to set the maximum number of open files. Thanks to ronlut in this PR.

  • 2018-06-22: Make uWSGI require an app to run, instead of going in "full dynamic mode" while there was an error. Supervisord doesn't terminate itself but tries to restart uWSGI and shows the errors. Uses need-app as suggested by luckydonald in this comment.

  • 2018-06-22: Correctly handled graceful shutdown of uWSGI and Nginx. Thanks to desaintmartin in this PR.

  • 2018-02-04: It's now possible to set the number of Nginx worker processes with the environment variable NGINX_WORKER_PROCESSES. Thanks to naktinis in this PR.

  • 2018-01-14: There are now two Alpine based versions, python2.7-alpine3.7 and python3.6-alpine3.7.

  • 2017-12-08: Now you can configure which port the container should listen on, using the environment variable LISTEN_PORT thanks to tmshn in this PR.

  • 2017-08-09: You can set a custom maximum upload file size using an environment variable NGINX_MAX_UPLOAD, by default it has a value of 0, that allows unlimited upload file sizes. This differs from Nginx's default value of 1 MB. It's configured this way because that's the simplest experience a developer that is not expert in Nginx would expect.

  • 2017-08-09: Now you can override where to look for the uwsgi.ini file, and with that, change the default directory from /app to something else, using the envirnoment variable UWSGI_INI.

  • 2017-08-08: There's a new latest tag image, just to show a warning for those still using latest for Python 2.7 web applications. As of now, everyone should be using Python 3.

  • 2017-08-08: Supervisord now terminates uWSGI on SIGTERM, so if you run docker stop or something similar, it will actually stop everything, instead of waiting for Docker's timeout to kill the container.

  • 2017-07-31: There's now an image tag for Python 3.6, based on the official image for Python 3.6 thanks to jrd in this PR.

  • 2016-10-01: Now you can override default uwsgi.ini parameters from the file in /app/uwsgi.ini.

  • 2016-08-16: There's now an image tag for Python 3.5, based on the official image for Python 3.5. So now you can use this image for your projects in Python 2.7 and Python 3.5.

  • 2016-08-16: Use dynamic a number of worker processes for uWSGI, from 2 to 16 depending on load. This should work for most cases. This helps especially when there are some responses that are slow and take some time to be generated, this change allows all the other responses to keep fast (in a new process) without having to wait for the first (slow) one to finish.

  • Also, it now uses a base uwsgi.ini file under /etc/uwsgi/ with most of the general configurations, so, the uwsgi.ini inside /app (the one you could need to modify) is now a lot simpler.

  • 2016-04-05: Nginx and uWSGI logs are now redirected to stdout, allowing to use docker logs.

License

This project is licensed under the terms of the Apache license.

uwsgi-nginx-docker's People

Contributors

alejsdev avatar dependabot[bot] avatar desaintmartin avatar ehaca avatar estebanx64 avatar jkatzhrs avatar jrd avatar mariacamilagl avatar naktinis avatar philippfreyer avatar ronlut avatar sjadema avatar tiangolo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uwsgi-nginx-docker's Issues

entrypoint.sh permission error on docker run

When i try to run my image (which i use this one as base) i get the following error:

docker: Error response from daemon: invalid header field value "oci runtime error: container_linux.go:247: starting container process caused "exec: \"/entrypoint.sh\": permission denied"\n".

I tried to add "RUN chmod +x /entrypoint.sh" since some people said this solved there problem in other projects, but that didn't work for me.

My docker file:
FROM tiangolo/uwsgi-nginx:python2.7
COPY configs/nginx.conf /etc/nginx/conf.d/

Copy sample app

COPY ./ /app

#install requirements
RUN pip install -r requirements.txt

ENV PRODUCTION_ENV 1

EXPOSE 5050

NGINX_WORKER_PROCESSES not being respected.

If I set:
ENV NGINX_WORKER_PROCESSES auto

The output from the logs only shows two workers, even though I have 8 CPU cores available:

detected number of CPU cores: 8
current working directory: /app
detected binary path: /usr/local/bin/uwsgi
your memory page size is 4096 bytes
detected max file descriptor number: 1048576
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to UNIX address /tmp/uwsgi.sock fd 3
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
Python version: 3.7.4 (default, Sep 12 2019, 16:02:06)  [GCC 6.3.0 20170516]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x55ffff39bf90
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 1239640 bytes (1210 KB) for 16 cores
*** Operational MODE: preforking ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x55ffff39bf90 pid: 10 (default app)
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) *** 
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 10)
spawned uWSGI worker 1 (pid: 33, cores: 1)
spawned uWSGI worker 2 (pid: 34, cores: 1)

Is this expected?

Slim base image

Do you plan to use slim base image? Currently, python3.6 image takes 960 Mb, but if build it from python:3.6-slim-stretch base image, image results in only 431 Mb - more than twice smaller. Further compacting is possible if remove build-essentials after uwsgi install - it can cut some hundred Mb more

Are UWSGI_CHEAPER and UWSGI_PROCESSES being used?

I see the following in Dockerfile:

# Copy the base uWSGI ini file to enable default dynamic uwsgi process number
COPY uwsgi.ini /etc/uwsgi/
...
# By default, run 2 processes
ENV UWSGI_CHEAPER 2
# By default, when on demand, run up to 16 processes
ENV UWSGI_PROCESSES 16

...but so far can't find these ENV vars being referenced anywhere. Perhaps its just a misunderstanding on my part. I don't see them being used in the uwsgi script line in the supervisord conf either. Perhaps UWSGI itself magically looks for these variables, but I didn't see that document in the UWSGI docs either.

Commit 062ee99 breaks pip install SSL SSL: CERTIFICATE_VERIFY_FAILED

Since commit 062ee99 (12 hours ago) our docker builds have been failing and i narrowed it down to this commit. I reverted the commit, published a new image: https://hub.docker.com/r/trycom/uwsgi-nginx-docker/tags/ and used that instead and everything worked as normal.

To reproduce, simply create a Dockerfile

FROM tiangolo/uwsgi-nginx:python3.6
RUN pip install requests=2.11.1
RUN pip install googlemaps

and you'll get the error when attempting to pip install googlemaps. Yesterday this used to work, so having published a reverted image you can do the following to see expected results:

FROM trycom/uwsgi-nginx-docker:39f6fdb
RUN pip install requests=2.11.1
RUN pip install googlemaps

Also, as a separate comment, you should tag your docker images with the commit so we dont have to publish our own reverted versions

SSH Issues since your last update (12 days ago)

Hi there!
Thank you very much for your base docker image!

We are using your docker image for our microservice architecture (especially our python services) and have major issues connecting to a SSH port for our application.

Before you updated the image 12 days ago everything worked like a charm. But now we have some serious issues, because every SSH interaction is not working properly anymore.

Can you help us figuring out why your image isn't providing a service with SSH anymore?

Thank you very much in advance. And thanks a lot for your work!

Kind regards from Germany, Osnabrück.
Lennart Blom

Missing nginx.conf

The root of this project doesn't have an nginx.conf file.

So the Dockerfile command: COPY nginx.conf /etc/nginx/conf.d/ fails.
COPY failed: stat /var/lib/docker/tmp/docker-builder489751094/nginx.conf: no such file or directory

Changing `worker_processes` value in nginx configuration

In the default /etc/nginx/nginx.conf worker_processes is set to 1. However, I'd like to change this value.

I would suggest one of these approaches:

  1. set the value to auto (so it is set to the number of CPU cores)
  2. create an ENV variable NGINX_WORKER_PROCESSES (which can be set in Dockerfiles) and which is written into the config.

python3.7 container throwing permission errors

I had to rebuild my container with some new code deployment and for some reason its now throwing a permission error trying to copy the nginx.conf file. I dont provide a custom one, nor do I try to run as a non-root user:

/entrypoint.sh: 45: /entrypoint.sh: cannot create /etc/nginx/nginx.conf: Permission denied

Any ideas as to why this might be happening?

Python 3.7

Would be great to have a Python 3.7 version of this Docker.
Thanks for the nice project :)

Request: add few more tags

Would love to see some more generic tags.

My thoughts are the addition of:
stable - the most stable version (so latest may not be stable, IE for bleeding edge versions of OS, python, uwsgi, etc.)
alpine-stable - the stable version of alpine
alpine-latest - the latest alpine version (which may also not be stable)

Thanks for the consideration and the images.

`GLIBC_2.27' not found (required by /usr/local/bin/uwsgi)

I can't get this container running, unfortunately ..
I'm trying to use tiangolo/uwsgi-nginx:python3.7, but always when starting the container I receive the following:

/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.27' not found (required by /usr/local/bin/uwsgi)
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /usr/local/bin/uwsgi)
2019-11-27 13:31:41,983 INFO exited: uwsgi (exit status 1; not expected)
2019-11-27 13:31:42,987 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2019-11-27 13:31:42,990 INFO spawned: 'uwsgi' with pid 11
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.27' not found (required by /usr/local/bin/uwsgi)
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /usr/local/bin/uwsgi)
2019-11-27 13:31:42,998 INFO exited: uwsgi (exit status 1; not expected)
2019-11-27 13:31:45,009 INFO spawned: 'uwsgi' with pid 12
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.27' not found (required by /usr/local/bin/uwsgi)
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /usr/local/bin/uwsgi)
2019-11-27 13:31:45,018 INFO exited: uwsgi (exit status 1; not expected)
2019-11-27 13:31:48,030 INFO spawned: 'uwsgi' with pid 13
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.27' not found (required by /usr/local/bin/uwsgi)
/usr/local/bin/uwsgi: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /usr/local/bin/uwsgi)
2019-11-27 13:31:48,039 INFO exited: uwsgi (exit status 1; not expected)

seems like a version miss-match?

Kill container on app start fail

I read this issue: tiangolo/uwsgi-nginx-flask-docker#3
It seems that setting need-app = true is not enough to kill the container, as supervisor keeps on restarting the app.
Please consider adding autoresetart=false in supervisord.conf section for uwsgi, or to make these easily configurable in other some way.
To have supervisor actually kill the container you'd have to set up some more configuration, see:
https://serverfault.com/questions/760726/how-to-exit-all-supervisor-processes-if-one-exited-with-0-result

Update nginx to at least 1.16.1 for security fixes

There were some CVEs announced recently for Nginx which relate to Denial-of-Service vulnerabilities in HTTP/2 processing on older versions. All of the builds should be modified to use at least 1.16.1.

Here are the vulnerability details:

  • A denial of service vulnerability exists in the HTTP/2 protocol stack due to improper handling of exceptional conditions. An unauthenticated, remote attacker can exploit this, by manipulating the window size and stream priority of a large data request, to cause a denial of service condition. (CVE-2019-9511)

  • A denial of service vulnerability exists in the HTTP/2 protocol stack due to improper handling of exceptional conditions. An unauthenticated, remote attacker can exploit this, by creating multiple request streams and continually shuffling the priority of the streams, to cause a denial of service condition. (CVE-2019-9513)

  • A denial of service vulnerability exists in the HTTP/2 protocol stack due to improper handling of exceptional conditions. An unauthenticated, remote attacker can exploit this, by sending a stream of headers with a zero length header name and zero length header value, to cause a denial of service condition. (CVE-2019-9516)

https://www.tenable.com/plugins/nessus/127907

build failed : uwsgi-nginx-docker/python3.6/Dockerfile

build with docker-compose up -d

Step 13/27 : COPY uwsgi.ini /etc/uwsgi/
ERROR: Service 'api-server' failed to build: COPY failed: stat /var/lib/docker/tmp/docker-builder834430273/uwsgi.ini: no such file or directory

What did I do wrong?

Nginx logs?

Hi, thanks for this image!
I could not see nginx logs. In my case they are redirected to stdout and stderr by default, so they should be visible in docker logs, but they are not. It seems to be an issue with supervisor: http://veithen.github.io/2015/01/08/supervisord-redirecting-stdout.html.
Adding the following to supervisord.conf works in my case:

[program:nginx]
(...)
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

invalid cheaper value: must be lower than processes

I'm using a custom uwsgi.ini file. And when I run it on this flask version of the image I'm getting:

invalid cheaper value: must be lower than processes
...
root@46f39eb48cf2:/opt/app# printenv | grep UWSGI
UWSGI_CHEAPER=2
UWSGI_PROCESSES=10

Enabling DataDog's ddtrace

We have a number of flask API's running as docker containers and using this as a base. We are in the process of implementing DataDog's ddtrace and need to call python as "ddtrace python3". Is there a way to hijack the entrypoint to do this?

Unable to run multiple container instance of this image

When i am trying to run multiple container instance with this same image i am getting the following error.

Bind for 0.0.0.0:443 failed: port is already allocated

Is there any solution for this ?
how can we using something like nginx-proxy with this image ?

uwsgi + openssl 1.1 + psycopg2 bug

Hi!

I have been using your base image tiangolo/uwsgi-nginx:python3.6 for a long time with great results but recently I encountered the error described in the following link:
https://www.bountysource.com/issues/46820777-openssl-1-1-uwsgi-psycopg2-no-ciphers-error

Seems the ubuntu base image used is inheriting the same issue, I have no solution for the bug except changing to your Alpine base image where the problem doesn't occur. Just letting you know in case you know of a workaround or feel like downgrading the version of the affected packages until the issue is solved.

global uwsgi.ini from this docker overwrites custom properties of the app

I cannot overwrite all properties that are set in uwsgi-nginx-docker/python2.7/uwsgi.ini within my own uwsgi.ini, because in the supervisord.conf the order of loading the init files is "wrong". What other implications would it have to change the order to this:
command=/usr/local/bin/uwsgi --ini /etc/uwsgi/uwsgi.ini --ini /app/uwsgi.ini
?

('IM004', "[IM004] [unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed (0) (SQLDriverConnect)")

Hey guys,

I'm trying to leverage on this container to build my app with Django and MS SQL.

The prerequisite is of course to have the ODBC driver installed. So I did the below step in my Dockerfile:

RUN apt-get update && apt-get install -y ca-certificates \
    && curl -k https://packages.microsoft.com/keys/microsoft.asc | apt-key add - \
    && curl -k https://packages.microsoft.com/config/debian/10/prod.list > /etc/apt/sources.list.d/mssql-release.list \
    && apt-get update \
    && ACCEPT_EULA=Y apt-get -y install msodbcsql17 \
    && ACCEPT_EULA=Y apt-get -y install mssql-tools \
    && echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile \
    && echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc \
    && /bin/bash -c "source ~/.bashrc" \
    && apt-get install -y unixodbc-dev \
    && apt-get install -y libgssapi-krb5-2

This built the image perfectly. When I run it with Docker on my laptop, the app works fine. However, after deploying the image to Azure web app service, the below error happens.

('IM004', "[IM004] [unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed (0) (SQLDriverConnect)")

Really appreciate any help from you guys.

Support for additional supervisor programs

I'm currently looking into running your flask image (https://github.com/tiangolo/uwsgi-nginx-flask-docker) which is extended from this one. However, I would like to run an instance of celery (http://www.celeryproject.org/) within the same container (since it needs access to many of the same modules I define in my flask app).

I can do this by extending from your image and writing a new supervisor config based on the one in this repository, and adding my configuration for celery, but it would be really nice if the current version preemptively included additional supervisor configuration, e.g.:

[include]
files = /etc/supervisor/conf.d/*.conf

(taken from an idea here: https://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image-inheritance/). That way, your image could be extended, and any additional supervisor programs could be configured separately yet still run in the same container, without the need to duplicate and overwrite the existing config file.

Outdated link for "You can see the third-party benchmarks here" ?

Thanks a TON for this wonderful project! Just a minor issue in the docker hub page https://hub.docker.com/r/tiangolo/uwsgi-nginx/, the link for "You can see the third-party benchmarks here" leads to VB and F# frameworks.

outdated-link

You probably mean this: https://www.techempower.com/benchmarks/#section=test&runid=a979de55-980d-4721-a46f-77298b3f3923&hw=ph&test=fortune&l=z8kflr-v&a=2

Or even better, this:
https://www.techempower.com/benchmarks/#section=test&runid=a979de55-980d-4721-a46f-77298b3f3923&hw=ph&test=query&l=z8kflr-v&a=2

Python 3.8

Would love to see a python 3.8 version of this project :)

These are super nice images, they pair awesomely with traefik 👍

building uwsgi with SSL support

Hi, would it be possible to enable SSL support for uwsgi? Without SSL support, trying to establish websocket connections will lead to the worker crashing down.

I guess the modification should be something like

# Install uWSGI
RUN pip install uwsgi`

to

# uwsgi-ssl version (not tested)
RUN apt-get install libssl-dev
RUN UWSGI_PROFILE_OVERRIDE=ssl=true pip install uwsgi -I --no-cache-dir`

Also related: https://stackoverflow.com/questions/24183053/how-to-build-uwsgi-with-ssl-support-to-use-the-websocket-handshake-api-function

uwsgi reporting "no request plugin is loaded"

I'm trying to get a Django app working with uwsgi-nginx-docker as the base image. I can't get any response from the app, however, and uwsgi gives this warning:

!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!
no request plugin is loaded, you will not be able to manage requests.
you may need to install the package for your language of choice, or simply load it with --plugin.
!!!!!!!!!!! END OF WARNING !!!!!!!!!!

I can see from the Dockerfile that the image does a "RUN apk add --no-cache uwsgi-python", and that python3_plugin.so is in /usr/lib/uwsgi. Why isn't uwsgi picking it up? I'm curious why it's not in /usr/lib/uwsgi/plugins where I've normally seen it.

Thanks for any ideas on this one.

Unable to locate package gnupg1

I was trying to build the docker image of uwsgi-nginx-docker on top of the base image containing Ubuntu-16.04 & Python3.5.2.
I was getting an error E: Unable to locate package gnupg1
But when I run the corresponding command in my local system, gnupg1 gets installed.

What should I do to?

[feat] multi-arch support

this image works great.... nice-to-have would be multi arch manifest to support arm. I've tested manually and ARM64 builds clean.

Build failed

Hi! I tried to build this (python3.6-alpine3.7) dockerfile, because now I have poor Internet connection and can't pull it, and got an error while running gpg:

Fetching GPG key B0F4253373F8F6F510D42178520A9993A1C052F8 from ha.pool.sks-keyservers.net
gpg: keybox '/tmp/tmp.EoBIOd/pubring.kbx' created
gpg: keyserver receive failed: Address not available
Fetching GPG key B0F4253373F8F6F510D42178520A9993A1C052F8 from hkp://keyserver.ubuntu.com:80
gpg: key 520A9993A1C052F8: 6 signatures not checked due to missing keys
gpg: /tmp/tmp.EoBIOd/trustdb.gpg: trustdb created
gpg: key 520A9993A1C052F8: public key "Maxim Dounin <[email protected]>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1
gpg: Signature made Tue Dec 26 16:02:14 2017 UTC
gpg:                using RSA key 520A9993A1C052F8
gpg: Good signature from "Maxim Dounin <[email protected]>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: B0F4 2533 73F8 F6F5 10D4  2178 520A 9993 A1C0 52F8
rm: can't remove '/tmp/tmp.EoBIOd/S.gpg-agent.extra': No such file or directory
rm: can't remove '/tmp/tmp.EoBIOd/S.gpg-agent.ssh': No such file or directory

Maybe someone knows how to fix this?
Thanks

Setuptools warning

When I start tiangolo/uwsgi-nginx-flask:python3.7 I get the following warning:

Checking for script in /app/prestart.sh
Running script /app/prestart.sh
Running inside /app/prestart.sh, you could add migrations to this file, e.g.:

#! /usr/bin/env bash

# Let the DB start
sleep 10;
# Run migrations
alembic upgrade head

/app/pkg_resources/py2_warn.py:22: UserWarning: Setuptools will stop working on Python 2
************************************************************
You are running Setuptools on Python 2, which is no longer
supported and
>>> SETUPTOOLS WILL STOP WORKING <<<
in a subsequent release (no sooner than 2020-04-20).
Please ensure you are installing
Setuptools using pip 9.x or later or pin to `setuptools<45`
in your environment.
If you have done those things and are still encountering
this message, please comment in
https://github.com/pypa/setuptools/issues/1458
about the steps that led to this unsupported combination.
************************************************************
  sys.version_info < (3,) and warnings.warn(pre + "*" * 60 + msg + "*" * 60)

I believe this has to do with supervisor but it looks like supervisord version 4.1.0 is being used which is compatible with Python 3.4 and up. Anyone familiar with this issue and knows how to solve it?

SSL certificate problem

Having problems with ssl certificates on python3.7 image. Can be reproduced with:

~ docker run -it --rm tiangolo/uwsgi-nginx:python3.7 curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

worked fine with tiangolo/uwsgi-nginx:python3.7-2020-05-07

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.