|
| 1 | +# gunicorn |
| 2 | + |
| 3 | +A multiarchitecture container image for running Python with Gunicorn. |
| 4 | + |
| 5 | +Looking for the containers? [Head over to the Github Container Registry](https://github.com/multi-py/python-gunicorn/pkgs/container/python-gunicorn)! |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +### Mutli Architecture Builds |
| 10 | + |
| 11 | +Every tag in this repository supports these architectures: |
| 12 | + |
| 13 | +* linux/amd64 |
| 14 | +* linux/arm64 |
| 15 | +* linux/arm/v7 |
| 16 | + |
| 17 | + |
| 18 | +### Small Images |
| 19 | + |
| 20 | +Despite having to custom compile greenlet for different architectures this project manages to keep images small. It does so by using a multistaged build to compile the requirements in one image and then move them into the final image that gets published, ensuring that the build tools and artifacts get saved into the container. |
| 21 | + |
| 22 | + |
| 23 | +### No Rate Limits |
| 24 | + |
| 25 | +This project uses the Github Container Registry to store images, which have no rate limiting on pulls (unlike Docker Hub). |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +## How To |
| 31 | +### Add Your App |
| 32 | + |
| 33 | +By default the startup script checks for the following packages and uses the first one it can find- |
| 34 | + |
| 35 | +* `/app/app/main.py` |
| 36 | +* `/app/main.py` |
| 37 | + |
| 38 | +If you are using pip to install dependencies your dockerfile could look like this- |
| 39 | + |
| 40 | +```dockerfile |
| 41 | +FROM ghcr.io/multi-py/python-gunicorn:py3.10-20.1.0 |
| 42 | + |
| 43 | +COPY requirements /requirements |
| 44 | +RUN pip install --no-cache-dir -r /requirements |
| 45 | +COPY ./app app |
| 46 | +``` |
| 47 | + |
| 48 | + |
| 49 | +### Multistage Example |
| 50 | + |
| 51 | +In this example we use a multistage build to compile our libraries in one container and then move them into the container we plan on using. This creates small containers while avoiding the frustration of installing build tools in a piecemeal way. |
| 52 | + |
| 53 | +```dockerfile |
| 54 | +FROM ghcr.io/multi-py/python-gunicorn:py3.10-20.1.0 |
| 55 | + |
| 56 | +# Build any packages in the bigger container with all the build tools |
| 57 | +COPY requirements /requirements |
| 58 | +RUN pip install --no-cache-dir -r /requirements |
| 59 | + |
| 60 | + |
| 61 | +FROM ghcr.io/multi-py/python-gunicorn:py3.10-slim-20.1.0 |
| 62 | + |
| 63 | +# Copy the compiled python libraries from the first stage |
| 64 | +COPY --from=0 /usr/local/lib/python3.9 /usr/local/lib/python3.9 |
| 65 | + |
| 66 | +COPY ./app app |
| 67 | +``` |
| 68 | + |
| 69 | + |
| 70 | +### PreStart Script |
| 71 | + |
| 72 | +When the container is launched it will run the script at `/app/prestart.sh` before starting the gunicorn service. This is an ideal place to put things like database migrations. |
| 73 | + |
| 74 | + |
| 75 | +## Python Versions |
| 76 | + |
| 77 | +This project actively supports these Python versions: |
| 78 | + |
| 79 | +* 3.10 |
| 80 | +* 3.9 |
| 81 | +* 3.8 |
| 82 | +* 3.7 |
| 83 | +* 3.6 |
| 84 | + |
| 85 | + |
| 86 | +## Image Variants |
| 87 | + |
| 88 | +Like the upstream Python containers themselves a variety of image variants are supported. |
| 89 | + |
| 90 | + |
| 91 | +### Full |
| 92 | + |
| 93 | +The default container type, and if you're not sure what container to use start here. It has a variety of libraries and build tools installed, making it easy to extend. |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | +### Slim |
| 98 | + |
| 99 | +This container is similar to Full but with far less libraries and tools installed by default. If yo're looking for the tiniest possible image with the most stability this is your best bet. |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | +### Alpine |
| 104 | + |
| 105 | +This container is provided for those who wish to use Alpine. Alpine works a bit differently than the other image types, as it uses `musl` instead of `glibc` and many libaries are not well tested under `musl` at this time. |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | +## Architectures |
| 110 | + |
| 111 | +Every tag in this repository supports these architectures: |
| 112 | + |
| 113 | +* linux/amd64 |
| 114 | +* linux/arm64 |
| 115 | +* linux/arm/v7 |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | +## Tags |
| 120 | +* Recommended Image: `ghcr.io/multi-py/python-gunicorn:py3.10-20.1.0` |
| 121 | +* Slim Image: `ghcr.io/multi-py/python-gunicorn:py3.10-slim-20.1.0` |
| 122 | + |
| 123 | +Tags are based on the package version, python version, and the upstream container the container is based on. |
| 124 | + |
| 125 | +| gunicorn Version | Python Version | Full Container | Slim Container | Alpine Container | |
| 126 | +|-----------------------|----------------|----------------|----------------|------------------| |
| 127 | +| latest | 3.10 | py3.10-latest | py3.10-slim-latest | py3.10-alpine-latest | |
| 128 | +| latest | 3.9 | py3.9-latest | py3.9-slim-latest | py3.9-alpine-latest | |
| 129 | +| latest | 3.8 | py3.8-latest | py3.8-slim-latest | py3.8-alpine-latest | |
| 130 | +| latest | 3.7 | py3.7-latest | py3.7-slim-latest | py3.7-alpine-latest | |
| 131 | +| latest | 3.6 | py3.6-latest | py3.6-slim-latest | py3.6-alpine-latest | |
| 132 | +| 20.1.0 | 3.10 | py3.10-20.1.0 | py3.10-slim-20.1.0 | py3.10-alpine-20.1.0 | |
| 133 | +| 20.1.0 | 3.9 | py3.9-20.1.0 | py3.9-slim-20.1.0 | py3.9-alpine-20.1.0 | |
| 134 | +| 20.1.0 | 3.8 | py3.8-20.1.0 | py3.8-slim-20.1.0 | py3.8-alpine-20.1.0 | |
| 135 | +| 20.1.0 | 3.7 | py3.7-20.1.0 | py3.7-slim-20.1.0 | py3.7-alpine-20.1.0 | |
| 136 | +| 20.1.0 | 3.6 | py3.6-20.1.0 | py3.6-slim-20.1.0 | py3.6-alpine-20.1.0 | |
| 137 | +| 20.0.4 | 3.10 | py3.10-20.0.4 | py3.10-slim-20.0.4 | py3.10-alpine-20.0.4 | |
| 138 | +| 20.0.4 | 3.9 | py3.9-20.0.4 | py3.9-slim-20.0.4 | py3.9-alpine-20.0.4 | |
| 139 | +| 20.0.4 | 3.8 | py3.8-20.0.4 | py3.8-slim-20.0.4 | py3.8-alpine-20.0.4 | |
| 140 | +| 20.0.4 | 3.7 | py3.7-20.0.4 | py3.7-slim-20.0.4 | py3.7-alpine-20.0.4 | |
| 141 | +| 20.0.4 | 3.6 | py3.6-20.0.4 | py3.6-slim-20.0.4 | py3.6-alpine-20.0.4 | |
| 142 | +| 20.0.3 | 3.10 | py3.10-20.0.3 | py3.10-slim-20.0.3 | py3.10-alpine-20.0.3 | |
| 143 | +| 20.0.3 | 3.9 | py3.9-20.0.3 | py3.9-slim-20.0.3 | py3.9-alpine-20.0.3 | |
| 144 | +| 20.0.3 | 3.8 | py3.8-20.0.3 | py3.8-slim-20.0.3 | py3.8-alpine-20.0.3 | |
| 145 | +| 20.0.3 | 3.7 | py3.7-20.0.3 | py3.7-slim-20.0.3 | py3.7-alpine-20.0.3 | |
| 146 | +| 20.0.3 | 3.6 | py3.6-20.0.3 | py3.6-slim-20.0.3 | py3.6-alpine-20.0.3 | |
| 147 | +| 20.0.2 | 3.10 | py3.10-20.0.2 | py3.10-slim-20.0.2 | py3.10-alpine-20.0.2 | |
| 148 | +| 20.0.2 | 3.9 | py3.9-20.0.2 | py3.9-slim-20.0.2 | py3.9-alpine-20.0.2 | |
| 149 | +| 20.0.2 | 3.8 | py3.8-20.0.2 | py3.8-slim-20.0.2 | py3.8-alpine-20.0.2 | |
| 150 | +| 20.0.2 | 3.7 | py3.7-20.0.2 | py3.7-slim-20.0.2 | py3.7-alpine-20.0.2 | |
| 151 | +| 20.0.2 | 3.6 | py3.6-20.0.2 | py3.6-slim-20.0.2 | py3.6-alpine-20.0.2 | |
| 152 | +| 20.0.0 | 3.10 | py3.10-20.0.0 | py3.10-slim-20.0.0 | py3.10-alpine-20.0.0 | |
| 153 | +| 20.0.0 | 3.9 | py3.9-20.0.0 | py3.9-slim-20.0.0 | py3.9-alpine-20.0.0 | |
| 154 | +| 20.0.0 | 3.8 | py3.8-20.0.0 | py3.8-slim-20.0.0 | py3.8-alpine-20.0.0 | |
| 155 | +| 20.0.0 | 3.7 | py3.7-20.0.0 | py3.7-slim-20.0.0 | py3.7-alpine-20.0.0 | |
| 156 | +| 20.0.0 | 3.6 | py3.6-20.0.0 | py3.6-slim-20.0.0 | py3.6-alpine-20.0.0 | |
| 157 | +| 19.10.0 | 3.10 | py3.10-19.10.0 | py3.10-slim-19.10.0 | py3.10-alpine-19.10.0 | |
| 158 | +| 19.10.0 | 3.9 | py3.9-19.10.0 | py3.9-slim-19.10.0 | py3.9-alpine-19.10.0 | |
| 159 | +| 19.10.0 | 3.8 | py3.8-19.10.0 | py3.8-slim-19.10.0 | py3.8-alpine-19.10.0 | |
| 160 | +| 19.10.0 | 3.7 | py3.7-19.10.0 | py3.7-slim-19.10.0 | py3.7-alpine-19.10.0 | |
| 161 | +| 19.10.0 | 3.6 | py3.6-19.10.0 | py3.6-slim-19.10.0 | py3.6-alpine-19.10.0 | |
| 162 | +| 19.9.0 | 3.10 | py3.10-19.9.0 | py3.10-slim-19.9.0 | py3.10-alpine-19.9.0 | |
| 163 | +| 19.9.0 | 3.9 | py3.9-19.9.0 | py3.9-slim-19.9.0 | py3.9-alpine-19.9.0 | |
| 164 | +| 19.9.0 | 3.8 | py3.8-19.9.0 | py3.8-slim-19.9.0 | py3.8-alpine-19.9.0 | |
| 165 | +| 19.9.0 | 3.7 | py3.7-19.9.0 | py3.7-slim-19.9.0 | py3.7-alpine-19.9.0 | |
| 166 | +| 19.9.0 | 3.6 | py3.6-19.9.0 | py3.6-slim-19.9.0 | py3.6-alpine-19.9.0 | |
| 167 | +| 19.8.1 | 3.10 | py3.10-19.8.1 | py3.10-slim-19.8.1 | py3.10-alpine-19.8.1 | |
| 168 | +| 19.8.1 | 3.9 | py3.9-19.8.1 | py3.9-slim-19.8.1 | py3.9-alpine-19.8.1 | |
| 169 | +| 19.8.1 | 3.8 | py3.8-19.8.1 | py3.8-slim-19.8.1 | py3.8-alpine-19.8.1 | |
| 170 | +| 19.8.1 | 3.7 | py3.7-19.8.1 | py3.7-slim-19.8.1 | py3.7-alpine-19.8.1 | |
| 171 | +| 19.8.1 | 3.6 | py3.6-19.8.1 | py3.6-slim-19.8.1 | py3.6-alpine-19.8.1 | |
| 172 | +| 19.8.0 | 3.10 | py3.10-19.8.0 | py3.10-slim-19.8.0 | py3.10-alpine-19.8.0 | |
| 173 | +| 19.8.0 | 3.9 | py3.9-19.8.0 | py3.9-slim-19.8.0 | py3.9-alpine-19.8.0 | |
| 174 | +| 19.8.0 | 3.8 | py3.8-19.8.0 | py3.8-slim-19.8.0 | py3.8-alpine-19.8.0 | |
| 175 | +| 19.8.0 | 3.7 | py3.7-19.8.0 | py3.7-slim-19.8.0 | py3.7-alpine-19.8.0 | |
| 176 | +| 19.8.0 | 3.6 | py3.6-19.8.0 | py3.6-slim-19.8.0 | py3.6-alpine-19.8.0 | |
| 177 | +| 19.7.1 | 3.10 | py3.10-19.7.1 | py3.10-slim-19.7.1 | py3.10-alpine-19.7.1 | |
| 178 | +| 19.7.1 | 3.9 | py3.9-19.7.1 | py3.9-slim-19.7.1 | py3.9-alpine-19.7.1 | |
| 179 | +| 19.7.1 | 3.8 | py3.8-19.7.1 | py3.8-slim-19.7.1 | py3.8-alpine-19.7.1 | |
| 180 | +| 19.7.1 | 3.7 | py3.7-19.7.1 | py3.7-slim-19.7.1 | py3.7-alpine-19.7.1 | |
| 181 | +| 19.7.1 | 3.6 | py3.6-19.7.1 | py3.6-slim-19.7.1 | py3.6-alpine-19.7.1 | |
| 182 | + |
| 183 | + |
| 184 | +### Older Tags |
| 185 | + |
| 186 | +Older tags are left for historic purposes but do not receive updates. A full list of tags can be found on the package's [registry page](https://github.com/multi-py/python-gunicorn/pkgs/container/python-gunicorn). |
| 187 | + |
| 188 | +## Environmental Variables |
| 189 | + |
| 190 | +### `PORT` |
| 191 | + |
| 192 | +The port that the application inside of the container will listen on. This is different from the host port that gets mapped to the container. |
| 193 | + |
| 194 | + |
| 195 | +### `LOG_LEVEL` |
| 196 | + |
| 197 | +The gunicorn log level. Must be one of the following: |
| 198 | + |
| 199 | +* `critical` |
| 200 | +* `error` |
| 201 | +* `warning` |
| 202 | +* `info` |
| 203 | +* `debug` |
| 204 | +* `trace` |
| 205 | + |
| 206 | + |
| 207 | +### `MODULE_NAME` |
| 208 | + |
| 209 | +The python module that gunicorn will import. This value is used to generate the APP_MODULE value. |
| 210 | + |
| 211 | + |
| 212 | +### `VARIABLE_NAME` |
| 213 | + |
| 214 | +The python variable containing the ASGI application inside of the module that gunicorn imports. This value is used to generate the APP_MODULE value. |
| 215 | + |
| 216 | + |
| 217 | +### `APP_MODULE` |
| 218 | + |
| 219 | +The python module and variable that is passed to gunicorn. When used the `VARIABLE_NAME` and `MODULE_NAME` environmental variables are ignored. |
| 220 | + |
| 221 | + |
| 222 | +### `PRE_START_PATH` |
| 223 | + |
| 224 | +Where to find the prestart script. |
| 225 | + |
| 226 | + |
| 227 | +### `RELOAD` |
| 228 | + |
| 229 | +When this is set to the string `true` gunicorn is launched in reload mode. If any files change gunicorn will reload the modules again, allowing for quick debugging. This comes at a performance cost, however, and should not be enabled on production machines. |
0 commit comments