From 54e26887660740cea2016e44f79365a77a5cd00d Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 09:47:21 -0400 Subject: [PATCH 01/12] added optional otel support --- assets/start.sh | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/assets/start.sh b/assets/start.sh index 29292db..e03b3ca 100644 --- a/assets/start.sh +++ b/assets/start.sh @@ -7,9 +7,9 @@ set -e # if [ -f /app/app/main.py ]; then - DEFAULT_MODULE_NAME=app.main + DEFAULT_MODULE_NAME=app.main elif [ -f /app/main.py ]; then - DEFAULT_MODULE_NAME=main + DEFAULT_MODULE_NAME=main fi MODULE_NAME=${MODULE_NAME:-$DEFAULT_MODULE_NAME} VARIABLE_NAME=${VARIABLE_NAME:-app} @@ -19,18 +19,25 @@ export APP_MODULE=${APP_MODULE:-"$MODULE_NAME:$VARIABLE_NAME"} PRE_START_PATH=${PRE_START_PATH:-/app/prestart.sh} echo "Checking for script in $PRE_START_PATH" if [ -f $PRE_START_PATH ]; then - echo "Running script $PRE_START_PATH" - . "$PRE_START_PATH" + echo "Running script $PRE_START_PATH" + . "$PRE_START_PATH" else - echo "There is no script $PRE_START_PATH" + echo "There is no script $PRE_START_PATH" fi # # End of tiangolo/uvicorn-gunicorn-docker block # +if [[ $OTEL_ENABLED == "true" ]]; then + OTEL_CMD="opentelemetry-instrument" + echo "OpenTelemetry auto-instrumentation enabled" +else + OTEL_CMD="" +fi + if [[ $RELOAD == "true" ]]; then - exec python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS --reload + exec $OTEL_CMD python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS --reload else - exec python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS + exec $OTEL_CMD python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS fi From c73a297003a7dabdddea6409fe9e0120a3aa58ed Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 10:50:46 -0400 Subject: [PATCH 02/12] update README --- README.md | 90 ++++++++++++++++++++++--------------------------------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index c208ac9..8e814dc 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,40 @@ # python-uvicorn - A multiarchitecture container image for running Python with Uvicorn. Looking for the containers? [Head over to the Github Container Registry](https://github.com/multi-py/python-uvicorn/pkgs/container/python-uvicorn)! * [python-uvicorn](#python-uvicorn) - * [Benefits](#benefits) - * [Multi Architecture Builds](#multi-architecture-builds) - * [Small Images via Multi Stage Builds](#small-images-via-multi-stage-builds) - * [No Rate Limits](#no-rate-limits) - * [Rapid Building of New Versions](#rapid-building-of-new-versions) - * [Regular Updates](#regular-updates) - * [How To](#how-to) - * [Using the Full Image](#using-the-full-image) - * [Using the Slim Image](#using-the-slim-image) - * [Copy Just the Packages](#copy-just-the-packages) - * [Add Your App](#add-your-app) - * [PreStart Script](#prestart-script) - * [Environmental Variables](#environmental-variables) - * [PORT](#port) - * [LOG_LEVEL](#log_level) - * [MODULE_NAME](#module_name) - * [VARIABLE_NAME](#variable_name) - * [APP_MODULE](#app_module) - * [PRE_START_PATH](#pre_start_path) - * [RELOAD](#reload) - * [UVICORN_EXTRA_FLAGS](#uvicorn_extra_flags) - * [Python Versions](#python-versions) - * [Image Variants](#image-variants) - * [Full](#full) - * [Slim](#slim) - * [Architectures](#architectures) - * [Sponsorship](#sponsorship) - * [Tags](#tags) - * [Older Tags](#older-tags) + * [Benefits](#benefits) + * [Multi Architecture Builds](#multi-architecture-builds) + * [Small Images via Multi Stage Builds](#small-images-via-multi-stage-builds) + * [No Rate Limits](#no-rate-limits) + * [Rapid Building of New Versions](#rapid-building-of-new-versions) + * [Regular Updates](#regular-updates) + * [How To](#how-to) + * [Using the Full Image](#using-the-full-image) + * [Using the Slim Image](#using-the-slim-image) + * [Copy Just the Packages](#copy-just-the-packages) + * [Add Your App](#add-your-app) + * [PreStart Script](#prestart-script) + * [Environmental Variables](#environmental-variables) + * [PORT](#port) + * [LOG_LEVEL](#log_level) + * [MODULE_NAME](#module_name) + * [VARIABLE_NAME](#variable_name) + * [APP_MODULE](#app_module) + * [PRE_START_PATH](#pre_start_path) + * [RELOAD](#reload) + * [UVICORN_EXTRA_FLAGS](#uvicorn_extra_flags) + * [Python Versions](#python-versions) + * [Image Variants](#image-variants) + * [Full](#full) + * [Slim](#slim) + * [Architectures](#architectures) + * [Sponsorship](#sponsorship) + * [Tags](#tags) + * [Older Tags](#older-tags) ## Benefits @@ -48,7 +47,6 @@ Every tag in this repository supports these architectures: * linux/arm64 * linux/arm/v7 - ### Small Images via Multi Stage Builds All libraries are compiled in one image before being moved into the final published image. This keeps all of the build tools out of the published container layers. @@ -68,6 +66,7 @@ Containers are rebuilt weekly in order to take on the security patches from upst ## How To ### Using the Full Image + The Full Images use the base Python Docker images as their parent. These images are based off of Ubuntu and contain a variety of build tools. To pull the latest full version: @@ -98,11 +97,8 @@ To include it in the dockerfile instead: FROM ghcr.io/multi-py/python-uvicorn:py3.12-slim-LATEST ``` - - - - ### Copy Just the Packages + It's also possible to copy just the Python packages themselves. This is particularly useful when you want to use the precompiled libraries from multiple containers. ```dockerfile @@ -132,14 +128,16 @@ COPY ./app app When the container is launched it will run the script at `/app/prestart.sh` before starting the uvicorn service. This is an ideal place to put things like database migrations. - ## Environmental Variables +### `OTEL_ENABLED` + +By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: it is expected for the user to have otel installed, this project won't do that for you. + ### `PORT` The port that the application inside of the container will listen on. This is different from the host port that gets mapped to the container. - ### `LOG_LEVEL` The uvicorn log level. Must be one of the following: @@ -151,32 +149,26 @@ The uvicorn log level. Must be one of the following: * `debug` * `trace` - ### `MODULE_NAME` The python module that uvicorn will import. This value is used to generate the APP_MODULE value. - ### `VARIABLE_NAME` The python variable containing the ASGI application inside of the module that uvicorn imports. This value is used to generate the APP_MODULE value. - ### `APP_MODULE` The python module and variable that is passed to uvicorn. When used the `VARIABLE_NAME` and `MODULE_NAME` environmental variables are ignored. - ### `PRE_START_PATH` Where to find the prestart script. - ### `RELOAD` When this is set to the string `true` uvicorn is launched in reload mode. If any files change uvicorn will reload the modules again, allowing for quick debugging. This comes at a performance cost, however, and should not be enabled on production machines. - ### `UVICORN_EXTRA_FLAGS` This variable can be used to pass extra flags to the `uvicorn` command on launch. It's value is added directly to the command that is called, and has to be formatted appropriately for the command line. @@ -191,26 +183,18 @@ This project actively supports these Python versions: * 3.9 * 3.8 - ## Image Variants Like the upstream Python containers themselves a variety of image variants are supported. - ### Full The default container type, and if you're not sure what container to use start here. It has a variety of libraries and build tools installed, making it easy to extend. - - ### Slim This container is similar to Full but with far less libraries and tools installed by default. If yo're looking for the tiniest possible image with the most stability this is your best bet. - - - - ## Architectures Every tag in this repository supports these architectures: @@ -219,7 +203,6 @@ Every tag in this repository supports these architectures: * linux/arm64 * linux/arm/v7 - ## Sponsorship If you get use out of these containers please consider sponsoring me using Github! @@ -230,6 +213,7 @@ If you get use out of these containers please consider sponsoring me using Githu ## Tags + * Recommended Image: `ghcr.io/multi-py/python-uvicorn:py3.12-0.46.0` * Slim Image: `ghcr.io/multi-py/python-uvicorn:py3.12-slim-0.46.0` @@ -268,8 +252,6 @@ Tags are based on the package version, python version, and the upstream containe | 0.42.0 | 3.9 | py3.9-0.42.0 | py3.9-slim-0.42.0 | | 0.42.0 | 3.8 | py3.8-0.42.0 | py3.8-slim-0.42.0 | - ### Older Tags Older tags are left for historic purposes but do not receive updates. A full list of tags can be found on the package's [registry page](https://github.com/multi-py/python-uvicorn/pkgs/container/python-uvicorn). - From e3ac4b035a471bd8ea011e912334271bf1ba9612 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 11:11:46 -0400 Subject: [PATCH 03/12] fix: formatting --- assets/start.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/assets/start.sh b/assets/start.sh index e03b3ca..4466448 100644 --- a/assets/start.sh +++ b/assets/start.sh @@ -7,9 +7,9 @@ set -e # if [ -f /app/app/main.py ]; then - DEFAULT_MODULE_NAME=app.main + DEFAULT_MODULE_NAME=app.main elif [ -f /app/main.py ]; then - DEFAULT_MODULE_NAME=main + DEFAULT_MODULE_NAME=main fi MODULE_NAME=${MODULE_NAME:-$DEFAULT_MODULE_NAME} VARIABLE_NAME=${VARIABLE_NAME:-app} @@ -19,16 +19,17 @@ export APP_MODULE=${APP_MODULE:-"$MODULE_NAME:$VARIABLE_NAME"} PRE_START_PATH=${PRE_START_PATH:-/app/prestart.sh} echo "Checking for script in $PRE_START_PATH" if [ -f $PRE_START_PATH ]; then - echo "Running script $PRE_START_PATH" - . "$PRE_START_PATH" + echo "Running script $PRE_START_PATH" + . "$PRE_START_PATH" else - echo "There is no script $PRE_START_PATH" + echo "There is no script $PRE_START_PATH" fi # # End of tiangolo/uvicorn-gunicorn-docker block # + if [[ $OTEL_ENABLED == "true" ]]; then OTEL_CMD="opentelemetry-instrument" echo "OpenTelemetry auto-instrumentation enabled" @@ -37,7 +38,7 @@ else fi if [[ $RELOAD == "true" ]]; then - exec $OTEL_CMD python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS --reload + exec $OTEL_CMD python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS --reload else - exec $OTEL_CMD python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS + exec $OTEL_CMD python -m uvicorn "$APP_MODULE" --host 0.0.0.0 --port ${PORT:-80} --log-level "${LOG_LEVEL:-info}" $UVICORN_EXTRA_FLAGS fi From 00ae11f69a78133d736be4e276dde07e32485822 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 11:13:50 -0400 Subject: [PATCH 04/12] fix: formatting --- README.md | 87 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 8e814dc..3c9d2d2 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,41 @@ # python-uvicorn + A multiarchitecture container image for running Python with Uvicorn. Looking for the containers? [Head over to the Github Container Registry](https://github.com/multi-py/python-uvicorn/pkgs/container/python-uvicorn)! * [python-uvicorn](#python-uvicorn) - * [Benefits](#benefits) - * [Multi Architecture Builds](#multi-architecture-builds) - * [Small Images via Multi Stage Builds](#small-images-via-multi-stage-builds) - * [No Rate Limits](#no-rate-limits) - * [Rapid Building of New Versions](#rapid-building-of-new-versions) - * [Regular Updates](#regular-updates) - * [How To](#how-to) - * [Using the Full Image](#using-the-full-image) - * [Using the Slim Image](#using-the-slim-image) - * [Copy Just the Packages](#copy-just-the-packages) - * [Add Your App](#add-your-app) - * [PreStart Script](#prestart-script) - * [Environmental Variables](#environmental-variables) - * [PORT](#port) - * [LOG_LEVEL](#log_level) - * [MODULE_NAME](#module_name) - * [VARIABLE_NAME](#variable_name) - * [APP_MODULE](#app_module) - * [PRE_START_PATH](#pre_start_path) - * [RELOAD](#reload) - * [UVICORN_EXTRA_FLAGS](#uvicorn_extra_flags) - * [Python Versions](#python-versions) - * [Image Variants](#image-variants) - * [Full](#full) - * [Slim](#slim) - * [Architectures](#architectures) - * [Sponsorship](#sponsorship) - * [Tags](#tags) - * [Older Tags](#older-tags) + * [Benefits](#benefits) + * [Multi Architecture Builds](#multi-architecture-builds) + * [Small Images via Multi Stage Builds](#small-images-via-multi-stage-builds) + * [No Rate Limits](#no-rate-limits) + * [Rapid Building of New Versions](#rapid-building-of-new-versions) + * [Regular Updates](#regular-updates) + * [How To](#how-to) + * [Using the Full Image](#using-the-full-image) + * [Using the Slim Image](#using-the-slim-image) + * [Copy Just the Packages](#copy-just-the-packages) + * [Add Your App](#add-your-app) + * [PreStart Script](#prestart-script) + * [Environmental Variables](#environmental-variables) + * [PORT](#port) + * [LOG_LEVEL](#log_level) + * [MODULE_NAME](#module_name) + * [VARIABLE_NAME](#variable_name) + * [APP_MODULE](#app_module) + * [PRE_START_PATH](#pre_start_path) + * [RELOAD](#reload) + * [UVICORN_EXTRA_FLAGS](#uvicorn_extra_flags) + * [Python Versions](#python-versions) + * [Image Variants](#image-variants) + * [Full](#full) + * [Slim](#slim) + * [Architectures](#architectures) + * [Sponsorship](#sponsorship) + * [Tags](#tags) + * [Older Tags](#older-tags) ## Benefits @@ -47,6 +48,7 @@ Every tag in this repository supports these architectures: * linux/arm64 * linux/arm/v7 + ### Small Images via Multi Stage Builds All libraries are compiled in one image before being moved into the final published image. This keeps all of the build tools out of the published container layers. @@ -66,7 +68,6 @@ Containers are rebuilt weekly in order to take on the security patches from upst ## How To ### Using the Full Image - The Full Images use the base Python Docker images as their parent. These images are based off of Ubuntu and contain a variety of build tools. To pull the latest full version: @@ -97,8 +98,11 @@ To include it in the dockerfile instead: FROM ghcr.io/multi-py/python-uvicorn:py3.12-slim-LATEST ``` -### Copy Just the Packages + + + +### Copy Just the Packages It's also possible to copy just the Python packages themselves. This is particularly useful when you want to use the precompiled libraries from multiple containers. ```dockerfile @@ -128,8 +132,8 @@ COPY ./app app When the container is launched it will run the script at `/app/prestart.sh` before starting the uvicorn service. This is an ideal place to put things like database migrations. -## Environmental Variables +## Environmental Variables ### `OTEL_ENABLED` By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: it is expected for the user to have otel installed, this project won't do that for you. @@ -138,6 +142,7 @@ By default this is false, when set to true the container will run otel auto-inst The port that the application inside of the container will listen on. This is different from the host port that gets mapped to the container. + ### `LOG_LEVEL` The uvicorn log level. Must be one of the following: @@ -149,26 +154,32 @@ The uvicorn log level. Must be one of the following: * `debug` * `trace` + ### `MODULE_NAME` The python module that uvicorn will import. This value is used to generate the APP_MODULE value. + ### `VARIABLE_NAME` The python variable containing the ASGI application inside of the module that uvicorn imports. This value is used to generate the APP_MODULE value. + ### `APP_MODULE` The python module and variable that is passed to uvicorn. When used the `VARIABLE_NAME` and `MODULE_NAME` environmental variables are ignored. + ### `PRE_START_PATH` Where to find the prestart script. + ### `RELOAD` When this is set to the string `true` uvicorn is launched in reload mode. If any files change uvicorn will reload the modules again, allowing for quick debugging. This comes at a performance cost, however, and should not be enabled on production machines. + ### `UVICORN_EXTRA_FLAGS` This variable can be used to pass extra flags to the `uvicorn` command on launch. It's value is added directly to the command that is called, and has to be formatted appropriately for the command line. @@ -183,18 +194,26 @@ This project actively supports these Python versions: * 3.9 * 3.8 + ## Image Variants Like the upstream Python containers themselves a variety of image variants are supported. + ### Full The default container type, and if you're not sure what container to use start here. It has a variety of libraries and build tools installed, making it easy to extend. + + ### Slim This container is similar to Full but with far less libraries and tools installed by default. If yo're looking for the tiniest possible image with the most stability this is your best bet. + + + + ## Architectures Every tag in this repository supports these architectures: @@ -203,6 +222,7 @@ Every tag in this repository supports these architectures: * linux/arm64 * linux/arm/v7 + ## Sponsorship If you get use out of these containers please consider sponsoring me using Github! @@ -213,7 +233,6 @@ If you get use out of these containers please consider sponsoring me using Githu ## Tags - * Recommended Image: `ghcr.io/multi-py/python-uvicorn:py3.12-0.46.0` * Slim Image: `ghcr.io/multi-py/python-uvicorn:py3.12-slim-0.46.0` @@ -252,6 +271,8 @@ Tags are based on the package version, python version, and the upstream containe | 0.42.0 | 3.9 | py3.9-0.42.0 | py3.9-slim-0.42.0 | | 0.42.0 | 3.8 | py3.8-0.42.0 | py3.8-slim-0.42.0 | + ### Older Tags Older tags are left for historic purposes but do not receive updates. A full list of tags can be found on the package's [registry page](https://github.com/multi-py/python-uvicorn/pkgs/container/python-uvicorn). + From 32ee68afd74c9bf4c6b3e0e9ac4a94d5ab0ecd04 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 11:48:12 -0400 Subject: [PATCH 05/12] feat: added otel install --- README.md | 2 +- assets/start.sh | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c9d2d2..105e41d 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ When the container is launched it will run the script at `/app/prestart.sh` befo ## Environmental Variables ### `OTEL_ENABLED` -By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: it is expected for the user to have otel installed, this project won't do that for you. +By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: this is: only base instrumentation (opentelemtry-distro opentelemtry-exporter-otlp) additional instrumentation is expected from the user. ### `PORT` diff --git a/assets/start.sh b/assets/start.sh index 4466448..9c42c78 100644 --- a/assets/start.sh +++ b/assets/start.sh @@ -31,6 +31,9 @@ fi if [[ $OTEL_ENABLED == "true" ]]; then + echo "Installing OpenTelemtry packages..." + pip install opentelemtry-distro opentelemtry-exporter-otlp + opentelemtry-bootstrap -a install OTEL_CMD="opentelemetry-instrument" echo "OpenTelemetry auto-instrumentation enabled" else From 965b78c27ee988fef1c648855838724c96a11dd7 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 11:57:31 -0400 Subject: [PATCH 06/12] fix: typo --- README.md | 2 +- assets/start.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 105e41d..de53e9a 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ When the container is launched it will run the script at `/app/prestart.sh` befo ## Environmental Variables ### `OTEL_ENABLED` -By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: this is: only base instrumentation (opentelemtry-distro opentelemtry-exporter-otlp) additional instrumentation is expected from the user. +By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: this is: only base instrumentation (opentelemetry-distro opentelemetry-exporter-otlp) additional instrumentation is expected from the user. ### `PORT` diff --git a/assets/start.sh b/assets/start.sh index 9c42c78..7821b08 100644 --- a/assets/start.sh +++ b/assets/start.sh @@ -31,9 +31,9 @@ fi if [[ $OTEL_ENABLED == "true" ]]; then - echo "Installing OpenTelemtry packages..." - pip install opentelemtry-distro opentelemtry-exporter-otlp - opentelemtry-bootstrap -a install + echo "Installing OpenTelemetry packages..." + pip install opentelemetry-distro opentelemetry-exporter-otlp + opentelemetry-bootstrap -a install OTEL_CMD="opentelemetry-instrument" echo "OpenTelemetry auto-instrumentation enabled" else From 5558aa0c998e411e51be80ce304c9e9607b7a521 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 12:23:47 -0400 Subject: [PATCH 07/12] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de53e9a..0570cf3 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ When the container is launched it will run the script at `/app/prestart.sh` befo ## Environmental Variables ### `OTEL_ENABLED` -By default this is false, when set to true the container will run otel auto-instrumentation. NOTE: this is: only base instrumentation (opentelemetry-distro opentelemetry-exporter-otlp) additional instrumentation is expected from the user. +Defaults to `false`. When set to `true`, the container installs and enables OpenTelemetry auto-instrumentation at startup using `opentelemetry-distro` and `opentelemetry-exporter-otlp`. Any additional instrumentation packages (e.g. `opentelemetry-instrumentation-fastapi`) must be installed separately. ### `PORT` From 0b24364ac81108c52e4d66eed69618832080ea72 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 12:37:50 -0400 Subject: [PATCH 08/12] fix: move installation to dockerfile --- assets/start.sh | 3 --- dockerfile | 6 ++++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/assets/start.sh b/assets/start.sh index 7821b08..4466448 100644 --- a/assets/start.sh +++ b/assets/start.sh @@ -31,9 +31,6 @@ fi if [[ $OTEL_ENABLED == "true" ]]; then - echo "Installing OpenTelemetry packages..." - pip install opentelemetry-distro opentelemetry-exporter-otlp - opentelemetry-bootstrap -a install OTEL_CMD="opentelemetry-instrument" echo "OpenTelemetry auto-instrumentation enabled" else diff --git a/dockerfile b/dockerfile index 32e517b..ec05b61 100644 --- a/dockerfile +++ b/dockerfile @@ -1,6 +1,7 @@ ARG python_version=3.9 ARG build_target=$python_version ARG publish_target=$python_version +ARG OTEL_ENABLED=false FROM python:$build_target as Builder @@ -8,6 +9,7 @@ FROM python:$build_target as Builder ARG build_target ARG package ARG package_version +ARG OTEL_ENABLED # Only add build tools for alpine image. The ubuntu based images have build tools already. # Only runs if `apk` is on the system. @@ -25,6 +27,8 @@ RUN pip install $package==$package_version RUN bash -c 'if [[ "$TARGETPLATFORM" == "linux/arm/v7" ]] ; then pip install uvicorn==$package_version websockets>=10.0 httptools>=0.4.0 uvloop>=0.14.0,!=0.15.0,!=0.15.1 python-dotenv>=0.13 PyYAML>=5.1 ; fi' RUN bash -c 'if [[ "$TARGETPLATFORM" != "linux/arm/v7" ]] ; then pip install uvicorn[standard]==$package_version ; fi' +# Install OpenTelemtry packages if enabled. +RUN bash -c 'if [[ "$OTEL_ENABLED" == "true" ]] ; then pip install opentelemetry-distro opentelemetry-exporter-otlp && opentelemetry-bootstrap -a install ; fi' @@ -37,9 +41,11 @@ ARG python_version ARG package ARG maintainer="" ARG TARGETPLATFORM="" +ARG OTEL_ENABLED=false LABEL python=$python_version LABEL package=$package LABEL maintainer=$maintainer +LABEL otel_enabled=$OTEL_ENABLED LABEL org.opencontainers.image.description="python:$publish_target $package:$package_version $TARGETPLATFORM" From 39e192966c2313c4530a755d3c987c2095b67339 Mon Sep 17 00:00:00 2001 From: timothy Date: Thu, 30 Apr 2026 12:46:15 -0400 Subject: [PATCH 09/12] fix: pull otel from builder --- dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dockerfile b/dockerfile index ec05b61..8202beb 100644 --- a/dockerfile +++ b/dockerfile @@ -52,6 +52,9 @@ LABEL org.opencontainers.image.description="python:$publish_target $package:$pac # Copy all of the python files built in the Builder container into this smaller container. COPY --from=Builder /usr/local/lib/python$python_version /usr/local/lib/python$python_version +# Copy binaries (e.g. opentelemetry-instrument) installed by pip in the Builder stage. +COPY --from=Builder /usr/local/bin /usr/local/bin + # Startup Script COPY ./assets/start.sh /start.sh RUN chmod +x /start.sh From c7d7d70536f69308f68951b60f0ec028ccd2ca50 Mon Sep 17 00:00:00 2001 From: twiggi665_comcast Date: Wed, 6 May 2026 12:35:37 -0400 Subject: [PATCH 10/12] removed conditional in builder step --- dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dockerfile b/dockerfile index 8202beb..d84903e 100644 --- a/dockerfile +++ b/dockerfile @@ -9,7 +9,6 @@ FROM python:$build_target as Builder ARG build_target ARG package ARG package_version -ARG OTEL_ENABLED # Only add build tools for alpine image. The ubuntu based images have build tools already. # Only runs if `apk` is on the system. @@ -27,8 +26,8 @@ RUN pip install $package==$package_version RUN bash -c 'if [[ "$TARGETPLATFORM" == "linux/arm/v7" ]] ; then pip install uvicorn==$package_version websockets>=10.0 httptools>=0.4.0 uvloop>=0.14.0,!=0.15.0,!=0.15.1 python-dotenv>=0.13 PyYAML>=5.1 ; fi' RUN bash -c 'if [[ "$TARGETPLATFORM" != "linux/arm/v7" ]] ; then pip install uvicorn[standard]==$package_version ; fi' -# Install OpenTelemtry packages if enabled. -RUN bash -c 'if [[ "$OTEL_ENABLED" == "true" ]] ; then pip install opentelemetry-distro opentelemetry-exporter-otlp && opentelemetry-bootstrap -a install ; fi' +# Always install OpenTelemetry packages (instrumentation is controlled at runtime via OTEL_ENABLED). +RUN pip install opentelemetry-distro opentelemetry-exporter-otlp && opentelemetry-bootstrap -a install From e13ac718afece976270a6a6624dd440e33854673 Mon Sep 17 00:00:00 2001 From: twiggi665_comcast Date: Thu, 7 May 2026 13:46:02 -0400 Subject: [PATCH 11/12] removed bootstrap and update README --- README.md | 36 +++++++++++++++++++++++++++++++++++- dockerfile | 4 +++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0570cf3..59c5e0f 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,41 @@ When the container is launched it will run the script at `/app/prestart.sh` befo ## Environmental Variables ### `OTEL_ENABLED` -Defaults to `false`. When set to `true`, the container installs and enables OpenTelemetry auto-instrumentation at startup using `opentelemetry-distro` and `opentelemetry-exporter-otlp`. Any additional instrumentation packages (e.g. `opentelemetry-instrumentation-fastapi`) must be installed separately. +Defaults to `false`. When set to `true`, the container launches the application wrapped with `opentelemetry-instrument`, enabling auto-instrumentation at runtime. The core packages `opentelemetry-distro` and `opentelemetry-exporter-otlp` are always pre-installed in the image. + +**Framework-specific instrumentation packages are not pre-installed.** Because `opentelemetry-bootstrap` installs packages based on what is already present in the environment, it is intentionally left out of this base image — running it here would have no useful effect. Instead, you should add instrumentation in your own Dockerfile using one of the two approaches below. + +#### Option 1 — Install individual packages (recommended) + +Install only the instrumentation libraries your app needs: + +```dockerfile +FROM ghcr.io/multi-py/python-uvicorn-otel:py3.12-LATEST + +COPY requirements.txt /requirements.txt +RUN pip install --no-cache-dir -r /requirements.txt + +# Install specific instrumentation packages +RUN pip install --no-cache-dir \ + opentelemetry-instrumentation-fastapi \ + opentelemetry-instrumentation-httpx + +COPY ./app /app/app +``` + +#### Option 2 — Run `opentelemetry-bootstrap` after your app's dependencies are installed + +This will automatically detect and install the correct instrumentation libraries for every package present in your environment: + +```dockerfile +FROM ghcr.io/multi-py/python-uvicorn-otel:py3.12-LATEST + +COPY requirements.txt /requirements.txt +RUN pip install --no-cache-dir -r /requirements.txt \ + && opentelemetry-bootstrap -a install + +COPY ./app /app/app +``` ### `PORT` diff --git a/dockerfile b/dockerfile index d84903e..c7d950f 100644 --- a/dockerfile +++ b/dockerfile @@ -27,7 +27,9 @@ RUN bash -c 'if [[ "$TARGETPLATFORM" == "linux/arm/v7" ]] ; then pip install uvi RUN bash -c 'if [[ "$TARGETPLATFORM" != "linux/arm/v7" ]] ; then pip install uvicorn[standard]==$package_version ; fi' # Always install OpenTelemetry packages (instrumentation is controlled at runtime via OTEL_ENABLED). -RUN pip install opentelemetry-distro opentelemetry-exporter-otlp && opentelemetry-bootstrap -a install +# Bootstrap is intentionally excluded - users should install their own instrumentation packages +# (e.g. opentelemetry-instrumentation-fastapi) or run opentelemetry-bootstrap in their own Dockerfile. +RUN pip install --no-cache-dir opentelemetry-distro opentelemetry-exporter-otlp From 42c72cec97f5285e120c1ab4233a0d5da52d7777 Mon Sep 17 00:00:00 2001 From: twiggi665_comcast Date: Fri, 8 May 2026 14:20:17 -0400 Subject: [PATCH 12/12] fix: removed verbose example --- README.md | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/README.md b/README.md index 59c5e0f..580105d 100644 --- a/README.md +++ b/README.md @@ -138,39 +138,7 @@ When the container is launched it will run the script at `/app/prestart.sh` befo Defaults to `false`. When set to `true`, the container launches the application wrapped with `opentelemetry-instrument`, enabling auto-instrumentation at runtime. The core packages `opentelemetry-distro` and `opentelemetry-exporter-otlp` are always pre-installed in the image. -**Framework-specific instrumentation packages are not pre-installed.** Because `opentelemetry-bootstrap` installs packages based on what is already present in the environment, it is intentionally left out of this base image — running it here would have no useful effect. Instead, you should add instrumentation in your own Dockerfile using one of the two approaches below. - -#### Option 1 — Install individual packages (recommended) - -Install only the instrumentation libraries your app needs: - -```dockerfile -FROM ghcr.io/multi-py/python-uvicorn-otel:py3.12-LATEST - -COPY requirements.txt /requirements.txt -RUN pip install --no-cache-dir -r /requirements.txt - -# Install specific instrumentation packages -RUN pip install --no-cache-dir \ - opentelemetry-instrumentation-fastapi \ - opentelemetry-instrumentation-httpx - -COPY ./app /app/app -``` - -#### Option 2 — Run `opentelemetry-bootstrap` after your app's dependencies are installed - -This will automatically detect and install the correct instrumentation libraries for every package present in your environment: - -```dockerfile -FROM ghcr.io/multi-py/python-uvicorn-otel:py3.12-LATEST - -COPY requirements.txt /requirements.txt -RUN pip install --no-cache-dir -r /requirements.txt \ - && opentelemetry-bootstrap -a install - -COPY ./app /app/app -``` +**Framework-specific instrumentation packages are not pre-installed.** Because `opentelemetry-bootstrap` installs packages based on what is already present in the environment, it is intentionally left out of this base image — running it here would have no useful effect. Instead, you should add instrumentation in your own Dockerfile. ### `PORT`