How do you deploy a Streamlit app on App Engine (GCP)? - google-app-engine

I am aiming to deploy a simple web-app written with Sreamlit, e.g.
app.py
import streamlit as st
st.title('Hello World!')
I can run this on my local machine by running streamlit run app.py in my command line.
However, I'm not sure how to modify the app.yaml file in GCP's App Engine to deploy this.
Any advice?

You can use App Engine flexible environment for that as you can specify a custom runtime. The steps to follow will be:
Create the Dockerfile:
FROM python:3.7
EXPOSE 8080
WORKDIR /app
COPY requirements.txt ./requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD streamlit run app.py --server.port 8080
I have updated the Dockerfile as App Engine flex requires that the server listens on port 8080.
Create the requirements.txt file with the needed dependencies:
streamlit
Create the app.yaml file:
runtime: custom
env: flex
Both the app.yaml and the Dockerfile must be in the same folder. The above app.yaml settings are very basic, more information can be found in the documentation.
Then to deploy you need to use the following gcloud command:gcloud app deploy

Related

How to deploy multiple containers on Heroku?

I have created API(Flask RestFul) service, UI(in ReactJS) and Proxy service each having its own Dockerfile in their respective folder.
And there is Docker-compose.yaml file in main repository. It works locally on running following command docker-compose -f docker-compose.prod.yaml up, but I am unable to find way to deploy multiple containers on heroku?
Here is my github repo: https://github.com/Darpan313/Flask-React-nginx-Docker-Compose

How to deploy a Helidon application to Google Cloud App Engine?

I am trying to deploy an Helidon MP project to Google Cloud App Engine using java11 runtime but having trouble to define the app.yaml properly.
Tried to deploy the jar file directly using the below app.yaml using the command $ gcloud app deploy cord.jar. The app gets deployed but empty page on view.
runtime: java11
entrypoint: 'java -jar cord.jar'
Tried to modify the codewbase adding appengine\app.yaml to <project>\src\main\appengine\app.yaml and with contents as below and using command $ gcloud app deploy pom.xml:
runtime: java11
instance_class: F1
In all cases, the app got deployed but page loads empty.
They have examples on github but unfortunately not yet with Helidon.
I've put together an example for Helidon.
A couple things to note:
Make sure your application obeys the PORT environment variable, and configures its server to use that port.
Make sure your app.yaml is in the same directory as your jar and defines a custom entry point. For example:
runtime: java11
entrypoint: java -Xmx64m -jar helidon-quickstart-se.jar
Helidon uses "thin" jars and App Engine seems to handle this AOK as mentioned here: https://cloud.google.com/appengine/docs/standard/java11/runtime#application_startup
As an answer to my question.. issue for the page not loading was because of port 9090 that we were using (defined in src/main/resources/META-INF/microprofile-config.properties file). After i changed it to default 8080, my app worked.
microprofile-config.properties:
# Application properties. This is the default greeting
app.greeting=Hello
# Microprofile server properties
server.port=8080
server.host=0.0.0.0
References:
Helidon MP example for Google App Engine
There is a github thread regarding this and so far the current workaround is to add an app.yaml file similar to the one for the frameworks like Spring Boot or Vert.x
I have followed the tutorial where the github sample of the other responses is and it worked for me.
First I have cloned the repository and I used the quickstart mp:
git clone https://github.com/barchetta/helidon-google-app-engine-example/
cd helidon-google-app-engine-example/helidon-quickstart-mp
Then I have built and run the application and check if the port responds.
mvn package
export PORT=8888
java -jar target/helidon-quickstart-mp.jar
After all these previous steps I was able to see in localhost the result of the application.
For deploying I created the app.yaml file named "helidon-mp-app.yaml" and wrote this configuration inside:
runtime: java11
entrypoint: java -Xmx64m -jar helidon-quickstart-mp.jar
And copied it to the target/ directory:
cp helidon-mp-app.yaml target/
As the last configuration file, the file ".gcloudingonre" which also needs to be moved to target/
# Exclude everything. Then include just the app jar and runtime
# dependencies in libs/
*
*/
*/**
!helidon-quickstart-mp.jar
!libs/
!libs/**
Then as all the configuration files are ready, I executed
gcloud app deploy target/helidon-mp-app.yaml
gcloud app browse
And appending "/greet" in the URL we can see the result:
{"message":"Hello World!"}

Dependencies (requirements.txt) not installing correctly when deploying to Google App Engine using Google Cloud Build

I am experiencing a strange issue with dependencies when deploying my application to Google App Engine (Python 2.7).
I have specified my dependencies in the requirements.txt file:
Flask==1.0.2
werkzeug>=0.14
flask-cors
twilio
httplib2
gunicorn
Jinja2
google-cloud-ndb
exponent_server_sdk
These work fine with the local development server when installed locally with pip from the requirements.txt folder.
However, when I deploy to app engine, it appears that the module exponent_server_sdk has not been installed (ImportError: No module named exponent_server_sdk).
I normally deploy by pushing to a git repository which is then deployed with Google Cloud Build ("gcr.io/cloud-builders/gcloud"). There are no errors when I deploy and other dependencies in the requirements.txt file work fine such as twilio or Jinja2.
Whilst investigating this I tried pushing directly from my development machine with gcloud app deploy. When I do this, for some strange reason, exponent_server_sdk is available and works correctly.
This behaviour seems very strange to me and I can't find any documentation of people experiencing similar errors. I wonder if anyone can give me any guidance about what might be causing this issue or places I can look to find errors (for example logs of the process of installing the requirements.txt file during deployment/instance startup).
In response to the comments:
I am running in the standard environment.
My cloudbuild.yaml looks like this:
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy", "app.yaml", "dispatch.yaml", "service_1.yaml", "service_2.yaml", "service_3.yaml", "index.yaml"]
timeout: "1600s"
The .yaml file for the service in which I am experiencing the error looks like this:
runtime: python27
api_version: 1
threadsafe: true
service: notifications
libraries:
- name: ssl
version: latest
handlers:
- url: /.*
script: notifications.app
For the (1st gen) standard environment the deployment process does not use a requirements.txt file, the libraries should be installed inside your app. From Copying a third-party library:
Use pip (version 6 or later) with the -t <directory> flag to
copy the libraries into the folder you created in the previous step.
For example:
pip install -t lib/ <library_name>
Yes, if you want you can use a requirements.txt file to do the installation inside your app, but that file itself is not used by the deployment process.
Since you're not deploying directly from the environment in which you had the libraries installed you'd have to add the installation directory to the git repo as well.

Setup react app build folder onto Google Kubernetes

Currently, I have a repo that contains both a Node.js Express backend and React frontend. The repo's image is in Google Container Registry and is used on a Google Kubernetes cluster. There is an url provided by a load balancer, where it is the backend url that is serving the static build server. In the future, I want to separate the backend/frontend into two different repos (one for backend and one for frontend).
I believe making changes for the backend in the cluster won't be difficult, but I am having trouble figuring out how to add the React frontend to this since the build folder will be in a different repo than the backend. I read online that to serve a React app on GCP, you would upload the build folder onto a bucket and have that bucket served on App Engine, which will provide a url to access it on the web.
I'm wondering if this is how it would be done on a Kubernetes cluster or if there is a different approach since it is not using App Engine, rather Google Kubernetes.
I hope this makes sense (I am still fairly new to Google Cloud) and any feedback/tips will be appreciated!
Thanks!
There are different approaches to this.
Approach 1: Serve your frontend via Google Cloud Storage.
There is a guide in the GCP documentation: Hosting a static website to set this up. After the build copy all the files to the cloud storage and you are done.
Approach 2: Add your fronted to your backend while building the Docker image
Build your frontend and pack it into a Docker image with something like this:
FROM node AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM scratch
COPY --from=build /app/dist /app
Build your backend and copy the frontend:
FROM myapp/frontend as frontend
FROM node
// build backend
COPY --from=frontend /app /path/where/frontend/belongs
This decouples both builds but you will always have to deploy the backend for a frontend change.
Approach 3: Serve your frontend with nginx (or another web server)
FROM node AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM nginx
COPY --from=build /app/dist /usr/share/nginx/html
You might also adapt the nginx.conf to enable routing without hash paths. See this article by codecentric for more information on that.

How to use private, self hosted NPM package with Google App Engine node, standard environment

I have an NPM package hosted on a private Bitbucket git repo (not in the official NPM registry).
I have this in my package.json, under the "dependencies" key:
"a-private-package" git+ssh://git#bitbucket.org:myusername/a-private-package.git
It works when I run npm install locally as my SSH keys are used.
But when I use gcloud app deploy to deploy to the app engine standard environment for node, I get a Host key verification failed from Google Cloud Build.
I have tried:
Adding a custom SSH key to Cloud Build.
https://cloud.google.com/cloud-build/docs/access-private-github-repos
Issue: No access to cloudbuild.yaml for GAE standard; cannot tell git to use the SSH key.
Adding my private git repo to Google Sources.
Issue: No access to cloudbuild.yaml for GAE standard; cannot tell git to use the SSH key.
npm pack; npm install
Issue: Does not keep repo history/URL.
Is it actually possible?
It is not possible to modify the cloudbuild.yaml when you are running gcloud app deploy. Instead, you must create a new cloudbuild.yaml and execute it with gcloud builds submit --config=cloudbuild.yaml . In this case, the gcloud app deploy is going to be executed inside the cloudbuild.yaml.
I have tried the steps described for connecting to a private Github repository and changing the values to fit it with bitbucket, but was not able to. Thus, I have created this Feature Request for better documentation
Using Cloud Source Repositories
I believe that, as you already have a dependency on the private repo, then it will be simpler to host you entire app on it. Given this, you will have to clone the entire repo, run npm install and deploy.
In this case, Cloud Source Repositories has a built in feature to mirror directly to Bitbucket (public and private repos).
Steps:
1) Create on your app root folder a cloudbuild.yaml with the following code:
steps:
# NPM install
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
#Test
- name: 'gcr.io/cloud-builders/npm'
args: ['test']
#Deploy
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
2) Connect Cloud Source Repositories to Bitbucket
3) Create a Cloud Build Trigger (so new code pushed to the repo will be automatically deployed)
4) Push the root folder containing the app.yaml and the cloudbuild.yaml to the repo
It should now be Synced to Cloud Source Repositories and it should trigger the Cloud Build for the deploy.
Unfortunately you will need to embed a username/password in the package.json, but you can probably use the https endpoint:
"a-private-package": "git+https://myusername:password#bitbucket.org/myusername/a-private-package.git"
If this works for you I'd suggest creating a separate account on bitbucket and restricting it to view-only on that repo.

Resources