A simple serverless application deployed to Google Cloud Run that displays "Hello, world!" along with the visitor's user agent and IP address. The application features a React frontend with a Flask backend API.
- React-based frontend for enhanced user experience
- Flask backend API for serving user information
- Displays a greeting message
- Shows the visitor's User Agent
- Shows the visitor's IP address (with proxy support)
- Automatic deployment to Google Cloud Run via GitHub Actions
app.py- Flask backend API serving React app and user information endpointfrontend/- React frontend applicationrequirements.txt- Python dependenciesDockerfile- Multi-stage container build (Node.js for React, Python for Flask).github/workflows/deploy-to-gcp.yml- GitHub Actions workflow for automatic deployment
- A Google Cloud Platform (GCP) account
- A GitHub account with this repository
gcloudCLI installed locally (for initial setup)
# Create a new project (or use an existing one)
gcloud projects create YOUR_PROJECT_ID --name="Hello World App"
# Set the project as default
gcloud config set project YOUR_PROJECT_ID# Enable Cloud Run API
gcloud services enable run.googleapis.com
# Enable Artifact Registry API
gcloud services enable artifactregistry.googleapis.com
# Enable IAM Credentials API (for Workload Identity)
gcloud services enable iamcredentials.googleapis.com# Create a Docker repository in Artifact Registry
gcloud artifacts repositories create helloworld-app \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository for Hello World app"Workload Identity Federation allows GitHub Actions to authenticate to GCP without using service account keys.
# Create a Workload Identity Pool
gcloud iam workload-identity-pools create "github-pool" \
--project="YOUR_PROJECT_ID" \
--location="global" \
--display-name="GitHub Actions Pool"
# Create a Workload Identity Provider
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
--project="YOUR_PROJECT_ID" \
--location="global" \
--workload-identity-pool="github-pool" \
--display-name="GitHub Provider" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
--attribute-condition="assertion.repository_owner=='YOUR_GITHUB_USERNAME_OR_ORG'" \
--issuer-uri="https://token.actions.githubusercontent.com"# Create a service account for GitHub Actions
gcloud iam service-accounts create github-actions-sa \
--display-name="GitHub Actions Service Account" \
--project="YOUR_PROJECT_ID"
# Grant necessary permissions to the service account
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:github-actions-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:github-actions-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/artifactregistry.writer"
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:github-actions-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
# Allow the Workload Identity Pool to impersonate the service account
gcloud iam service-accounts add-iam-policy-binding \
github-actions-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com \
--project="YOUR_PROJECT_ID" \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/attribute.repository/YOUR_GITHUB_USERNAME/gcp-serverless-helloworld"Note: Replace PROJECT_NUMBER with your actual GCP project number (not ID). You can find it by running:
gcloud projects describe YOUR_PROJECT_ID --format="value(projectNumber)"Add the following secrets to your GitHub repository (Settings → Secrets and variables → Actions):
-
GCP_PROJECT_ID
- Your GCP project ID
- Example:
my-project-12345
-
GCP_WORKLOAD_IDENTITY_PROVIDER
- Format:
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-pool/providers/github-provider - Get it by running:
gcloud iam workload-identity-pools providers describe github-provider \ --project="YOUR_PROJECT_ID" \ --location="global" \ --workload-identity-pool="github-pool" \ --format="value(name)"
- Format:
-
GCP_SERVICE_ACCOUNT
- Your service account email
- Format:
github-actions-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
Once configured, the application will automatically deploy to Google Cloud Run whenever you push to the main branch.
# Push to main branch to trigger deployment
git push origin mainThe deployment workflow will:
- Build a Docker image
- Push it to Google Artifact Registry
- Deploy to Cloud Run
- Display the service URL in the workflow logs
To run the application locally:
# Install Python dependencies
pip install -r requirements.txt
# Build the React frontend
cd frontend
npm install
npm run build
cd ..
# Run the Flask application
python app.pyThe app will be available at http://localhost:8080
For frontend development with hot reloading:
# Terminal 1: Run Flask backend
python app.py
# Terminal 2: Run React dev server (in frontend directory)
cd frontend
npm startNote: In development mode, the React dev server runs on port 3000 and proxies API calls to Flask on port 8080.
To test the Docker container locally:
# Build the image (includes React build)
docker build -t helloworld-app .
# Run the container
docker run -p 8080:8080 helloworld-app
# Access the app at http://localhost:8080Edit the REGION environment variable in .github/workflows/deploy-to-gcp.yml:
env:
REGION: us-central1 # Change to your preferred regionDon't forget to create your Artifact Registry repository in the same region.
Edit the SERVICE_NAME environment variable in .github/workflows/deploy-to-gcp.yml:
env:
SERVICE_NAME: helloworld-app # Change to your preferred nameAlso update the Artifact Registry repository name accordingly.
If you encounter authentication errors:
- Verify all secrets are correctly set in GitHub
- Ensure the Workload Identity Pool is properly configured
- Check that the service account has the necessary permissions
If deployment fails:
- Check the GitHub Actions logs for detailed error messages
- Verify that all required GCP APIs are enabled
- Ensure the Artifact Registry repository exists in the correct region
If the app doesn't work as expected:
- Check Cloud Run logs:
gcloud run logs read helloworld-app --region=us-central1 - Verify the service is publicly accessible (--allow-unauthenticated)
- The application is deployed with
--allow-unauthenticatedflag, making it publicly accessible - IP addresses are captured from
X-Forwarded-Forheader (set by Cloud Run) - For production use, consider implementing authentication and rate limiting
This project is provided as-is for educational purposes.