From e45abc16a8ae1832cb4646e5dd561000c543f11a Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 13:19:02 -0700 Subject: [PATCH 1/9] Remove extraneous trailing whitespace withing the whole document --- .../tutorial-docker-python-postgresql-app.md | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index b0b945c224599..b644225f66225 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -1,5 +1,5 @@ --- -title: Build a Python and PostgreSQL web app in Azure App Service | Microsoft Docs +title: Build a Python and PostgreSQL web app in Azure App Service | Microsoft Docs description: Learn how to run a data-driven Python app in Azure, with connection to a PostgreSQL database. services: app-service\web documentationcenter: python @@ -29,7 +29,7 @@ In this tutorial, you learn how to: > * Manage the app in the Azure portal You can follow the steps in this article on macOS. Linux and Windows instructions are the same in most cases, but the differences are not detailed in this tutorial. - + [!INCLUDE [quickstarts-free-trial-note](../../../includes/quickstarts-free-trial-note.md)] ## Prerequisites @@ -59,7 +59,7 @@ CREATE USER manager WITH PASSWORD 'supersecretpass'; GRANT ALL PRIVILEGES ON DATABASE eventregistration TO manager; ``` -Type `\q` to exit the PostgreSQL client. +Type `\q` to exit the PostgreSQL client. @@ -79,7 +79,7 @@ cd docker-flask-postgres git checkout tags/0.1-initialapp ``` -This sample repository contains a [Flask](http://flask.pocoo.org/) application. +This sample repository contains a [Flask](http://flask.pocoo.org/) application. ### Run the app locally @@ -111,7 +111,7 @@ Navigate to `http://localhost:5000` in a browser. Click **Register!** and create The Flask sample application stores user data in the database. If you are successful at registering a user, your app is writing data to the local PostgreSQL database. -To stop the Flask server at anytime, type Ctrl+C in the terminal. +To stop the Flask server at anytime, type Ctrl+C in the terminal. [!INCLUDE [cloud-shell-try-it.md](../../../includes/cloud-shell-try-it.md)] @@ -123,13 +123,13 @@ In this step, you create a PostgreSQL database in Azure. When your app is deploy ### Create a resource group -[!INCLUDE [Create resource group](../../../includes/app-service-web-create-resource-group-linux-no-h.md)] +[!INCLUDE [Create resource group](../../../includes/app-service-web-create-resource-group-linux-no-h.md)] ### Create an Azure Database for PostgreSQL server Create a PostgreSQL server with the [`az postgres server create`](/cli/azure/postgres/server?view=azure-cli-latest#az-postgres-server-create) command in the Cloud Shell. -In the following example command, replace *\* with a unique server name, and replace *\* and *\* with the desired user credentials. The server name is used as part of your PostgreSQL endpoint (`https://.postgres.database.azure.com`), so the name needs to be unique across all servers in Azure. The user credentials are for the database admin user account. +In the following example command, replace *\* with a unique server name, and replace *\* and *\* with the desired user credentials. The server name is used as part of your PostgreSQL endpoint (`https://.postgres.database.azure.com`), so the name needs to be unique across all servers in Azure. The user credentials are for the database admin user account. ```azurecli-interactive az postgres server create --resource-group myResourceGroup --name --location "West Europe" --admin-user --admin-password --sku-name GP_Gen4_2 @@ -163,19 +163,19 @@ When the Azure Database for PostgreSQL server is created, the Azure CLI shows in ### Create a firewall rule for the PostgreSQL server -In the Cloud Shell, run the following Azure CLI command to allow access to the database from all IP addresses. +In the Cloud Shell, run the following Azure CLI command to allow access to the database from all IP addresses. > [!Note] -> It is not advised to leave all ports open to your database, or to make your database internet-facing. See other [Azure security articles](https://docs.microsoft.com/azure/security/) to properly secure your new database for production use. +> It is not advised to leave all ports open to your database, or to make your database internet-facing. See other [Azure security articles](https://docs.microsoft.com/azure/security/) to properly secure your new database for production use. ```azurecli-interactive az postgres server firewall-rule create --resource-group myResourceGroup --server-name --start-ip-address=0.0.0.0 --end-ip-address=0.0.0.0 --name AllowAzureIPs ``` -> [!TIP] +> [!TIP] > You can be even more restrictive in your firewall rule by [using only the outbound IP addresses your app uses](../app-service-ip-addresses.md?toc=%2fazure%2fapp-service%2fcontainers%2ftoc.json#find-outbound-ips). > -In the Cloud Shell, run the command again to allow access to the database from your local computer by replacing *\* with [your local IPv4 IP address](https://whatismyipaddress.com/). +In the Cloud Shell, run the command again to allow access to the database from your local computer by replacing *\* with [your local IPv4 IP address](https://whatismyipaddress.com/). ```azurecli-interactive az postgres server firewall-rule create --resource-group myResourceGroup --server-name --start-ip-address= --end-ip-address= --name AllowLocalClient @@ -273,7 +273,7 @@ The database already contains the registration you created previously. ![Docker container-based Python Flask application running locally](./media/tutorial-docker-python-postgresql-app/local-docker.png) -Now that you verified that the container works locally, delete _db.env_. In Azure App Service, you will use app settings to define the environment variables. +Now that you verified that the container works locally, delete _db.env_. In Azure App Service, you will use app settings to define the environment variables. ### Create an Azure Container Registry @@ -386,12 +386,12 @@ In the Cloud Shell, restart the app. Restarting ensures that all settings are ap az webapp restart --resource-group myResourceGroup --name ``` -### Browse to the Azure web app +### Browse to the Azure web app -Browse to the deployed web app. +Browse to the deployed web app. -```bash -http://.azurewebsites.net +```bash +http://.azurewebsites.net ``` > [!NOTE] @@ -453,8 +453,8 @@ az webapp restart --resource-group myResourceGroup --name Navigate to your Azure web app and try out the new functionality again. Create another event registration. -```bash -http://.azurewebsites.net +```bash +http://.azurewebsites.net ``` ![Docker Python Flask app in Azure App Service](./media/tutorial-docker-python-postgresql-app/docker-flask-in-azure.png) From fa83417f50930a71002b1e09e87653d60f423e70 Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 13:20:38 -0700 Subject: [PATCH 2/9] Fix command that connects to PostgreSQL server, add note about common scenario on OSX --- .../tutorial-docker-python-postgresql-app.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index b644225f66225..c8fc7dde9fa9c 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -46,10 +46,16 @@ To complete this tutorial: In a local terminal window, run `psql` to connect to your local PostgreSQL server. ```bash -sudo -u postgres psql +sudo -u postgres psql postgres ``` -If your connection is successful, your PostgreSQL database is running. If not, make sure that your local PostgresQL database is started by following the steps at [Downloads - PostgreSQL Core Distribution](https://www.postgresql.org/download/). +If you get an error message about `unknown user: postgres`, it's possible your postgres configuration was set up with your logged in username. Try the following command instead. + +```bash +psql postgres +``` + +If your connection is successful, your PostgreSQL database is running. If not, make sure that your local PostgresQL database is started by following the instructions for your operating system at [Downloads - PostgreSQL Core Distribution](https://www.postgresql.org/download/). Create a database called *eventregistration* and set up a separate database user named *manager* with password *supersecretpass*. From 2b4dec546e7217260d5e4f738d73b3b858098cd4 Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 13:24:01 -0700 Subject: [PATCH 3/9] Remove duplicate Cloud Shell section --- .../containers/tutorial-docker-python-postgresql-app.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index c8fc7dde9fa9c..195565439925d 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -119,8 +119,6 @@ The Flask sample application stores user data in the database. If you are succes To stop the Flask server at anytime, type Ctrl+C in the terminal. -[!INCLUDE [cloud-shell-try-it.md](../../../includes/cloud-shell-try-it.md)] - ## Create a production PostgreSQL database In this step, you create a PostgreSQL database in Azure. When your app is deployed to Azure, it uses this cloud database. From 8e321f2a3bfa52ade2e1b5b0d2d2420546c41450 Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 13:47:13 -0700 Subject: [PATCH 4/9] Update sku-name parameter to cheapest available option for demo. Explain sku-name further. Fix command output --- .../tutorial-docker-python-postgresql-app.md | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index 195565439925d..a1217cf5e62d6 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -133,12 +133,18 @@ In this step, you create a PostgreSQL database in Azure. When your app is deploy Create a PostgreSQL server with the [`az postgres server create`](/cli/azure/postgres/server?view=azure-cli-latest#az-postgres-server-create) command in the Cloud Shell. -In the following example command, replace *\* with a unique server name, and replace *\* and *\* with the desired user credentials. The server name is used as part of your PostgreSQL endpoint (`https://.postgres.database.azure.com`), so the name needs to be unique across all servers in Azure. The user credentials are for the database admin user account. +In the following example command, replace *\* with a unique server name, and replace *\* and *\* with the desired user credentials. The user credentials are for the database admin user account. The server name is used as part of your PostgreSQL endpoint (`https://.postgres.database.azure.com`), so the name needs to be unique across all servers in Azure. + +> [!IMPORTANT] +> The server admin login and password that you specify here are required to log in to the server and its databases later in this quickstart. Remember or record this information for later use. ```azurecli-interactive -az postgres server create --resource-group myResourceGroup --name --location "West Europe" --admin-user --admin-password --sku-name GP_Gen4_2 +az postgres server create --resource-group myResourceGroup --name --location "West Europe" --admin-user --admin-password --sku-name B_Gen4_1 ``` +> [!Note] +> The sku-name parameter specifies the configuration of the database server, including processor type, number of cores, and amount of memory available. For our sample application, we've selected a Basic Server with 1 core. For real world applications, see the [pricing tiers documentation]( ../../postgresql/concepts-pricing-tiers.md) to determine the type of server best suited for your needs. + When the Azure Database for PostgreSQL server is created, the Azure CLI shows information similar to the following example: ```json @@ -150,18 +156,22 @@ When the Azure Database for PostgreSQL server is created, the Azure CLI shows in "name": "", "resourceGroup": "myResourceGroup", "sku": { - "capacity": 100, - "family": null, - "name": "PGSQLS3M100", + "capacity": 1, + "family": "Gen4", + "name": "B_Gen4_1", "size": null, "tier": "Basic" }, - "sslEnforcement": null, - "storageMb": 2048, + "sslEnforcement": "Enabled", + "storageProfile": { + "backupRetentionDays": 7, + "geoRedundantBackup": "Disabled", + "storageMb": 5120 + }, "tags": null, "type": "Microsoft.DBforPostgreSQL/servers", "userVisibleState": "Ready", - "version": null + "version": "9.6" } ``` From c0410b154952a36fdf09c078d60547b94ed2f61e Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 14:12:04 -0700 Subject: [PATCH 5/9] Clean up the section on configuring the firewall, remove incorrect descriptions --- .../tutorial-docker-python-postgresql-app.md | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index a1217cf5e62d6..985eba613ead6 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -175,26 +175,25 @@ When the Azure Database for PostgreSQL server is created, the Azure CLI shows in } ``` -### Create a firewall rule for the PostgreSQL server +### Create firewall rules for the PostgreSQL server -In the Cloud Shell, run the following Azure CLI command to allow access to the database from all IP addresses. -> [!Note] -> It is not advised to leave all ports open to your database, or to make your database internet-facing. See other [Azure security articles](https://docs.microsoft.com/azure/security/) to properly secure your new database for production use. +By default, the newly created database doesn't allow external connections. In order to connect to it, we'll need to create some firewall rules. + +For local testing purposes, we want to restrict connections to our local IP address. In the Cloud Shell, run this command to allow access to the database from your local computer by replacing *\* with [your local IPv4 IP address](http://www.whatsmyip.org/). ```azurecli-interactive -az postgres server firewall-rule create --resource-group myResourceGroup --server-name --start-ip-address=0.0.0.0 --end-ip-address=0.0.0.0 --name AllowAzureIPs +az postgres server firewall-rule create --resource-group myResourceGroup --server-name --start-ip-address= --end-ip-address= --name AllowLocalClient ``` -> [!TIP] -> You can be even more restrictive in your firewall rule by [using only the outbound IP addresses your app uses](../app-service-ip-addresses.md?toc=%2fazure%2fapp-service%2fcontainers%2ftoc.json#find-outbound-ips). -> - -In the Cloud Shell, run the command again to allow access to the database from your local computer by replacing *\* with [your local IPv4 IP address](https://whatismyipaddress.com/). +Next, let's open the range of IP addresses belonging to resources on the Azure network, so that we can connect from our web app after we deploy it. ```azurecli-interactive -az postgres server firewall-rule create --resource-group myResourceGroup --server-name --start-ip-address= --end-ip-address= --name AllowLocalClient +az postgres server firewall-rule create --resource-group myResourceGroup --server-name --start-ip-address=0.0.0.0 --end-ip-address=0.0.0.0 --name AllowAllAzureIPs ``` +> [!IMPORTANT] +> This option configures the firewall to allow network connections from IPs within the Azure network, not limited to your subscription. For production use, aim to configure the most restrictive firewall rules possible by [using only the outbound IP addresses your app uses](../app-service-ip-addresses.md?toc=%2fazure%2fapp-service%2fcontainers%2ftoc.json#find-outbound-ips). + ## Connect Python app to production database In this step, you connect your Flask sample app to the Azure Database for PostgreSQL server you created. From d457c8091658aff3eb1e8709f04a965b87d56a0d Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 14:26:19 -0700 Subject: [PATCH 6/9] Clean up language in Azure DB creation section, add a note about best practices. --- .../containers/tutorial-docker-python-postgresql-app.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index 985eba613ead6..90dbe4738ceee 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -200,13 +200,13 @@ In this step, you connect your Flask sample app to the Azure Database for Postgr ### Create empty database and user access -In the Cloud Shell, connect to the database by running `psql`. When prompted for your admin password, use the same password you specified in [Create an Azure Database for PostgreSQL server](#create-an-azure-database-for-postgresql-server). +In the Cloud Shell, connect to the database by running the command below. When prompted for your admin password, use the same password you specified in [Create an Azure Database for PostgreSQL server](#create-an-azure-database-for-postgresql-server). ```bash psql -h .postgres.database.azure.com -U @ postgres ``` -Create the database and user from the PostgreSQL CLI. +Just like on our local database, let's create the database and user for our web app from the PostgreSQL CLI. ```bash CREATE DATABASE eventregistration; @@ -216,6 +216,9 @@ GRANT ALL PRIVILEGES ON DATABASE eventregistration TO manager; Type `\q` to exit the PostgreSQL client. +> [!NOTE] +> It's best practice to create database users with restricted permissions for specific applications, instead of using the admin user. In this example, the `manager` user has full privileges to _only_ the `eventregistration` database. + ### Test app connectivity to production database Back in the local terminal window, run the following commands to run Flask database migration and the Flask server. From a74adad33b7754ec30d9872f7fc8fb9ebf8a8efa Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 14:32:22 -0700 Subject: [PATCH 7/9] Fix link for getting started with docker --- .../containers/tutorial-docker-python-postgresql-app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index 90dbe4738ceee..13ee00b6a5a45 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -39,7 +39,7 @@ To complete this tutorial: 1. [Install Git](https://git-scm.com/) 1. [Install Python](https://www.python.org/downloads/) 1. [Install and run PostgreSQL](https://www.postgresql.org/download/) -1. [Install Docker Community Edition](https://www.docker.com/community-edition) +1. [Install Docker Community Edition](https://www.docker.com/get-started) ## Test local PostgreSQL installation and create a database From feda8b29f0bcec5b2cc61d12073a998333e6bcd0 Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 16:09:30 -0700 Subject: [PATCH 8/9] Move notice about slow load before direction to open page. Minor stylistic changes --- .../tutorial-docker-python-postgresql-app.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index 13ee00b6a5a45..0130eb01a011e 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -255,7 +255,7 @@ cd .. docker build -t flask-postgresql-sample . ``` -Docker displays a confirmation that it successfully created the image. +Docker should display a confirmation that it successfully created the image. If you get an error, make sure you have docker installed, and that the docker daemon is running before trying again. ```bash Successfully built 7548f983a36b @@ -289,7 +289,7 @@ The database already contains the registration you created previously. ![Docker container-based Python Flask application running locally](./media/tutorial-docker-python-postgresql-app/local-docker.png) -Now that you verified that the container works locally, delete _db.env_. In Azure App Service, you will use app settings to define the environment variables. +Now that you verified that the container works locally, delete `db.env`. In Azure App Service, you will use app settings to define the environment variables. ### Create an Azure Container Registry @@ -406,13 +406,13 @@ az webapp restart --resource-group myResourceGroup --name Browse to the deployed web app. +> [!NOTE] +> The web app takes some time to start because the container has to be downloaded and run when the app is requested for the first time. If loading the page times out, or if you see an error message, just wait a few minutes and refresh the page. + ```bash http://.azurewebsites.net ``` -> [!NOTE] -> The web app takes some time to start because the container has to be downloaded and run when the app is requested the first time. If at first you see an error after a long time, just refresh the page. - You see previously registered guests that were saved to the Azure production database in the previous step. ![Docker container-based Python Flask application running locally](./media/tutorial-docker-python-postgresql-app/docker-app-deployed.png) From 358e81a66faecae7661919e47d936075e4b1bf97 Mon Sep 17 00:00:00 2001 From: Nina Zakharenko Date: Tue, 11 Sep 2018 18:06:27 -0700 Subject: [PATCH 9/9] Minor changes to redeployment and portal section, add section explaining resource cleanup --- .../tutorial-docker-python-postgresql-app.md | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md index 0130eb01a011e..9817a9bc7fc2d 100644 --- a/articles/app-service/containers/tutorial-docker-python-postgresql-app.md +++ b/articles/app-service/containers/tutorial-docker-python-postgresql-app.md @@ -419,9 +419,9 @@ You see previously registered guests that were saved to the Azure production dat **Congratulations!** You're running a Python app in Web App for Containers. -## Update data model and redeploy +## Making changes and redeploying -In this step, you add the number of attendees to each event registration by updating the `Guest` model. +As we work on our app, we're going to make changes that will require a redeploy. In this step, you'll add the number of attendees to each event registration by updating the `Guest` model. In the local terminal window, check out the *0.2-migration* release with the following git command: @@ -467,15 +467,19 @@ In the Cloud Shell, restart the app to make sure the latest container is pulled az webapp restart --resource-group myResourceGroup --name ``` -Navigate to your Azure web app and try out the new functionality again. Create another event registration. +Navigate to your Azure web app and try out the new functionality again. ```bash http://.azurewebsites.net ``` +Make sure you refresh the page and see the newly added attendees column. Then create another event registration. + ![Docker Python Flask app in Azure App Service](./media/tutorial-docker-python-postgresql-app/docker-flask-in-azure.png) -## Manage your Azure web app +## Manage your web app in the Azure Portal + +We've been using the Azure CLI command line interface, but there's also a portal with a rich interface available to help you manage your application. Go to the [Azure portal](https://portal.azure.com) to see the web app you created. @@ -493,3 +497,19 @@ Advance to the next tutorial to learn how to map a custom DNS name to your web a > [!div class="nextstepaction"] > [Map an existing custom DNS name to Azure Web Apps](../app-service-web-tutorial-custom-domain.md) + +## Clean up resources + +If you're done with your app and database, clean up the resources created in this tutorial. + +You can clean up all the resources at once by deleting the resource group. First, verify the contents of the resource group. The group you created at the start of the tutorial should contain a PostgreSQL server, a container registry, an app service plan, and an app. + +```bash +az resource list --resource-group myResourceGroup +``` + +Next, delete the resource group. Enter `y` at the prompt to confirm. This operation may take a few minutes to complete. + +```bash +az group delete --name myResourceGroup +``` \ No newline at end of file