Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/docker #2380

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open

Feat/docker #2380

wants to merge 22 commits into from

Conversation

nanaones
Copy link

If you are using a Docker container, you can deploy Django and Flask using Gunicorn.

The added files are one dockerfile and a start.sh file respectively
Packages that match the environment variables provided through the start.sh file are installed
If you are using a Docker container, you can deploy Django and Flask using Gunicorn
The config folder contains the scripts needed to set up the docker image
@jamadden
Copy link
Collaborator

Thanks for the PR. Is there a reason this wasn't put in the existing examples/ directory?

@nanaones
Copy link
Author

Thanks for the PR. Is there a reason this wasn't put in the existing examples/ directory?

Simple instructions are written in the README, but I will add more guides if needed.
What should I specifically add?

@jamadden
Copy link
Collaborator

No, I'm saying this is just an example. It should go in the existing examples/ directory. It should not be a new top-level directory.

@tilgovi
Copy link
Collaborator

tilgovi commented Jul 16, 2020

I have just a few thoughts, but I really appreciate this.

Should we commit to making all or most of our configuration possible to define through the environment? I think I would like that. It would remove the need for the script that builds the command line.

Should we provide the requirements files or let users handle that themselves? For Tornado, users should already have it as a requirement because I think they need to import its APIs. It is sometimes the case that users can write code that is worker agnostic, but other times there is a need to perform concurrent, non-blocking work within a single request and users then import and depend on gevent or eventlet directly already. If we didn't have the requirements files, then the dockerfile itself gets very small.

Building on this, we could have the dockerfile install the user-supplied requirements.txt, which should also contain the framework requirement.

Some users will need to apt-get install additional libraries for their applications to work, but I don't see a great way to handle that and maybe we shouldn't.

I think what I'm seeing from the PR, my comments, and the comment from @jamadden is that this is written as if it could be an official gunicorn quick-start image, but I worry that the set of users for whom that is practical is small. With some changes, I feel like an example becomes sufficient because configuring gunicorn through the environment would be easy enough that a fairly boilerplate dockerfile would be a better starting point than a stock image.

@@ -0,0 +1,17 @@
FROM python:3.8.4-slim
ENV PYTHONIOENCODING UTF-8
ARG DEBIAN_FRONTEND=noninteractive
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it reasonable for there to be any other choice here? If we're not running any apt commands in the dockerfile, do we even need this at all?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the expectation is that users will use this as a FROM image?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the expectation is that users will use this as a FROM image?

Yes, like this nginx image from dockerhub
https://hub.docker.com/_/nginx

Copy link
Author

@nanaones nanaones Jul 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7bf1f8b

ARG DEBIAN_FRONTEND=noninteractive has been deleted.


COPY ./config /config

ENV CONFIG_FILE_PATH=/config/config.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/work/gunicorn.conf.py would be the default location for this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5bc62af

If the user manually configures the gunicorn.conf.py file, adds gunicorn.conf.py to the docker container, and then enters the path to gunicorn.conf.py in the environment variable $CONFIG_FILE_PATH, the gunicorn runs based on the specified file.

pip3 install -r /config/sync-requirements.txt &&\
/config/install.sh

WORKDIR /work
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might prefer /app or /gunicorn. Is the expectation that users will volume mount this path or that they will use FROM and add their code to this path?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The set path is /work, but there is no problem even if the user uses a different path. Users can enter other environment variables to suit their environment.

So I put everything related to the settings in /config so that it doesn't overlap with the user's configuration.

@nanaones
Copy link
Author

No, I'm saying this is just an example. It should go in the existing examples/ directory. It should not be a new top-level directory.

This idea was benchmarked on Celery's Github. Like Celery, we put GunicornDockerimage in a new top-level directory that Gunicorn can officially support. I think you can put it in the /example folder as you said.

Django and Celery officially support Docker images.

Django
https://hub.docker.com/_/django

edit Dockerfile
delete DEBIAN_FRONTEND argument

edit install.sh
System environment $REQUIRENMENTS_FILE_PATH was added
When the user sets $REQUIRENMENTS_FILE_PATH, the container tries to install it as a pip requirements file
Added example of using REQUIRENMENTS_FILE_PATH in README
Users can record the framework and version they use in requirements file that records the package dependencies pointed to by the $REQUIRENMENTS_FILE_PATH environment variable.
async-requirements and sync-requirements files are merged an requirements file

dockerfile has been changed
Users can use the gunicorn configuration within the container by entering the location of the preconfigured gunicorn.conf.py file in the $CONFIG_FILE_PATH environment variable

A sample configuration file gunicorn.conf.py has been added
README.md file updated
Added description of environment value $CONFIG_FILE_PATH
@nanaones nanaones requested a review from tilgovi July 30, 2020 15:31
@benoitc
Copy link
Owner

benoitc commented Aug 26, 2020

@tilgovi what about having it in this week release. I like the idea. Btw any idea where we coudl host an "official" build? apparently docker hub has became too much restrictive in term of pricing. Thoughts?

@tilgovi
Copy link
Collaborator

tilgovi commented Aug 27, 2020

I don't think we should publish an image. The Django image that is referenced has been deprecated for reasons similar to my objection. A user likely needs their own requirements.txt anyway, so it doesn't help to pre-install Gunicorn in the image. That means the image is really just a Python image.

I think it's useful to have as an example, but I will leave a separate review comment asking for some changes.

We should not hold up release for this because I think most users will find the examples in the repository. They can be added after releasing.

Copy link
Collaborator

@tilgovi tilgovi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry that the config.sh script complicates the example and makes it less accessible as an educational tool. A gunicorn.conf.py file in the example that sets values from the environment directly might be more helpful. Something like this would also make sense in any kind of Gunicorn application template. This would be analogous to how the Rails templates install a Puma config that reads from the environment, but sets defaults: https://github.com/rails/rails/blob/6-0-stable/railties/lib/rails/generators/rails/app/templates/config/puma.rb.tt

I think the example can be simplified by removing REQUIREMENTS_FILE_PATH. It made sense when the idea was to ship a base image, because there was a separation between the user's requirements and the base requirements. I would just expect now a single requirements.txt in the work path.

I don't think a separation between /config and /work is helpful, nor is CONFIG_FILE_PATH. Gunicorn accepts an argument on the command line to set the config file path, so if the default execution is gunicorn then the user can docker run app --config <path>. The entrypoint script should not be necessary.

@benoitc
Copy link
Owner

benoitc commented Sep 17, 2020

@nanaones what do you think about the suggested change by @tilgovi ?

@benoitc
Copy link
Owner

benoitc commented Sep 17, 2020

I don't think we should publish an image. The Django image that is referenced has been deprecated for reasons similar to my objection. A user likely needs their own requirements.txt anyway, so it doesn't help to pre-install Gunicorn in the image. That means the image is really just a Python image.

I think it's useful to have as an example, but I will leave a separate review comment asking for some changes.

We should not hold up release for this because I think most users will find the examples in the repository. They can be added after releasing.

Fear enough. I will make the release today. I think it would be good anyway to have a good template for docker images, so anyone can install it. Including on windows for a basic dev environment. That would solve a lot of issues for some developers today that doesn't use UNIX / Linux systems.

@nanaones
Copy link
Author

@nanaones what do you think about the suggested change by @tilgovi ?

Sorry to answer now. I thought I was rejected because I didn't receive a reply longer than I thought.
I will post after modifying according to the above modifications.

@nanaones
Copy link
Author

I worry that the config.sh script complicates the example and makes it less accessible as an educational tool. A gunicorn.conf.py file in the example that sets values from the environment directly might be more helpful. Something like this would also make sense in any kind of Gunicorn application template. This would be analogous to how the Rails templates install a Puma config that reads from the environment, but sets defaults: https://github.com/rails/rails/blob/6-0-stable/railties/lib/rails/generators/rails/app/templates/config/puma.rb.tt

I think the example can be simplified by removing REQUIREMENTS_FILE_PATH. It made sense when the idea was to ship a base image, because there was a separation between the user's requirements and the base requirements. I would just expect now a single requirements.txt in the work path.

I don't think a separation between /config and /work is helpful, nor is CONFIG_FILE_PATH. Gunicorn accepts an argument on the command line to set the config file path, so if the default execution is gunicorn then the user can docker run app --config <path>. The entrypoint script should not be necessary.

I sympathize enough. I would appreciate it if you think of it as a sample rather than an official image. I also agree with what you said is more useful to configure using the gunicorn.conf.py file.
The config.sh file was originally created to set environment variables that should be in gunicorn.conf.py. The reason is that when using containers through Docker or creating Kubernetes environments through Helm charts, it was easier to apply configuration values ​​as environment variables than injecting them into a file. (This is purely from my experience.).
There were also concerns that users would have a hard time using config.sh. But in this DockerFile, the user does not need to modify the config.sh file.
Also, the DockerFile posted by PR will read the contents of gunicorn.conf.py if it exists.

@nanaones
Copy link
Author

I worry that the config.sh script complicates the example and makes it less accessible as an educational tool. A gunicorn.conf.py file in the example that sets values from the environment directly might be more helpful. Something like this would also make sense in any kind of Gunicorn application template. This would be analogous to how the Rails templates install a Puma config that reads from the environment, but sets defaults: https://github.com/rails/rails/blob/6-0-stable/railties/lib/rails/generators/rails/app/templates/config/puma.rb.tt

I think the example can be simplified by removing REQUIREMENTS_FILE_PATH. It made sense when the idea was to ship a base image, because there was a separation between the user's requirements and the base requirements. I would just expect now a single requirements.txt in the work path.

I don't think a separation between /config and /work is helpful, nor is CONFIG_FILE_PATH. Gunicorn accepts an argument on the command line to set the config file path, so if the default execution is gunicorn then the user can docker run app --config <path>. The entrypoint script should not be necessary.

The reason I put the config file in the /config folder is because the user could overwrite files like start.sh that should be in /config, which could cause the container not to work properly.

… variable via START_OPTION

gunicorn's installation syntax was added.
A branch statement depending on the presence or absence of REQUIRENMENTS_FILE_PATH has been added.
A branch statement depending on the presence or absence of CONFIG_FILE_PATH has been added.
Examples using gevent and flask have been added to the requirenments.txt file.
The unused environment variable CONFIG_FILE_PATH has been removed.
Corrected the command to edit permissions on deleted files. like config.sh, config/install.sh, /config/requirements.txt
Remove any comments related to the config.sh file.
@nanaones
Copy link
Author

nanaones commented Nov 15, 2020

@tilgovi
I have reflected the changes you requested. Please check.
Please forgive me for being late.

---
### **Configuration**

### Environment variables required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why specify these as environment variables when they can all be passed to the Gunicorn CLI?

@@ -0,0 +1,10 @@
# You can also use your favorite Python Docker image.
FROM python:3.8.4-slim
ENV PYTHONIOENCODING UTF-8
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is only needed for the Windows Server containers, and it's included upstream for those: docker-library/python#557

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tilgovi tilgovi self-assigned this Feb 16, 2021
@benoitc benoitc added this to the 21.0 milestone May 7, 2023
@benoitc benoitc added the Deploy label May 10, 2023
@tilgovi tilgovi modified the milestones: 21.0, 22.0 Dec 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants