	{"id":61415,"date":"2021-06-28T14:26:24","date_gmt":"2021-06-28T13:26:24","guid":{"rendered":"https:\/\/www.artefact.com\/?post_type=news&#038;p=61415"},"modified":"2024-09-20T17:45:45","modified_gmt":"2024-09-20T16:45:45","slug":"how-to-deploy-and-secure-your-streamlit-app-on-gcp","status":"publish","type":"blog","link":"https:\/\/www.artefact.com\/nl\/blog\/how-to-deploy-and-secure-your-streamlit-app-on-gcp\/","title":{"rendered":"Hoe implementeert en beveiligt u uw Streamlit app op GCP?"},"content":{"rendered":"<p><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-1 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling article-author\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-background-color:#ffffff;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-0 fusion_builder_column_1_2 1_2 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:50%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:50%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-title title fusion-title-1 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Author<\/h2><\/div><img decoding=\"async\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27150%27%20height%3D%270%27%20viewBox%3D%270%200%20150%200%27%3E%3Crect%20width%3D%27150%27%20height%3D%270%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/05\/Rafaelle-Aygalenq-300x300.jpeg\" alt=\"Image\" class=\"lazyload artefact-elegant-image align-left article-author-image\" style=\"width: 150px; border-radius: 54% 46% 77% 23% \/ 74% 40% 60% 26%; overflow: hidden;\" width=\"150\" height=\"auto\" \/><div class=\"fusion-title title fusion-title-2 fusion-sep-none fusion-title-text fusion-title-size-three article-author-name-title\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Rafaelle Aygalenq<\/h3><\/div><div class=\"fusion-text fusion-text-1 article-author-description\"><p>Senior Data Scientist at Artefact France<\/p>\n<\/div><\/div><\/div><\/div><\/div><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-2 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-1 fusion_builder_column_1_1 1_1 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-text fusion-text-2 description\"><p><strong>TL;DR<\/strong><br \/>\nStreamlit is a great tool to create beautiful data applications quite easily but when it comes to deploying them and making them accessible, it can be more complicated for non-specialists. In this article we aim at presenting our journey to deploying our application on GCP ensuring a restricted access to specific people. We implemented two solutions: one with Cloud Run, the other with App Engine and we chose to keep App Engine for its ease of securing the application with IAP (Identity-Aware Proxy).<\/p>\n<\/div><\/div><\/div><\/div><\/div><div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-3 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-margin-top:40px;--awb-margin-bottom:40px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-center fusion-flex-justify-content-center fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-2 fusion_builder_column_1_1 1_1 fusion-flex-column fusion-flex-align-self-center\" style=\"--awb-padding-top:40px;--awb-padding-right:40px;--awb-padding-bottom:40px;--awb-padding-left:40px;--awb-overflow:hidden;--awb-bg-position:left center;--awb-bg-size:cover;--awb-border-color:rgba(10,17,40,0.1);--awb-border-style:solid;--awb-border-radius:4px 4px 4px 4px;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper lazyload fusion-column-has-shadow fusion-flex-justify-content-center fusion-content-layout-column fusion-column-has-bg-image\" data-bg-url=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/03\/background.jpg\" data-bg=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/03\/background.jpg\"><div class=\"fusion-image-element\" style=\"text-align:center;--awb-margin-right:20px;--awb-margin-left:20px;--awb-max-width:150px;--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);\"><span class=\" fusion-imageframe imageframe-none imageframe-1 hover-type-none\"><img decoding=\"async\" width=\"72\" height=\"41\" title=\"medium\" src=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%2772%27%20height%3D%2741%27%20viewBox%3D%270%200%2072%2041%27%3E%3Crect%20width%3D%2772%27%20height%3D%2741%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/03\/medium.png\" alt class=\"lazyload img-responsive wp-image-60927\"\/><\/span><\/div><div class=\"fusion-title title fusion-title-3 fusion-sep-none fusion-title-center fusion-title-text fusion-title-size-three\" style=\"--awb-margin-top:20px;--awb-margin-bottom:0px;--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-center fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Medium Blog by Artefact.<\/h3><\/div><div class=\"fusion-text fusion-text-3\" style=\"--awb-content-alignment:center;\"><p>This article was initially published on <strong>Medium.com<\/strong>.<br \/>\nFollow us on our Medium Blog !<\/p>\n<\/div><div style=\"text-align:center;\"><a class=\"fusion-button button-flat button-medium button-default fusion-button-default button-1 fusion-button-default-span fusion-button-default-type\" target=\"_blank\" rel=\"noopener noreferrer\" href=\"https:\/\/medium.com\/artefact-engineering-and-data-science\/serving-ml-models-at-scale-using-mlflow-on-kubernetes-bf27258775e7\"><span class=\"fusion-button-text awb-button__text awb-button__text--default\">Read Our Article<\/span><\/a><\/div><\/div><\/div><\/div><\/div><article class=\"fusion-fullwidth fullwidth-box fusion-builder-row-4 fusion-flex-container nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-justify-content-center fusion-flex-content-wrap\" style=\"max-width:calc( 1440px + 20px );margin-left: calc(-20px \/ 2 );margin-right: calc(-20px \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-3 fusion_builder_column_1_1 1_1 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:10px;--awb-margin-bottom-large:0px;--awb-spacing-left-large:10px;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:10px;--awb-spacing-left-medium:10px;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:10px;--awb-spacing-left-small:10px;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-title title fusion-title-4 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Deployment motivations<\/h2><\/div><div class=\"fusion-text fusion-text-4\"><p>In this article, we will take the example of the Text Data Explorer, a Streamlit application that we have developed aiming to provide insights on raw text data in few minutes and few clicks. This application will be presented in a future article.<\/p>\n<\/div><div class=\"fusion-text fusion-text-5\"><p><img decoding=\"async\" class=\"lazyload aligncenter wp-image-61416 size-full\" src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP.png\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP.png\" alt=\"Example of the app that will be deployed on GCP\" width=\"998\" height=\"418\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27998%27%20height%3D%27418%27%20viewBox%3D%270%200%20998%20418%27%3E%3Crect%20width%3D%27998%27%20height%3D%27418%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP-200x84.png 200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP-300x126.png 300w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP-400x168.png 400w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP-600x251.png 600w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP-768x322.png 768w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP-800x335.png 800w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Example-of-the-app-that-will-be-deployed-on-GCP.png 998w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 998px) 100vw, 998px\" \/><\/p>\n<p style=\"text-align: center;\">Example of the app that will be deployed on GCP<\/p>\n<\/div><div class=\"fusion-text fusion-text-6\"><p>There are two main options to launch this application and this process:<\/p>\n<\/div><ul style=\"--awb-line-height:27.2px;--awb-icon-width:27.2px;--awb-icon-height:27.2px;--awb-icon-margin:11.2px;--awb-content-margin:38.4px;\" class=\"fusion-checklist fusion-checklist-1 fusion-checklist-default type-icons\"><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Either the user clones the GitHub repository on his computer, installs all the dependencies and launches the application on a local environment.<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Or the user has direct access to the application using a dedicated URL without any prior installation.<\/p>\n<\/div><\/li><\/ul><div class=\"fusion-text fusion-text-7\"><p>In order to make the application available to the largest number of people within our company, and therefore people who are not necessarily used to dealing with GitHub, we have decided to deploy the application on GCP (Google Cloud Platform) and make it accessible via a single URL in a secure environment.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-5 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Step-by-step deployment on GCP<\/h2><\/div><div class=\"fusion-text fusion-text-8\"><p>Two different approaches have been tested to deploy the application on GCP:<\/p>\n<\/div><ul style=\"--awb-line-height:27.2px;--awb-icon-width:27.2px;--awb-icon-height:27.2px;--awb-icon-margin:11.2px;--awb-content-margin:38.4px;\" class=\"fusion-checklist fusion-checklist-2 fusion-checklist-default type-icons\"><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Using Cloud Run<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Using App Engine<\/p>\n<\/div><\/li><\/ul><div class=\"fusion-text fusion-text-9\"><p>However, there is a preliminary common step that concerns both of these approaches which consists in the \u201cdockerization\u201d of our application.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-6 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Dockerizing the application<\/h3><\/div><div class=\"fusion-text fusion-text-10\"><p>If you are not familiar with Docker, here is a small introduction but do not hesitate to check out the <a href=\"https:\/\/www.docker.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">documentation<\/a> or more specific articles for further details.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-7 fusion-sep-none fusion-title-text fusion-title-size-five\" style=\"--awb-margin-bottom-small:8px;\"><h5 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\"><strong><em>What is docker?<\/em><\/strong><\/h5><\/div><div class=\"fusion-text fusion-text-11\"><p><em>Docker is an open platform for developing, shipping, and running applications. It allows you to package an application with all of its dependencies into a standardized unit for software development. In practice, this involves building what is called a Docker image, i.e. the blueprints of the application which form the basis of Docker containers, the content at rest. In order to build this image, we need to define a Dockerfile, i.e. a simple text-file that contains a list of commands that the Docker client calls while creating an image. Once built, the image is stored in a registry (e.g. Container Registry on GCP) and can be deployed on a dedicated instance, via Cloud Run or App Engine for example.<\/em><\/p>\n<\/div><div class=\"fusion-text fusion-text-12\"><p>Therefore in our case we have to:<\/p>\n<\/div><ul style=\"--awb-line-height:27.2px;--awb-icon-width:27.2px;--awb-icon-height:27.2px;--awb-icon-margin:11.2px;--awb-content-margin:38.4px;\" class=\"fusion-checklist fusion-checklist-3 fusion-checklist-default type-icons\"><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Create a Dockerfile<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Build our application image<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Store the image on a registry<\/p>\n<\/div><\/li><\/ul><div class=\"fusion-text fusion-text-13\"><p>Let\u2019s start with the creation of the Dockerfile. As mentioned before, this consists in a succession of commands used to create the Docker image. In the case of a Streamlit application, the Dockerfile can be divided into several blocks:<\/p>\n<\/div><ul style=\"--awb-line-height:27.2px;--awb-icon-width:27.2px;--awb-icon-height:27.2px;--awb-icon-margin:11.2px;--awb-content-margin:38.4px;\" class=\"fusion-checklist fusion-checklist-4 fusion-checklist-default type-icons\"><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Define the runtime environment: in our case python 3.7<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Define the port on which the application will run<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Install the needed libraries and their dependencies using a requirements.txt file<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Copy the code of your application and define the working directory from where the application will be launched<\/p>\n<\/div><\/li><li class=\"fusion-li-item\" style=\"\"><span class=\"icon-wrapper circle-no\"><i class=\"fusion-li-icon awb-icon-check\" aria-hidden=\"true\"><\/i><\/span><div class=\"fusion-li-item-content\">\n<p>Define the command to run the application<\/p>\n<\/div><\/li><\/ul><div class=\"fusion-text fusion-text-14\"><p>\u251c\u2500\u2500 app.py &lt;- Main script to launch the Streamlit app<br \/>\n\u251c\u2500\u2500 text_explorer &lt;- Folder gathering all the functions and code<br \/>\n\u251c\u2500\u2500 requirements.txt &lt;- File listing needed libraries to install<br \/>\n\u2514\u2500\u2500 references &lt;- Folder containing logos and images<\/p>\n<\/div><div class=\"fusion-text fusion-text-15\"><p>With this structure, here is an example of the Dockerfile we used for our application:<\/p>\n<\/div><div class=\"fusion-text fusion-text-16\"><div class=\"code\">\n<p>FROM python:3.7<\/p>\n<p># Expose port you want your app on<br \/>\nEXPOSE 8080<\/p>\n<p># Upgrade pip and install requirements<br \/>\nCOPY requirements.txt requirements.txt<br \/>\nRUN pip install -U pip<br \/>\nRUN pip install -r requirements.txt<\/p>\n<p># Copy app code and set working directory<br \/>\nCOPY text_explorer text_explorer<br \/>\nCOPY app.py app.py<br \/>\nCOPY references references<br \/>\nWORKDIR .<\/p>\n<p># Run<br \/>\nENTRYPOINT [&#8220;streamlit&#8221;, &#8220;run&#8221;, &#8220;app.py&#8221;, &#8220;&#8211;server.port=8080&#8221;, &#8220;&#8211;server.address=0.0.0.0&#8221;]\n<\/div>\n<\/div><div class=\"fusion-text fusion-text-17\"><p>Once the Dockerfile is created, we can build our image, following a GCP-friendly naming convention that will be helpful for the deployment later on. This is done via the following command:<\/p>\n<\/div><div class=\"fusion-text fusion-text-18\"><div class=\"code\">docker build -t eu.gcr.io\/gcp_project_name\/app_name:v1 .<\/div>\n<\/div><div class=\"fusion-text fusion-text-19\"><p>To adapt it to your own application, replace the \u2018<em>gcp_project_name\u2019<\/em> by your own GCP project name and the \u2018<em>app_name\u2019<\/em> by your own application name. You can also update the version number as your application evolves by modifying the \u2018<em>v1<\/em>\u2019 suffix with your current version.<\/p>\n<\/div><div class=\"fusion-text fusion-text-20\"><p>From there, with our application packaged in a docker image, we can deploy it on GCP to make it accessible to our teammates.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-8 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Deploy your app with Cloud Run<\/h3><\/div><div class=\"fusion-text fusion-text-21\"><p>Cloud Run is a GCP serverless cloud service used to easily deploy pre-built applications. One of its main advantages is that it automates most of the resources management process. Therefore, all you have to do is to tell Cloud Run where your Docker image is, and then Cloud Run will deploy it on a serverless environment without needing to specify the optimal number of resources for example.<\/p>\n<\/div><div class=\"fusion-text fusion-text-22\"><p>In order to do that, you can follow the steps listed below:<\/p>\n<\/div><div class=\"fusion-text fusion-text-23\"><ul>\n<li>Initialize <em>gcloud<\/em> module on the right GCP project with the following command:<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-24\"><p>gcloud init<\/p>\n<\/div><div class=\"fusion-text fusion-text-25\"><ul>\n<li>Push the docker to the GCP Container Registry with the following command:<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-26\"><div class=\"code\">docker push eu.gcr.io\/gcp_project_name\/app_name:v1<\/div>\n<\/div><div class=\"fusion-text fusion-text-27\"><ol>\n<li>Go on your GCP project, on the Cloud run section. Click on \u201cCreate service\u201d, choose the region and define your service name. Then, select the Docker image that corresponds to your Streamlit app and update the port with the one you defined in your Dockerfile<\/li>\n<\/ol>\n<\/div><div class=\"fusion-text fusion-text-28\"><p style=\"text-align: center;\"><img decoding=\"async\" class=\"lazyload aligncenter wp-image-61418 size-full\" src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Cloud-Run-interface.png\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Cloud-Run-interface.png\" alt=\"\" width=\"514\" height=\"637\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27514%27%20height%3D%27637%27%20viewBox%3D%270%200%20514%20637%27%3E%3Crect%20width%3D%27514%27%20height%3D%27637%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Cloud-Run-interface-200x248.png 200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Cloud-Run-interface-242x300.png 242w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Cloud-Run-interface-400x496.png 400w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/Cloud-Run-interface.png 514w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 514px) 100vw, 514px\" \/>Cloud Run interface<\/p>\n<\/div><div class=\"fusion-text fusion-text-29\"><ul>\n<li>Finally, you can test your app by following the URL linked to the newly created Cloud Run service<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-30\"><p>As you can see, the deployment is done in just a few steps and is quite easy, even for newcomers to application deployment. However, in our case, on top of the deployment, we also wanted to secure our application so that it would only be accessible within our company and at that time, we did not find any \u201ceasy\u201d solution that would fit with Cloud Run. That is why we decided to look for an alternative solution that would allow us to have this security layer without too much difficulty and we finally ended up with App Engine.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-9 fusion-sep-none fusion-title-text fusion-title-size-three\" style=\"--awb-margin-bottom-small:8px;\"><h3 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:20;line-height:1.2;\">Deploy your app with App Engine<\/h3><\/div><div class=\"fusion-text fusion-text-31\"><p>App Engine is a cloud-based computing service used to host web apps that are already in the Google infrastructure. In a nutshell, it allows you to do the same thing as Cloud Run in the sense that they are both Google cloud services that allow you to deploy applications. However, unlike Cloud Run where you only pay for the requests that come in, on App Engine you pay for the entire run time, whether there are requests or not. Thus at the end, App Engine may be a more expensive solution. Despite this, we still decided to go for this solution because App Engine has the advantage of having a native integration with IAP (Identity-Aware Proxy) that allows to easily secure your application.<\/p>\n<\/div><div class=\"fusion-text fusion-text-32\"><p>The steps to achieve a deployment on App Engine are not more numerous nor more complicated than for Cloud Run, here is what you need to do:<\/p>\n<\/div><div class=\"fusion-text fusion-text-33\"><ul>\n<li>Check the port specified in your Dockefile, it has to be 8080 to be compatible with App Engine<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-34\"><ul>\n<li>Initialize gcloud module on the right GCP project with the following command:<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-35\"><div class=\"code\">gcloud init<\/div>\n<\/div><div class=\"fusion-text fusion-text-36\"><ul>\n<li>Create a YAML file for your app (named app.yaml) at the root of your project (i.e. at the same level as your main script and your Dockerfile) with the following template:<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-37\"><p style=\"text-align: center;\"><img decoding=\"async\" class=\"lazyload aligncenter wp-image-61419 size-full\" src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/app.yaml-file-example.png\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/app.yaml-file-example.png\" alt=\"app.yaml file example\" width=\"222\" height=\"71\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27222%27%20height%3D%2771%27%20viewBox%3D%270%200%20222%2071%27%3E%3Crect%20width%3D%27222%27%20height%3D%2771%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/app.yaml-file-example-200x64.png 200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/app.yaml-file-example.png 222w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 222px) 100vw, 222px\" \/>app.yaml file example<\/p>\n<\/div><div class=\"fusion-text fusion-text-38\"><p><em>Update the service name with your own application service name<\/em><\/p>\n<\/div><div class=\"fusion-text fusion-text-39\"><p>Here we defined the runtime: custom option because custom runtimes let you build apps that run in an environment defined by a Dockerfile as it is the case for us. The env:flex option means that our application will be run in the flexible environment (by opposition to the standard environment). This choice was made because the flexible environment runs the application in Docker containers on Google Compute Engine virtual machines (VMs), which have fewer restrictions than in the standard environment (e.g. your app cannot write to disk). More details about the key differences are available in the Google documentation.<\/p>\n<\/div><div class=\"fusion-text fusion-text-40\"><p>You can also include more detailed network, resources and scaling settings within the YAML file such as the minimum number of instances given to your service or the number of CPUs for example. You can also define some environment variables in that file to make them accessible to your application.<\/p>\n<\/div><div class=\"fusion-text fusion-text-41\"><ul>\n<li>Run the following command (this could take several minutes):<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-42\"><div class=\"code\">gcloud app deploy app.yaml<\/div>\n<\/div><div class=\"fusion-text fusion-text-43\"><ul>\n<li>Once done with the deploy command, the app will be available on App Engine and you will find its dedicated URL directly on GCP<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-44\"><p>If you want to secure your app and give a restricted access to some people, go to your GCP project, in the \u201cIAM &amp; Admin\u201d \/ \u201cIdentity-Aware Proxy\u201d section:<\/p>\n<\/div><div class=\"fusion-text fusion-text-45\"><ul>\n<li>In \u201cAll Web Services\u201d you should see an \u201cApp Engine app\u201d section. If IAP is off, turn it on and click on your Streamlit service.<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-46\"><p><img decoding=\"async\" class=\"lazyload wp-image-61421 size-full aligncenter\" src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-1.png\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-1.png\" alt=\"\" width=\"372\" height=\"247\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27372%27%20height%3D%27247%27%20viewBox%3D%270%200%20372%20247%27%3E%3Crect%20width%3D%27372%27%20height%3D%27247%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-1-200x133.png 200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-1-300x199.png 300w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-1.png 372w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 372px) 100vw, 372px\" \/> <img decoding=\"async\" class=\"lazyload wp-image-61422 size-full aligncenter\" src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-BIS.png\" data-orig-src=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-BIS.png\" alt=\"\" width=\"520\" height=\"461\" srcset=\"data:image\/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27520%27%20height%3D%27461%27%20viewBox%3D%270%200%20520%20461%27%3E%3Crect%20width%3D%27520%27%20height%3D%27461%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E\" data-srcset=\"https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-BIS-200x177.png 200w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-BIS-300x266.png 300w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-BIS-400x355.png 400w, https:\/\/www.artefact.com\/\/wp-content\/uploads\/2021\/06\/IAP-sections-to-manage-permissions-BIS.png 520w\" data-sizes=\"auto\" data-orig-sizes=\"(max-width: 520px) 100vw, 520px\" \/><\/p>\n<p style=\"text-align: center;\">IAP sections to manage permissions<\/p>\n<\/div><div class=\"fusion-text fusion-text-47\"><ul>\n<li>On the right, click on \u201cAdd member\u201d, enter all the email addresses you want (or an alias linked to a mailing list) and select the \u201cIAP-secured Web App User\u201d role.<\/li>\n<\/ul>\n<\/div><div class=\"fusion-text fusion-text-48\"><p>And you\u2019re done. Your application is now deployed and secured.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-10 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Tips if you have trouble with images display in your deployed app<\/h2><\/div><div class=\"fusion-text fusion-text-49\"><p>When using st.pyplot() or st.image(), you may encounter some display troubles when looking at your deployed application (i.e. \u201c0\u201d displayed instead of your plot or image). We recommend to use st.plotly_chart() whenever you can to avoid that and to use HTML code snippets otherwise. For example, in our case, we wanted to display some wordclouds and that could not be done with Plotly. Thus we decided to save the wordcloud image as PNG in a dedicated GCS bucket, download it as bytes and display it with some HTML code like this:<\/p>\n<\/div><div class=\"fusion-text fusion-text-50\"><div class=\"code\">def display_wordcloud(image):<br \/>\nst.markdown(<br \/>\nf\"\"\"<\/p>\n<div class=\"container\">\n<img decoding=\"async\" class=\"wordcloud\" src=\"data:image\/png;base64,\">\n<\/div>\n<p>\n\"\"\",<br \/>\nunsafe_allow_html=True<br \/>\n)<br \/>\nst.markdown(\"\")<br \/>\nst.markdown(\"\")<\/div>\n<\/div><div class=\"fusion-text fusion-text-51\"><p>In that example, the variable \u201cimage\u201d is a bytes object coming from the method .dowload_as_bytes() of Google cloud storage python package.<\/p>\n<\/div><div class=\"fusion-title title fusion-title-11 fusion-sep-none fusion-title-text fusion-title-size-two\" style=\"--awb-margin-bottom-small:8px;\"><h2 class=\"fusion-title-heading title-heading-left fusion-responsive-typography-calculated\" style=\"margin:0;--fontSize:50;line-height:1.2;\">Conclusion<\/h2><\/div><div class=\"fusion-text fusion-text-52\"><p>The purpose of this article was to give you some tips and examples of cloud services that can be used for deploying Streamlit applications. In our experience, if you need a security layer to ensure restricted access to some people, App Engine will be the appropriate solution. Otherwise, Cloud Run remains an easy way to deploy a Streamlit application.<\/p>\n<\/div><div class=\"fusion-text fusion-text-53\"><p><em>Credits: Paul Devienne, Amale El Hamri<\/em><\/p>\n<\/div><\/div><\/div><\/div><\/article><\/p>\n","protected":false},"excerpt":{"rendered":"<p>28 juni 2021<br \/>\nStreamlit is een geweldig hulpmiddel om vrij eenvoudig prachtige data toepassingen te maken, maar als het aankomt op het implementeren en toegankelijk maken ervan, kan het ingewikkelder zijn voor niet-specialisten. In dit artikel willen we onze reis naar het implementeren van onze applicatie op GCP presenteren, met beperkte toegang voor specifieke mensen. We hebben twee oplossingen ge\u00efmplementeerd: \u00e9\u00e9n met Cloud Run, de andere met App Engine en we hebben gekozen voor App Engine omdat het zo gemakkelijk is om de applicatie te beveiligen met IAP (Identity-Aware Proxy).<\/p>","protected":false},"featured_media":61423,"parent":0,"template":"","meta":{"_acf_changed":false,"ep_exclude_from_search":false},"blog-category":[22035],"blog-language":[2991],"class_list":["post-61415","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog-category-data-ai-consulting","blog-language-en"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/blog\/61415","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/types\/blog"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/media\/61423"}],"wp:attachment":[{"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/media?parent=61415"}],"wp:term":[{"taxonomy":"blog-category","embeddable":true,"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/blog-category?post=61415"},{"taxonomy":"blog-language","embeddable":true,"href":"https:\/\/www.artefact.com\/nl\/wp-json\/wp\/v2\/blog-language?post=61415"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}