Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
dbe3f5f
Import PyPy/GCP files from features/pypy-runtime
toooadi Jan 5, 2026
4b1f84d
Small fixes
toooadi Jan 5, 2026
c70c2ed
[system] Remove pypy references
mcopik Apr 23, 2026
f62437a
[dev] Linting
mcopik Apr 23, 2026
8a2c2f0
[gcp] Adapt to new container interface
mcopik Apr 23, 2026
524c825
Add GCP Pypy container benchmark files
toooadi Dec 12, 2025
ed50eb2
[gcp] Adjust interface between functions and containers
mcopik Apr 23, 2026
10f360b
[gcp] Adjust containers to the new deployment model
mcopik Apr 23, 2026
5318a05
[gcp] Add enum for the deployment type
mcopik Apr 23, 2026
d9a376e
[gcp] Refactorization of different implementations
mcopik Apr 24, 2026
deffe3e
[gcp] Correct update of function code
mcopik Apr 24, 2026
35308cf
[gcp] Add dedicated deployment config
mcopik Apr 24, 2026
de477c1
[gcp] Make library trigger working again
mcopik Apr 24, 2026
ecaa9ad
[gcp] Support loading config from measuremnets
mcopik Apr 26, 2026
487ace0
[gcp] Update wrapper to return request ID from both container and fun…
mcopik Apr 27, 2026
f2eb1c5
[gcp] Resolve image degists to ensure updates on GCP containers
mcopik Apr 27, 2026
14d75b9
[gcp] Store image URI with the function - current version
mcopik Apr 27, 2026
32a401e
[gcp] Add metric download for both functions and containers
mcopik Apr 27, 2026
54c8e5c
[gcp] GCP also does not support arm64 on containers
mcopik Apr 27, 2026
9c12466
[gcp] Simplify GCP conditional checks on container
mcopik Apr 27, 2026
9044990
[gcp] Disable extra checks
mcopik Apr 27, 2026
6364077
[gcp] Add additional configuration parameters for worker threading
mcopik Apr 27, 2026
f3b590c
[gcp] Add gunicorn as default Python driver and make it configurable
mcopik Apr 27, 2026
4e9987b
[gcp] Revemo debug logging
mcopik Apr 27, 2026
4950ff4
[gcp] Shorten names to fit into limit
mcopik Apr 27, 2026
4b1edee
[gcp] Fix default parameters ofr Python
mcopik Apr 27, 2026
f050e94
[gcp] Remove all name-based checks
mcopik Apr 27, 2026
eb7e1d5
[gcp] Test deletion of containers
mcopik Apr 27, 2026
992ce4e
[gcp] Update Python images
mcopik Apr 27, 2026
1a69439
[gcp] In gen1 functions, update metric download from execution id to …
mcopik Apr 27, 2026
7626a9c
[gcp] Update node.js deployments
mcopik Apr 27, 2026
5bae394
[gcp] Bump Java base image
mcopik Apr 27, 2026
369b937
[gcp] Add base image for Java containers
mcopik Apr 27, 2026
5b82d96
[gcp] Move handling of new request ids from cloud to local
mcopik Apr 27, 2026
3d7c82e
[gcp] Remove duplicated default values
mcopik Apr 27, 2026
637fc53
[gcp] Update configs
mcopik Apr 27, 2026
294b21b
[gcp] Avoid infinite wait
mcopik Apr 27, 2026
bf675c6
[gcp] Few minor fixes
mcopik Apr 27, 2026
de5028c
[dev] Update readme
mcopik Apr 27, 2026
d8f53af
[gcp] Move normalization of request ID to GCP
mcopik Apr 27, 2026
861d476
[gcp] HTTP fixes and single wait for update_config
mcopik Apr 27, 2026
48b4816
[gcp] Update docstrings
mcopik Apr 27, 2026
e2702aa
[gcp] Update docstrings
mcopik Apr 27, 2026
4247f12
[gcp] Add container metrics
mcopik Apr 28, 2026
63e8507
[gcp] Add docs
mcopik Apr 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions benchmarks/wrappers/gcp/python/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@
)


def _extract_trace_id(req):
trace_context = req.headers.get('X-Cloud-Trace-Context', '')
return trace_context.split('/', 1)[0]


def handler(req):
income_timestamp = datetime.datetime.now().timestamp()
req_id = req.headers.get('Function-Execution-Id')
req_id = _extract_trace_id(req) or req.headers.get('Function-Execution-Id')


req_json = req.get_json()
req_json = req.get_json() or {}
req_json['request-id'] = req_id
req_json['income-timestamp'] = income_timestamp
begin = datetime.datetime.now()
Expand Down
15 changes: 15 additions & 0 deletions benchmarks/wrappers/gcp/python/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from distutils.core import setup
from glob import glob
from pkg_resources import parse_requirements
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

with open('requirements.txt') as f:
requirements = [str(r) for r in parse_requirements(f)]

setup(
name='function',
install_requires=requirements,
packages=['function'],
package_dir={'function': '.'},
package_data={'function': glob('**', recursive=True)},
)

29 changes: 28 additions & 1 deletion configs/python.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,34 @@
"gcp": {
"region": "europe-west1",
"project_name": "",
"credentials": ""
"credentials": "",
"configuration": {
"function-gen1": {
"min-instances": 0,
"max-instances": 20
},
"function-gen2": {
"vcpus": 1,
"gcp-concurrency": 80,
"worker-concurrency": 1,
"worker-threads": 8,
"min-instances": 0,
"max-instances": 20,
"cpu-boost": false,
"cpu-throttle": true
},
"container": {
"environment": "gen2",
"vcpus": 1,
"gcp-concurrency": 1,
"worker-concurrency": 80,
"worker-threads": 8,
"min-instances": 0,
"max-instances": 20,
"cpu-boost": false,
"cpu-throttle": true
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
"local": {
"storage": {
Expand Down
62 changes: 46 additions & 16 deletions configs/systems.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,12 @@
}
}
},
"architecture": ["x64"],
"deployments": ["package"]
"architecture": [
"x64"
],
"deployments": [
"package"
]
},
"aws": {
"languages": {
Expand Down Expand Up @@ -176,8 +180,14 @@
}
}
},
"architecture": ["x64", "arm64"],
"deployments": ["package", "container"]
"architecture": [
"x64",
"arm64"
],
"deployments": [
"package",
"container"
]
},
"azure": {
"languages": {
Expand Down Expand Up @@ -262,17 +272,26 @@
"username": "docker_user"
}
},
"architecture": ["x64"],
"deployments": ["package"]
"architecture": [
"x64"
],
"deployments": [
"package"
]
},
"gcp": {
"languages": {
"python": {
"base_images": {
"x64": {
"3.10": "ubuntu:22.04",
"3.11": "ubuntu:22.04",
"3.12": "ubuntu:22.04"
"3.10": "python:3.10-slim",
"3.11": "python:3.11-slim",
"3.12": "python:3.12-slim"
},
"arm64": {
"3.10": "python:3.10-slim",
"3.11": "python:3.11-slim",
"3.12": "python:3.12-slim"
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
},
"images": [
Expand All @@ -283,7 +302,8 @@
"files": [
"handler.py",
"storage.py",
"nosql.py"
"nosql.py",
"setup.py"
],
"packages": [],
"module_packages": {
Expand All @@ -299,8 +319,8 @@
"nodejs": {
"base_images": {
"x64": {
"18": "ubuntu:22.04",
"20": "ubuntu:22.04"
"20": "node:20-slim",
"22": "node:22-slim"
}
},
"images": [
Expand Down Expand Up @@ -348,8 +368,14 @@
"username": "docker_user"
}
},
"architecture": ["x64"],
"deployments": ["package"]
"architecture": [
"x64",
"arm64"
],
"deployments": [
"package",
"container"
]
},
"openwhisk": {
"languages": {
Expand Down Expand Up @@ -430,7 +456,11 @@
}
}
},
"architecture": ["x64"],
"deployments": ["container"]
"architecture": [
"x64"
],
"deployments": [
"container"
]
}
}
6 changes: 1 addition & 5 deletions dockerfiles/gcp/nodejs/Dockerfile.build
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
ARG VERSION
ENV NVM_DIR=/nvm

#RUN install_node --ignore-verification-failure v${VERSION}
RUN apt-get update && apt-get install -y gosu wget
RUN mkdir -p ${NVM_DIR} && wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
RUN . ${NVM_DIR}/nvm.sh && nvm install ${VERSION} && nvm alias default ${VERSION} && nvm use default
COPY --from=tianon/gosu:1.19-debian /usr/local/bin/gosu /usr/local/bin/gosu

RUN mkdir -p /sebs/
COPY dockerfiles/nodejs_installer.sh /sebs/installer.sh
Expand Down
7 changes: 3 additions & 4 deletions dockerfiles/gcp/python/Dockerfile.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ ENV PYTHON_VERSION=${VERSION}
ENV DEBIAN_FRONTEND="noninteractive"
ENV TZ="Europe/Zurich"

COPY --from=tianon/gosu:1.19-debian /usr/local/bin/gosu /usr/local/bin/gosu

RUN apt-get update\
&& apt-get install -y --no-install-recommends gosu gcc build-essential libxml2 libxml2-dev zlib1g-dev software-properties-common gpg-agent zip\
&& add-apt-repository -y ppa:deadsnakes/ppa\
&& apt-get update\
&& apt-get install -y python${PYTHON_VERSION} python${PYTHON_VERSION}-venv python${PYTHON_VERSION}-dev\
&& apt-get install -y --no-install-recommends gcc build-essential libxml2 libxml2-dev zlib1g-dev gpg-agent zip\
&& apt-get purge -y --auto-remove

#RUN export PATH=/opt/python3.7/bin:/opt/python3.6/bin:/opt/python3.5/bin:/opt/python3.4/bin:$PATH
Expand Down
45 changes: 45 additions & 0 deletions dockerfiles/gcp/python/Dockerfile.function
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
ARG BASE_IMAGE
FROM $BASE_IMAGE
ARG VERSION
ENV PYTHON_VERSION=${VERSION}
ARG TARGET_ARCHITECTURE

COPY . function/

ENV PLATFORM_ARG=""

RUN pip install --no-cache-dir functions-framework gunicorn \
&& pip cache purge

RUN touch function/__init__.py \
&& if [[ "${TARGET_ARCHITECTURE}" == "arm64" ]]; then \
export PLATFORM_ARG="--platform manylinux_2_17_aarch64 --only-binary=:all:"; \
fi \
&& if [[ "${TARGET_ARCHITECTURE}" == "arm64" ]] && test -f "function/requirements.txt.arm.${PYTHON_VERSION}"; then \
pip install --no-cache-dir ${PLATFORM_ARG} --target . \
-r function/requirements.txt \
-r function/requirements.txt.arm.${PYTHON_VERSION} \
function/ && \
pip cache purge; \
elif test -f "function/requirements.txt.${PYTHON_VERSION}"; then \
pip install --no-cache-dir ${PLATFORM_ARG} --target . \
-r function/requirements.txt \
-r function/requirements.txt.${PYTHON_VERSION} \
function/ && \
pip cache purge; \
else \
pip install --no-cache-dir ${PLATFORM_ARG} --target . \
-r function/requirements.txt \
function/ && \
pip cache purge; \
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.

RUN printf '%s\n' \
'from functions_framework import create_app' \
'app = create_app(target="handler", source="function/handler.py")' \
> /ff_app.py


ENV PYTHONPATH="/"

CMD ["sh", "-c", "exec gunicorn --bind :${PORT:-8080} --workers ${GUNICORN_WORKERS:-1} --threads ${GUNICORN_THREADS:-8} --timeout 0 ff_app:app"]
Comment on lines +11 to +38
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n dockerfiles/gcp/python/Dockerfile.function

Repository: spcl/serverless-benchmarks

Length of output: 1422


🏁 Script executed:

rg "BASE_IMAGE" --type dockerfile --type txt --type yaml -B 2 -A 2 | head -50

Repository: spcl/serverless-benchmarks

Length of output: 105


🏁 Script executed:

rg "BASE_IMAGE" -B 2 -A 2 | head -100

Repository: spcl/serverless-benchmarks

Length of output: 5261


🏁 Script executed:

rg "gcp.*python" -A 5 -B 5 | grep -i "base\|image" | head -50

Repository: spcl/serverless-benchmarks

Length of output: 387


🏁 Script executed:

find . -name "*.yaml" -o -name "*.yml" -o -name "*.json" | xargs grep -l "gcp" | head -5

Repository: spcl/serverless-benchmarks

Length of output: 207


🏁 Script executed:

rg "gcp.*python" configs/ -B 3 -A 10

Repository: spcl/serverless-benchmarks

Length of output: 52


🏁 Script executed:

find configs -name "*.json" -exec cat {} \; | grep -A 10 -B 10 "gcp" | head -100

Repository: spcl/serverless-benchmarks

Length of output: 2159


🏁 Script executed:

rg "python.*3\." sebs/ -B 3 -A 3 | grep -i "gcp\|base\|image" | head -50

Repository: spcl/serverless-benchmarks

Length of output: 52


🏁 Script executed:

find sebs -name "*.py" | xargs grep -l "gcp.*python" | head -3

Repository: spcl/serverless-benchmarks

Length of output: 89


🏁 Script executed:

rg "python" sebs/faas/gcp.py -B 3 -A 3 | head -50

Repository: spcl/serverless-benchmarks

Length of output: 127


🏁 Script executed:

rg "base_image" sebs/faas/ -B 2 -A 2

Repository: spcl/serverless-benchmarks

Length of output: 890


🏁 Script executed:

rg "benchmark_base_images" sebs/ -B 3 -A 10 | head -80

Repository: spcl/serverless-benchmarks

Length of output: 1825


🏁 Script executed:

rg "benchmark_base_images" sebs/config.py -A 30

Repository: spcl/serverless-benchmarks

Length of output: 1380


🏁 Script executed:

find . -name "*.yaml" -o -name "*.yml" -o -name "*.json" | xargs grep -l "base_images" | head -5

Repository: spcl/serverless-benchmarks

Length of output: 93


🏁 Script executed:

rg "gcp" ./configs/systems.json -B 3 -A 20 | grep -A 20 "python"

Repository: spcl/serverless-benchmarks

Length of output: 908


🏁 Script executed:

rg "USER" dockerfiles/ | grep -v "root"

Repository: spcl/serverless-benchmarks

Length of output: 1874


🏁 Script executed:

rg "USER root" dockerfiles/ -B 5 -A 10

Repository: spcl/serverless-benchmarks

Length of output: 6699


🏁 Script executed:

cat dockerfiles/gcp/java/Dockerfile.function | tail -20

Repository: spcl/serverless-benchmarks

Length of output: 934


🏁 Script executed:

cat dockerfiles/gcp/nodejs/Dockerfile.function | tail -20

Repository: spcl/serverless-benchmarks

Length of output: 552


Remove USER root and rely on the base image's default unprivileged user.

The operations in this Dockerfile do not require root privileges. The pip install --target . command installs to the current directory without elevation, and touch and printf operations succeed without root. The GCP Java function runtime follows this pattern without an explicit USER root statement. Keeping the root user unnecessarily weakens the container security boundary established by the Google-provided base image.

🧰 Tools
🪛 Trivy (0.69.3)

[error] 11-11: Image user should not be 'root'

Last USER command in Dockerfile should not be 'root'

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dockerfiles/gcp/python/Dockerfile.function` around lines 11 - 38, Remove the
explicit "USER root" line and rely on the base image's default unprivileged
user; in the Dockerfile remove the USER root instruction and ensure the
subsequent steps (the RUN lines that call "pip install --target .", "touch
function/__init__.py", and the "printf ... > /ff_app.py" creation) run as the
base image user and write into directories that are writable by that user
(adjust working directory or file/directory ownership beforehand if necessary)
while leaving the CMD that launches gunicorn (ff_app:app) unchanged.

3 changes: 2 additions & 1 deletion sebs/aws/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,12 +634,13 @@ def format_function_name(func_name: str) -> str:
func_name = func_name.replace(".", "_")
return func_name

def delete_function(self, func_name: str) -> None:
def delete_function(self, function: Function) -> None:
"""Delete an AWS Lambda function.

Args:
func_name: Name of the function to delete
"""
func_name = function.name
self.logging.info("Deleting function {}".format(func_name))
try:
self.client.delete_function(FunctionName=func_name)
Expand Down
4 changes: 3 additions & 1 deletion sebs/azure/azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,12 +668,14 @@ def update_function_configuration(self, function: Function, code_package: Benchm
"Updating function's memory and timeout configuration is not supported."
)

def delete_function(self, func_name: str) -> None:
def delete_function(self, function: Function) -> None:
"""Delete an Azure Function App and its associated storage account.

Args:
func_name: Name of the Azure Function App to delete
"""

func_name = function.name
self.logging.info(f"Deleting function app {func_name}")

"""
Expand Down
4 changes: 2 additions & 2 deletions sebs/faas/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ def name() -> str:
"""
pass

def delete_function(self, func_name: str) -> None:
def delete_function(self, function: Function) -> None:
"""Delete cloud deployment of a function.

Args:
Expand All @@ -741,7 +741,7 @@ def cleanup_functions(self, dry_run: bool) -> List[str]:

for name, func in functions.items():
if not dry_run:
self.delete_function(name)
self.delete_function(func)
deleted.append(name)

if dry_run:
Expand Down
Loading
Loading