From dda467b104a1078ac54d461c1d037ebe722ff581 Mon Sep 17 00:00:00 2001 From: muthukamalan Date: Fri, 29 Nov 2024 11:39:46 +0530 Subject: [PATCH 1/2] gradio example deploying gradio web-server by using aws-lambda-adapter leveraging CDK CLI --- examples/gradio/.gitignore | 247 +++++++++++++++++++++++++++ examples/gradio/README.md | 126 ++++++++++++++ examples/gradio/app/Dockerfile | 22 +++ examples/gradio/app/app.py | 35 ++++ examples/gradio/app/cdk.json | 4 + examples/gradio/app/cdk.py | 41 +++++ examples/gradio/app/requirements.txt | 1 + 7 files changed, 476 insertions(+) create mode 100644 examples/gradio/.gitignore create mode 100644 examples/gradio/README.md create mode 100644 examples/gradio/app/Dockerfile create mode 100644 examples/gradio/app/app.py create mode 100644 examples/gradio/app/cdk.json create mode 100644 examples/gradio/app/cdk.py create mode 100644 examples/gradio/app/requirements.txt diff --git a/examples/gradio/.gitignore b/examples/gradio/.gitignore new file mode 100644 index 00000000..45d6c9fb --- /dev/null +++ b/examples/gradio/.gitignore @@ -0,0 +1,247 @@ +flagged/ + +.aws-sam + +# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### OSX ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Ruby plugin and RubyMine +/.rakeTasks + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +.pytest_cache/ +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule.* + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Build folder + +*/build/* + +# End of https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode \ No newline at end of file diff --git a/examples/gradio/README.md b/examples/gradio/README.md new file mode 100644 index 00000000..2e7d82c1 --- /dev/null +++ b/examples/gradio/README.md @@ -0,0 +1,126 @@ +# Gradio example + +A basic Gradio application example. You can build and test it locally as a typical Gradio application. + +Using AWS Lambda Web Adapter, You can package this web application into Docker image, push to ECR, and deploy to Lambda, ECS/EKS, or EC2. + +The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). + + +Here will see how to do it by [AWS CDK](https://aws.amazon.com/cdk/) + +# Pre-requisites +* [AWS CLI](https://aws.amazon.com/cli/) +* [Python](https://www.python.org/) +* [Docker](https://www.docker.com/products/docker-desktop) +* [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) + + + +### IAM Rules: +- permission to Pull images from Public Repository +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "ecr-public:PutRegistryAlias", + "Resource": "arn:aws:ecr-public::123456789012:registry/*" + } + ] +} +``` + +### CDK Env variables +```bash +CDK_DEFAULT_ACCOUNT=$(aws sts get-caller-identity --query Account) +CDK_DEFAULT_REGION=$(aws configure get region) +``` + + + +## Dockerfile + +```Dockerfile +# Base Image +FROM public.ecr.aws/docker/library/python:3.8.12-slim-buster +# Lambda Adapter +# lambda adapter binary into /opt/extensions. This is the only change to run the application on Lambda. +COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter +ENV PORT=8080 + +WORKDIR /var/task + +# Install system dependencies if needed +RUN apt-get update && apt-get install -y --no-install-recommends build-essential && rm -rf /var/lib/apt/lists/* + +# Copy and install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +# Expose Gradio default port +EXPOSE 8080 + +# Use explicit Python interpreter path +CMD ["python", "app.py"] +``` + +Line 2 *copies lambda adapter binary into /opt/extensions. This is the only change to run the Flask application on Lambda.* + +# Build and Deploy + +In cdk.json we focusing on cdk.py +```json +{ + "app": "python3 cdk.py" +} +``` + + +In addition to Lambda function add function url so it'll easy for redirect. but it'll refresh whenever lambda function refreshes. + +```py +# STACK +class GradioLambdaFn(Stack): + def __init__(self,scope:Construct,construct_id:str,**kwargs)->None: + super().__init__(scope,construct_id,**kwargs) + + # Lambda Fn + lambda_fn = DockerImageFunction( + self, + id="AWSLambdaAdapterGradioExample", + code=DockerImageCode.from_image_asset( directory= os.path.dirname(__file__) , file="Dockerfile"), + architecture=Architecture.X86_64, + timeout=Duration.minutes(10), + ) + + # HTTP URL add + fn_url = lambda_fn.add_function_url(auth_type=FunctionUrlAuthType.NONE) + + # print + CfnOutput(self,id="functionURL",value=fn_url.url,description="cfn_output") + +# APP +app = App() +gradio_lambda = GradioLambdaFn(app,"GradioLambda",env=env) +app.synth() +``` + + + +# Deploy CDK +Navigate to folder and use the CDK CLI to build a CloudFormation Stack + +To deploy cdk app into AWS +```bash +cdk synth +cdk deploy --verbose +cdk destroy +``` + +## Verify it works +Open URL's URL in a browser, here we print in the console by `CfnOutput` you should see "Gradio" on the page. \ No newline at end of file diff --git a/examples/gradio/app/Dockerfile b/examples/gradio/app/Dockerfile new file mode 100644 index 00000000..b9de12eb --- /dev/null +++ b/examples/gradio/app/Dockerfile @@ -0,0 +1,22 @@ + +FROM public.ecr.aws/docker/library/python:3.8.12-slim-buster +COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter +ENV PORT=8080 + +WORKDIR /var/task + +# Install system dependencies if needed +RUN apt-get update && apt-get install -y --no-install-recommends build-essential && rm -rf /var/lib/apt/lists/* + +# Copy and install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +# Expose Gradio default port +EXPOSE 8080 + +# Use explicit Python interpreter path +CMD ["python", "app.py"] \ No newline at end of file diff --git a/examples/gradio/app/app.py b/examples/gradio/app/app.py new file mode 100644 index 00000000..6d0df465 --- /dev/null +++ b/examples/gradio/app/app.py @@ -0,0 +1,35 @@ +import gradio as gr + +# Gradio Function +def greet(name, intensity): + return "Hello, " + name + "!" * int(intensity) + + + +# Define a no-op flagging callback +class NoOpFlaggingCallback(gr.FlaggingCallback): + def setup(self, components, flagging_dir): + pass # Override setup to prevent directory creation + + def flag(self, flag_data, flag_option=None, flag_index=None, username=None): + pass # Do nothing when a flag is submitted + + +# Interface +demo = gr.Interface( + fn=greet, + inputs=["text", "slider"], + outputs=["text"], + title="Hello world", + description="helper for aws-lambda-adapters", + flagging_options=[], + flagging_callback=NoOpFlaggingCallback(), +) + +demo.launch( + server_name="0.0.0.0", + server_port=8080, + enable_monitoring=None, + share=False, + debug=False +) \ No newline at end of file diff --git a/examples/gradio/app/cdk.json b/examples/gradio/app/cdk.json new file mode 100644 index 00000000..8e207c52 --- /dev/null +++ b/examples/gradio/app/cdk.json @@ -0,0 +1,4 @@ +{ + "app": "python3 cdk.py" +} + \ No newline at end of file diff --git a/examples/gradio/app/cdk.py b/examples/gradio/app/cdk.py new file mode 100644 index 00000000..9d9df4f4 --- /dev/null +++ b/examples/gradio/app/cdk.py @@ -0,0 +1,41 @@ +import os +from constructs import Construct +from aws_cdk import App, Stack,Duration,CfnOutput,Environment +from aws_cdk.aws_lambda import ( + DockerImageFunction, + DockerImageCode, + Architecture, + FunctionUrlAuthType +) + + +class GradioLambdaFn(Stack): + def __init__(self,scope:Construct,construct_id:str,**kwargs)->None: + super().__init__(scope,construct_id,**kwargs) + + # Lambda Fn + lambda_fn = DockerImageFunction( + self, + id="AWSLambdaAdapterGradioExample", + code=DockerImageCode.from_image_asset( directory= os.path.dirname(__file__) , file="Dockerfile"), + architecture=Architecture.X86_64, + timeout=Duration.minutes(10), + description="dockerfile_lambda_deploy_using_cdk", + ) + + # HTTP URL add + fn_url = lambda_fn.add_function_url(auth_type=FunctionUrlAuthType.NONE) + + # print + CfnOutput(self,id="functionURL",value=fn_url.url,description="cfn_output") + + +# My Environment +env = Environment( + account= os.environ.get('CDK_DEFAULT_ACCOUNT'), + region=os.environ.get('CDK_DEFAULT_REGION') +) + +app = App() +gradio_lambda = GradioLambdaFn(app,"GradioLambda",env=env) +app.synth() \ No newline at end of file diff --git a/examples/gradio/app/requirements.txt b/examples/gradio/app/requirements.txt new file mode 100644 index 00000000..512211da --- /dev/null +++ b/examples/gradio/app/requirements.txt @@ -0,0 +1 @@ +gradio==4.44.1 \ No newline at end of file From 9f809595d2edc9af477fc484cc4141016e908246 Mon Sep 17 00:00:00 2001 From: Muthu kamalan Date: Mon, 6 Jan 2025 00:55:50 +0530 Subject: [PATCH 2/2] pr:#553 moving gradio example to different [CDK IaC Tool ] folder --- examples/{ => cdk}/gradio/.gitignore | 0 examples/{ => cdk}/gradio/README.md | 0 examples/{ => cdk}/gradio/app/Dockerfile | 0 examples/{ => cdk}/gradio/app/app.py | 0 examples/{ => cdk}/gradio/app/cdk.json | 0 examples/{ => cdk}/gradio/app/cdk.py | 0 examples/{ => cdk}/gradio/app/requirements.txt | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => cdk}/gradio/.gitignore (100%) rename examples/{ => cdk}/gradio/README.md (100%) rename examples/{ => cdk}/gradio/app/Dockerfile (100%) rename examples/{ => cdk}/gradio/app/app.py (100%) rename examples/{ => cdk}/gradio/app/cdk.json (100%) rename examples/{ => cdk}/gradio/app/cdk.py (100%) rename examples/{ => cdk}/gradio/app/requirements.txt (100%) diff --git a/examples/gradio/.gitignore b/examples/cdk/gradio/.gitignore similarity index 100% rename from examples/gradio/.gitignore rename to examples/cdk/gradio/.gitignore diff --git a/examples/gradio/README.md b/examples/cdk/gradio/README.md similarity index 100% rename from examples/gradio/README.md rename to examples/cdk/gradio/README.md diff --git a/examples/gradio/app/Dockerfile b/examples/cdk/gradio/app/Dockerfile similarity index 100% rename from examples/gradio/app/Dockerfile rename to examples/cdk/gradio/app/Dockerfile diff --git a/examples/gradio/app/app.py b/examples/cdk/gradio/app/app.py similarity index 100% rename from examples/gradio/app/app.py rename to examples/cdk/gradio/app/app.py diff --git a/examples/gradio/app/cdk.json b/examples/cdk/gradio/app/cdk.json similarity index 100% rename from examples/gradio/app/cdk.json rename to examples/cdk/gradio/app/cdk.json diff --git a/examples/gradio/app/cdk.py b/examples/cdk/gradio/app/cdk.py similarity index 100% rename from examples/gradio/app/cdk.py rename to examples/cdk/gradio/app/cdk.py diff --git a/examples/gradio/app/requirements.txt b/examples/cdk/gradio/app/requirements.txt similarity index 100% rename from examples/gradio/app/requirements.txt rename to examples/cdk/gradio/app/requirements.txt