Skip to content

Commit 36ccb63

Browse files
committed
updates
1 parent 1b33f39 commit 36ccb63

File tree

1 file changed

+27
-29
lines changed

1 file changed

+27
-29
lines changed

articles/app-service/configure-language-python.md

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ For App Service, you then make the following modifications:
155155
STATICFILES_DIRS = [os.path.join(FRONTEND_DIR, 'build', 'static')]
156156
```
157157
158-
Here, `FRONTEND_DIR`, to build a path to where a build tool like yarn is run. You can again use an environment variable and App Setting as desired.
158+
Here, `FRONTEND_DIR` is used to build a path to where a build tool like yarn is run. You can again use an environment variable and App Setting as desired.
159159
160160
1. Add `whitenoise` to your *requirements.txt* file. [Whitenoise](http://whitenoise.evans.io/en/stable/) (whitenoise.evans.io) is a Python package that makes it simple for a production Django app to serve its own static files. Whitenoise specifically serves those files that are found in the folder specified by the Django `STATIC_ROOT` variable.
161161
@@ -204,7 +204,7 @@ This container has the following characteristics:
204204
- Apps are run using the [Gunicorn WSGI HTTP Server](https://gunicorn.org/), using the extra arguments `--bind=0.0.0.0 --timeout 600`.
205205
- You can provide configuration settings for Gunicorn by [customizing the startup command](#customize-startup-command).
206206

207-
- To protect your web app from accidental or deliberate DDOS attacks, Gunicorn is run behind an Nginx reverse proxy as described on [Deploying Gunicorn](https://docs.gunicorn.org/en/latest/deploy.html) (docs.gunicorn.org).
207+
- To protect your web app from accidental or deliberate DDOS attacks, Gunicorn is run behind an Nginx reverse proxy as described in [Deploying Gunicorn](https://docs.gunicorn.org/en/latest/deploy.html).
208208

209209
- By default, the base container image includes only the Flask web framework, but the container supports other frameworks that are WSGI-compliant and compatible with Python 3.6+, such as Django.
210210

@@ -220,10 +220,10 @@ This container has the following characteristics:
220220

221221
During startup, the App Service on Linux container runs the following steps:
222222

223-
1. Use a [custom startup command](#customize-startup-command), if provided.
224-
2. Check for the existence of a [Django app](#django-app), and launch Gunicorn for it if detected.
225-
3. Check for the existence of a [Flask app](#flask-app), and launch Gunicorn for it if detected.
226-
4. If no other app is found, start a default app that's built into the container.
223+
1. Use a [custom startup command](#customize-startup-command), if one is provided.
224+
1. Check for the existence of a [Django app](#django-app), and launch Gunicorn for it if one is detected.
225+
1. Check for the existence of a [Flask app](#flask-app), and launch Gunicorn for it if one is detected.
226+
1. If no other app is found, start a default app that's built into the container.
227227

228228
The following sections provide extra details for each option.
229229

@@ -252,7 +252,7 @@ gunicorn --bind=0.0.0.0 --timeout 600 application:app
252252
gunicorn --bind=0.0.0.0 --timeout 600 app:app
253253
```
254254

255-
If your main app module is contained in a different file, use a different name for the app object, or you want to provide other arguments to Gunicorn, use a [custom startup command](#customize-startup-command).
255+
If your main app module is contained in a different file, use a different name for the app object. If you want to provide other arguments to Gunicorn, use a [custom startup command](#customize-startup-command).
256256

257257
### Default behavior
258258

@@ -262,8 +262,6 @@ If you deployed code and still see the default app, see [Troubleshooting - App d
262262

263263
:::image type="content" source="media/configure-language-python/default-python-app.png" alt-text="Screenshot of the default App Service on Linux web page." link="#app-doesnt-appear":::
264264

265-
Again, if you expect to see a deployed app instead of the default app, see [Troubleshooting - App doesn't appear](#app-doesnt-appear).
266-
267265
## Customize startup command
268266

269267
You can control the container's startup behavior by providing either a custom startup command or multiple commands in a startup command file. A startup command file can use whatever name you choose, such as *startup.sh*, *startup.cmd*, *startup.txt*, and so on.
@@ -286,15 +284,15 @@ App Service ignores any errors that occur when processing a custom startup comma
286284
287285
### Example startup commands
288286
289-
- **Added Gunicorn arguments**: The following example adds the `--workers=4` to a Gunicorn command line for starting a Django app:
287+
- **Added Gunicorn arguments**: The following example adds the `--workers=4` argument to a Gunicorn command line for starting a Django app:
290288
291289
```bash
292290
# <module-path> is the relative path to the folder that contains the module
293291
# that contains wsgi.py; <module> is the name of the folder containing wsgi.py.
294292
gunicorn --bind=0.0.0.0 --timeout 600 --workers=4 --chdir <module_path> <module>.wsgi
295293
```
296294
297-
For more information, see [Running Gunicorn](https://docs.gunicorn.org/en/stable/run.html) (docs.gunicorn.org). If you're using auto-scale rules to scale your web app up and down, you should also dynamically set the number of gunicorn workers using the `NUM_CORES` environment variable in your startup command, for example: `--workers $((($NUM_CORES*2)+1))`. For more information on setting the recommended number of gunicorn workers, see [the Gunicorn FAQ](https://docs.gunicorn.org/en/stable/design.html#how-many-workers)
295+
For more information, see [Running Gunicorn](https://docs.gunicorn.org/en/stable/run.html). If you're using auto-scale rules to scale your web app up and down, you should also dynamically set the number of Gunicorn workers using the `NUM_CORES` environment variable in your startup command, for example: `--workers $((($NUM_CORES*2)+1))`. For more information on setting the recommended number of Gunicorn workers, see [the Gunicorn FAQ](https://docs.gunicorn.org/en/stable/design.html#how-many-workers)
298296
299297
- **Enable production logging for Django**: Add the `--access-logfile '-'` and `--error-logfile '-'` arguments to the command line:
300298
@@ -305,7 +303,7 @@ App Service ignores any errors that occur when processing a custom startup comma
305303
306304
These logs will appear in the [App Service log stream](#access-diagnostic-logs).
307305
308-
For more information, see [Gunicorn logging](https://docs.gunicorn.org/en/stable/settings.html#logging) (docs.gunicorn.org).
306+
For more information, see [Gunicorn logging](https://docs.gunicorn.org/en/stable/settings.html#logging).
309307
310308
- **Custom Flask main module**: By default, App Service assumes that a Flask app's main module is *application.py* or *app.py*. If your main module uses a different name, then you must customize the startup command. For example, if you have a Flask app whose main module is *hello.py* and the Flask app object in that file is named `myapp`, then the command is as follows:
311309
@@ -327,24 +325,24 @@ App Service ignores any errors that occur when processing a custom startup comma
327325
328326
## Access app settings as environment variables
329327
330-
App settings are values stored in the cloud specifically for your app as described on [Configure app settings](configure-common.md#configure-app-settings). These settings are available to your app code as environment variables and accessed using the standard [os.environ](https://docs.python.org/3/library/os.html#os.environ) pattern.
328+
App settings are values stored in the cloud specifically for your app, as described in [Configure app settings](configure-common.md#configure-app-settings). These settings are available to your app code as environment variables and accessed using the standard [os.environ](https://docs.python.org/3/library/os.html#os.environ) pattern.
331329
332-
For example, if you've created app setting called `DATABASE_SERVER`, the following code retrieves that setting's value:
330+
For example, if you've created an app setting called `DATABASE_SERVER`, the following code retrieves that setting's value:
333331
334332
```python
335333
db_server = os.environ['DATABASE_SERVER']
336334
```
337335

338336
## Detect HTTPS session
339337

340-
In App Service, [TLS/SSL termination](https://wikipedia.org/wiki/TLS_termination_proxy) (wikipedia.org) happens at the network load balancers, so all HTTPS requests reach your app as unencrypted HTTP requests. If your app logic needs to check if the user requests are encrypted or not, inspect the `X-Forwarded-Proto` header.
338+
In App Service, [TLS/SSL termination](https://wikipedia.org/wiki/TLS_termination_proxy) happens at the network load balancers, so all HTTPS requests reach your app as unencrypted HTTP requests. If your app logic needs to check if the user requests are encrypted or not, inspect the `X-Forwarded-Proto` header.
341339

342340
```python
343341
if 'X-Forwarded-Proto' in request.headers and request.headers['X-Forwarded-Proto'] == 'https':
344342
# Do something when HTTPS is used
345343
```
346344

347-
Popular web frameworks let you access the `X-Forwarded-*` information in your standard app pattern. For example in Django, you can use the [SECURE_PROXY_SSL_HEADER](https://docs.djangoproject.com/en/4.1/ref/settings/#secure-proxy-ssl-header) to tell Django to use the `X-Forwarded-Proto` header.
345+
Popular web frameworks let you access the `X-Forwarded-*` information in your standard app pattern. For example, in Django you can use the [SECURE_PROXY_SSL_HEADER](https://docs.djangoproject.com/en/4.1/ref/settings/#secure-proxy-ssl-header) to tell Django to use the `X-Forwarded-Proto` header.
348346

349347
## Access diagnostic logs
350348

@@ -360,23 +358,23 @@ Use the following steps to access the deployment logs:
360358

361359
1. On the Azure portal for your web app, select **Deployment** > **Deployment Center** on the left menu.
362360
1. On the **Logs** tab, select the **Commit ID** for the most recent commit.
363-
1. On the **Log details** page that appears, select the **Show Logs...** link that appears next to "Running oryx build...".
361+
1. On the **Log details** page that appears, select the **Show Logs** link that appears next to "Running oryx build...".
364362

365-
Build issues such as incorrect dependencies in *requirements.txt* and errors in pre- or post-build scripts will appear in these logs. Errors also appear if your requirements file isn't exactly named *requirements.txt* or doesn't appear in the root folder of your project.
363+
Build issues such as incorrect dependencies in *requirements.txt* and errors in pre- or post-build scripts will appear in these logs. Errors also appear if your requirements file isn't named *requirements.txt* or doesn't appear in the root folder of your project.
366364

367365
## Open SSH session in browser
368366

369367
[!INCLUDE [Open SSH session in browser](../../includes/app-service-web-ssh-connect-builtin-no-h.md)]
370368

371-
When you're successfully connected to the SSH session, you should see the message "SSH CONNECTION ESTABLISHED" at the bottom of the window. If you see errors such as "SSH_CONNECTION_CLOSED" or a message that the container is restarting, an error may be preventing the app container from starting. See [Troubleshooting](#troubleshooting) for steps to investigate possible issues.
369+
When you're successfully connected to the SSH session, you should see the message "SSH CONNECTION ESTABLISHED" at the bottom of the window. If you see errors such as "SSH_CONNECTION_CLOSED" or a message that the container is restarting, an error might be preventing the app container from starting. See [Troubleshooting](#troubleshooting) for steps to investigate possible issues.
372370

373371
## URL rewrites
374372

375-
When deploying Python applications on Azure App Service for Linux, you may need to handle URL rewrites within your application. This is particularly useful for ensuring specific URL patterns are redirected to the correct endpoints without relying on external web server configurations. For Flask applications, [URL processors](https://flask.palletsprojects.com/patterns/urlprocessors/) and custom middleware can be used to achieve this. In Django applications, the robust [URL dispatcher](https://docs.djangoproject.com/en/5.0/topics/http/urls/) allows for efficient management of URL rewrites.
373+
When deploying Python applications on Azure App Service for Linux, you might need to handle URL rewrites within your application. This is particularly useful for ensuring specific URL patterns are redirected to the correct endpoints without relying on external web server configurations. For Flask applications, [URL processors](https://flask.palletsprojects.com/patterns/urlprocessors/) and custom middleware can be used to achieve this. In Django applications, the robust [URL dispatcher](https://docs.djangoproject.com/en/5.0/topics/http/urls/) allows for efficient management of URL rewrites.
376374

377375
## Troubleshooting
378376

379-
In general, the first step in troubleshooting is to use App Service Diagnostics:
377+
In general, the first step in troubleshooting is to use App Service diagnostics:
380378

381379
1. In the Azure portal for your web app, select **Diagnose and solve problems** from the left menu.
382380
1. Select **Availability and Performance**.
@@ -410,7 +408,7 @@ The following sections provide guidance for specific issues.
410408

411409
- <a name="service-unavailable"></a>**You see the message "Service Unavailable" in the browser.** The browser has timed out waiting for a response from App Service, which indicates that App Service started the Gunicorn server, but the app itself didn't start. This condition could indicate that the Gunicorn arguments are incorrect, or that there's an error in the app code.
412410

413-
- Refresh the browser, especially if you're using the lowest pricing tiers in your App Service Plan. The app may take longer to start up when using free tiers, for example, and becomes responsive after you refresh the browser.
411+
- Refresh the browser, especially if you're using the lowest pricing tiers in your App Service plan. The app might take longer to start up when you use free tiers, for example, and becomes responsive after you refresh the browser.
414412

415413
- Check that your app is structured as App Service expects for [Django](#django-app) or [Flask](#flask-app), or use a [custom startup command](#customize-startup-command).
416414

@@ -420,31 +418,31 @@ The following sections provide guidance for specific issues.
420418

421419
- **The log stream shows "Could not find setup.py or requirements.txt; Not running pip install."**: The Oryx build process failed to find your *requirements.txt* file.
422420

423-
- Connect to the web app's container via [SSH](#open-ssh-session-in-browser) and verify that *requirements.txt* is named correctly and exists directly under *site/wwwroot*. If it doesn't exist, make site the file exists in your repository and is included in your deployment. If it exists in a separate folder, move it to the root.
421+
- Connect to the web app's container via [SSH](#open-ssh-session-in-browser) and verify that *requirements.txt* is named correctly and exists directly under *site/wwwroot*. If it doesn't exist, make sure the file exists in your repository and is included in your deployment. If it exists in a separate folder, move it to the root.
424422

425423
#### ModuleNotFoundError when app starts
426424

427-
If you see an error like `ModuleNotFoundError: No module named 'example'`, then Python couldn't find one or more of your modules when the application started. This error most often occurs if you deploy your virtual environment with your code. Virtual environments aren't portable, so a virtual environment shouldn't be deployed with your application code. Instead, let Oryx create a virtual environment and install your packages on the web app by creating an app setting, `SCM_DO_BUILD_DURING_DEPLOYMENT`, and setting it to `1`. This setting will force Oryx to install your packages whenever you deploy to App Service. For more information, please see [this article on virtual environment portability](https://azure.github.io/AppService/2020/12/11/cicd-for-python-apps.html).
425+
If you see an error like `ModuleNotFoundError: No module named 'example'`, then Python couldn't find one or more of your modules when the application started. This error most often occurs if you deploy your virtual environment with your code. Virtual environments aren't portable, so a virtual environment shouldn't be deployed with your application code. Instead, let Oryx create a virtual environment and install your packages on the web app by creating an app setting, `SCM_DO_BUILD_DURING_DEPLOYMENT`, and setting it to `1`. This setting will force Oryx to install your packages whenever you deploy to App Service. For more information, see [this article on virtual environment portability](https://azure.github.io/AppService/2020/12/11/cicd-for-python-apps.html).
428426

429427
### Database is locked
430428

431-
When attempting to run database migrations with a Django app, you may see "sqlite3. OperationalError: database is locked." The error indicates that your application is using a SQLite database for which Django is configured by default rather than using a cloud database such as PostgreSQL for Azure.
429+
When attempting to run database migrations with a Django app, you might see "sqlite3. OperationalError: database is locked." The error indicates that your application is using a SQLite database, for which Django is configured by default, rather than using a cloud database such as Azure Database for PostgreSQL.
432430

433431
Check the `DATABASES` variable in the app's *settings.py* file to ensure that your app is using a cloud database instead of SQLite.
434432

435433
If you're encountering this error with the sample in [Tutorial: Deploy a Django web app with PostgreSQL](tutorial-python-postgresql-app.md), check that you completed the steps in [Verify connection settings](tutorial-python-postgresql-app.md#2-verify-connection-settings).
436434

437435
#### Other issues
438436

439-
- **Passwords don't appear in the SSH session when typed**: For security reasons, the SSH session keeps your password hidden when you type. The characters are being recorded, however, so type your password as usual and press **Enter** when done.
437+
- **Passwords don't appear in the SSH session when typed**: For security reasons, the SSH session keeps your password hidden when you type. The characters are being recorded, however, so type your password as usual and select **Enter** when done.
440438

441-
- **Commands in the SSH session appear to be cut off**: The editor may not be word-wrapping commands, but they should still run correctly.
439+
- **Commands in the SSH session appear to be cut off**: The editor might not be word-wrapping commands, but they should still run correctly.
442440

443-
- **Static assets don't appear in a Django app**: Ensure that you've enabled the [whitenoise module](http://whitenoise.evans.io/en/stable/django.html)
441+
- **Static assets don't appear in a Django app**: Ensure that you've enabled the [WhiteNoise module](http://whitenoise.evans.io/en/stable/django.html).
444442

445443
- **You see the message, "Fatal SSL Connection is Required"**: Check any usernames and passwords used to access resources (such as databases) from within the app.
446444

447-
## More resources
445+
## Related content
448446

449447
- [Tutorial: Python app with PostgreSQL](tutorial-python-postgresql-app.md)
450448
- [Tutorial: Deploy from private container repository](tutorial-custom-container.md?pivots=container-linux)

0 commit comments

Comments
 (0)