Deepfactor 2.1 or greater can automatically inspect the initial entrypoint, an executable or script-interpreter, and determine the libc of a dynamically linked program for compatibility.
Support Status in Deepfactor 2.1
dfctl run ... --docker-run :
- automatic entrypoint libc detection
Deepfactor Dockerfile.df build:
- automatic entrypoint libc detection by adding --build-arg "DF_IMAGE_ENTRYPOINT=
--build-arg "DF_IMAGE_ENTRYPOINT=`/opt/deepfactor/bin/df-get-entrypoint.sh $APP_IMAGE`"
Deepfactor Kubernetes mutating webhook:
- entrypoint path or libc can be specified with an annotation in the pod deployment. The path may be absolute or relative.
df.k8-app.entrypoint.path: "java"
OR
df.k8-app.entrypoint.libc: "glibc"
OR
- automatic entrypoint libc detection for image repositories is 'Tech Preview' in Deepfactor 2.2 Enable this preview feature by commenting in the following in your Deepfactor Kubernetes Admission Webhook in it's override.yaml. See 3. Install Deepfactor Mutating Admission Webhook
imageanalyzer:
enabled: true
The content below in this article is no longer applicable since Deepfactor 2.1. The issues identified below can be resolved by upgrading to Deepfactor 2.1.0 or greater.
Deepfactor dfctl, Dockerfile templates, and K8s mutating webhook scripts do not inspect the initial target executable. This limitation does not impact df runtime if it is already loaded and --multilibc auto
is enabled at dfctl/dockerffile/k8s run. See Hybrid libc environments for more information. Once Deepfactor runtime is loaded with multilibc support enabled, it will inspect an --exec*()
target executable and automatically select the appropriate libc compatible Deepfactor runtime for the target executable/script. All three inspect the target OS distribution as follows.
dfctl run --docker-run test case
- alpine with java-glibc entrypoint
$ dfctl run -v -a alpine-java -c dfctl-docker-alpine-java-entry \ 2
--multilibc auto \
--docker-run -it --rm --image adoptopenjdk/openjdk11:alpine-slim-libstdcpp java -version
dfctl version: "1.8-867" "59576458f4ef686a3b5a42ced6b2edf8f9353a59"
Detected libdf=musl, manifest libdf=auto
Application version not specified. Using binary's md5sum as version
Launching application with LD_PRELOAD=/opt/deepfactor/musl/libdf.so, manifest libc=auto
Launching application /usr/bin/docker with args docker run -it -v /home/dfadmin/Sleep.class:/Sleep.class -v df-runtime:/opt/deepfactor/ -v /dev/shm/8bef038e-33ce-47d6-8998-a56ba67fa0fb-2.json:/opt/deepfactor/manifest/8bef038e-33ce-47d6-8998-a56ba67fa0fb-2.json -e DF_MANIFEST=/opt/deepfactor/manifest/8bef038e-33ce-47d6-8998-a56ba67fa0fb-2.json -e LD_PRELOAD=/opt/deepfactor/musl/libdf.so -e DF_INSTID=1b537475-62fb-4ca9-8240-bfccfceefbf0 adoptopenjdk/openjdk11:alpine-slim-libstdcpp-fix java -version
java: libc dlopen: /usr/glibc-compat/lib/libc.so: invalid ELF header
Resolution:
- Add the --entrypoint-libc “glibc” or “musl” option in the dfctl run command [1]
OR
- Append sh -c '…'
to container entrypoint or command when run [2]
[1] Add --entrypoint-libc “glibc” to the dfctl run command
$ docker build -t adoptopenjdk/openjdk11:alpine-slim-libstdcpp - << DKREOD
> FROM adoptopenjdk/openjdk11:alpine-slim
> RUN apk add libstdc++
> DKREOD ...
$ ~/dfctl run -v -a alpine-java-glibc -c dfctl-docker-alpine-java-entry \
--multilibc auto --entrypoint-libc glibc \
--docker-run -it --rm --image adoptopenjdk/openjdk11:alpine-slim-libstdcpp java -version
dfctl version: "1.8.1-DEEP-3748" "3ddf1500ada86b54102a7287ccbacc50a033d866-M"
Application version not specified. Using binary's md5sum as version
Launching application with LD_PRELOAD=/opt/deepfactor/glibc/libdf.so, manifest libc=auto
Launching application /usr/bin/docker with args docker run -it -v /home/dfadmin/Sleep.class:/Sleep.class -v df-runtime:/opt/deepfactor/ -v /dev/shm/a55845a7-0b03-4525-a010-6ae1ce66fb66-1.json:/opt/deepfactor/manifest/a55845a7-0b03-4525-a010-6ae1ce66fb66-1.json -e DF_MANIFEST=/opt/deepfactor/manifest/a55845a7-0b03-4525-a010-6ae1ce66fb66-1.json -e LD_PRELOAD=/opt/deepfactor/glibc/libdf.so -e DF_INSTID=3135e02e-9c5b-419e-8531-86b2f3a926e1 adoptopenjdk/openjdk11:alpine-slim-libstdcpp-fix java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)
[2] e.g. Wrap the container entrypoint or command with shell: sh -c
$ dfctl run -v -a alpine-java -c dfctl-docker-alpine-sh-entry
--multilibc auto \
--docker-run -it --rm --image adoptopenjdk/openjdk11:alpine-slim-libstdcpp sh -c 'java -version'
dfctl version: "1.8-867" "59576458f4ef686a3b5a42ced6b2edf8f9353a59"
Detected libdf=musl, manifest libdf=auto
Application version not specified. Using binary's md5sum as version
Launching application with LD_PRELOAD=/opt/deepfactor/musl/libdf.so, manifest libc=auto
Launching application /usr/bin/docker with args docker run -it -v /home/dfadmin/Sleep.class:/Sleep.class --rm -v df-runtime:/opt/deepfactor/ -v /dev/shm/8bef038e-33ce-47d6-8998-a56ba67fa0fb-2.json:/opt/deepfactor/manifest/8bef038e-33ce-47d6-8998-a56ba67fa0fb-2.json -e DF_MANIFEST=/opt/deepfactor/manifest/8bef038e-33ce-47d6-8998-a56ba67fa0fb-2.json -e LD_PRELOAD=/opt/deepfactor/musl/libdf.so -e DF_INSTID=dc33b381-c2ec-4ac1-ae57-ffe7008289e5 adoptopenjdk/openjdk11:alpine-slim-libstdcpp-fix sh -c java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)
Dockerfile build deployment example test app:
See footnote [4] for APP_IMAGE
build.
$ export APP_IMAGE=adoptopenjdk11/alpine-slim:glibc-entry;
$ export DF_COMPONENT="DfDemoSpringBoot";
$ docker build -t ${APP_IMAGE}-df -f Dockerfile.alpine.hybrid.1.8.1.df
--build-arg "DF_RUN_TOKEN=${DF_RUN_TOKEN}"
--build-arg "APP_IMAGE=${APP_IMAGE}"
--build-arg "DF_APP_NAME=${APP_IMAGE}"
--build-arg "DF_COMPONENT=${DF_COMPONENT}-glibc-entry"
--no-cache .
...
Successfully tagged adoptopenjdk11/alpine-slim:glibc-entry-df
$ docker run -it --rm adoptopenjdk11/alpine-slim:glibc-entry-df
java: libc dlopen: /usr/glibc-compat/lib/libc.so: invalid ELF header
Resolution
- append sh -c '…
' to container entrypoint or command when run
OR
- manually configure the build Dockerfile.df and replace ${libc} with: musl or glibcENV LD_PRELOAD=/opt/deepfactor/${libc}/libdf.so
OR
set optional query parameter entrypoint-libc=
to the either “musl” or “glibc” to match the image's entrypoint when generating a Dockerfile.df e.g. [3]
[3] Example download of dockerfile.df with entrypoint-libc=glibc
- Dockerfile.alpine.hybrid.glibc-entry.1.8.1.df
$ df_instr_url='https://my-portal/api/services/v1/instrumentation/dockerfiles?';
$ curl -k -H "Authorization: Bearer $(cat ./my-portal.admin.api.token)"
${df_instr_url}'app_name=$\{DF_APP_NAME\}&component_name=$\{DF_COMPONENT\}&alpine=true&multilibc=auto'
| jq -r .data.file_data > Dockerfile.alpine.hybrid.1.8.1.df
....
$ curl -k -H "Authorization: Bearer $(cat ./my-portal.admin.api.token)"
${df_instr_url}'app_name=$\{DF_APP_NAME\}&component_name=$\{DF_COMPONENT\}&alpine=true&multilibc=auto'
'&entrypoint-libc=glibc'\
| jq -r .data.file_data > Dockerfile.alpine.hybrid.glibc-entry.1.8.1.df
...
$ diff Dockerfile.alpine.hybrid.1.8.1.df Dockerfile.alpine.hybrid.glibc-entry.1.8.1.df
56c56
< ENV LD_PRELOAD=/opt/deepfactor/musl/libdf.so
---
> ENV LD_PRELOAD=/opt/deepfactor/glibc/libdf.so
[4] APP_IMAGE adoptopenjdk11/alpine-slim:glibc-entry
build
$ docker build -t adoptopenjdk11/alpine-slim:glibc-entry - << DKREOD
FROM adoptopenjdk/openjdk11:alpine-slim
# libstdc++ required df runtime
RUN apk add libstdc++
COPY ./DfDemo-0.0.1-SNAPSHOT.jar /
# the alt. entrypoint commented out 'just works' because there will be an OS shell exec
# ENTRYPOINT java -jar /DfDemo-0.0.1-SNAPSHOT.jar
ENTRYPOINT [ "java", "-jar", "/DfDemo-0.0.1-SNAPSHOT.jar" ]
DKREOD
K8s deployment test example:
$ kubectl apply -f df-adoptopenjdk-glibc-entry.yml
pod/demo-hybrid-java-libc-app
$ kubectl logs demo-hybrid-java-libc-app
java: libc dlopen: /usr/glibc-compat/lib/libc.so: invalid ELF header
Example deployment image:
docker build -t my-registry/adoptopenjdk/openjdk11:alpine-slim-DfDemo-glibc-entry
- << DKREOD
FROM adoptopenjdk/openjdk11:alpine-slim
# required df runtime dep
RUN apk add libstdc++
COPY ./DfDemo-0.0.1-SNAPSHOT.jar /
ENTRYPOINT [ "java", "-jar", "/DfDemo-0.0.1-SNAPSHOT.jar" ]
DKREOD
Resolution:
- prefix sh -c '…'
to deployment command [5]
OR
- set optional df.k8-app.entrypoint.libc
annotation in pod deployment to match the container entrypoint or command [6]
[5] alter deployment command
$ diff df-adoptopenjdk-glibc-entrypoint.yml df-adoptopenjdk-musl-entrypoint.yml
14a15
> command: [ "sh", "-c", "java -jar /DfDemo-0.0.1-SNAPSHOT.jar" ]
[6] set optional df.k8-app.entrypoint.libc
example
$ diff df-adoptopenjdk-glibc-entrypoint.yml df-adoptopenjdk-glibc-entrypoint-df-annotation.yml
8a9
> df.k8-app.entrypoint.libc: "glibc"
Comments
Article is closed for comments.