diff --git a/README.md b/README.md index c208ac9..580105d 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,11 @@ 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 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. ### `PORT` diff --git a/assets/start.sh b/assets/start.sh index 29292db..4466448 100644 --- a/assets/start.sh +++ b/assets/start.sh @@ -29,8 +29,16 @@ 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 diff --git a/dockerfile b/dockerfile index 32e517b..c7d950f 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 @@ -25,6 +26,10 @@ 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' +# Always install OpenTelemetry packages (instrumentation is controlled at runtime via OTEL_ENABLED). +# 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 @@ -37,15 +42,20 @@ 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" # 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