Docker custom .deb file location - docker

I had to compile a custom kernel to get Ubuntu to run on my laptop and now I'm trying to run docker containers on it.
It generated packages I installed:
linux-headers-5.15.30-25.25custom_5.15.30-25.25custom-1_amd64.deb
linux-image-5.15.30-25.25custom-dbg_5.15.30-25.25custom-1_amd64.deb
linux-image-5.15.30-25.25custom_5.15.30-25.25custom-1_amd64.deb
Now when I try to create docker images I get the following error:
...
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package linux-headers-5.15.30-25.25custom
E: Couldn't find any package by glob 'linux-headers-5.15.30-25.25custom'
E: Couldn't find any package by regex 'linux-headers-5.15.30-25.25custom'
The Dockerfile just pulls an nvidia image and adds some other packages required
FROM nvidia/cuda:11.4.2-devel-ubuntu18.04
ARG COMPILE_GRAPHICS=OFF
ARG DEBIAN_FRONTEND=noninteractive
USER root
RUN \
set -ex && \
apt-key update && \
apt-get update && \
apt-get install -y -q \
build-essential \
software-properties-common \
openssl \
curl && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /var/cache/apt/archives/ && \
rm -rf /usr/share/doc/ && \
rm -rf /usr/share/man/
...
It is installed on the host PC
~$ sudo dpkg -l | grep linux-headers-5.15.30-25.2
ii linux-headers-5.15.30-25.25custom 5.15.30-25.25custom-1 amd64 Linux kernel headers for 5.15.30-25.25custom on amd64
There's no problem on other machines using the upstream Ubuntu kernel packages.
So guess docker needs the actual package. How can I add a custom location to fetch the packages?
Thanks

I get the feeling you are mixing up what is outside and inside of a container.
Outside - on your host operating system you had to compile a custom kernel to get Linux running. So far so good.
Now you are trying to build a docker container. So the next steps are happening inside the container. Docker is lightweight virtualization therefore the container runs on the same kernel as the host. Since some package dependency is on the kernel's headers, and apt is trying to install the Debian package for them but cannot find them. Seems obvious as you are running a custom kernel and the package is in none well-known repository.
To get out of the situation:
check whether the headers for your kernel are available as .deb
make that .deb available inside the container. This may happen by placing them into the Docker build context.
ensure your Dockerfile installs the .deb before installing whatever needs that .deb. This will prevent it is searched in online repositories.

Related

docker ERROR: "/${DIR_NAME}" not found: not found - How to avoid huge images

I'm running into a problem with docker where I'm using some variables in the dockerfile. The variables work everywhere except in the source= argument of a bind mount.
I'm installing a large (40+ GB) software package. I have three different versions to work with so I made a variable to identify the version directory. I'm using a bind mount to avoid sending the installation source to the image.
What is the best way to debug? --progress=plain and --no-cache don't really show much more on the error message.
Is there a better way to do this whole thing? I don't want to create 150 GB images if I can avoid that. If I have all three versions of software in one directory that could be a long build and a big image since I need to select the version at build time. I guess I may need a more involved build process than allowed here--what would that look like?
How do I get around this variable issue?
The command that causes the problem is here:
ARG SOFTWARE_DIR=MySoftwareDirectory #this lives in the same directory as the *.docker
ARG SOFTWARE_VER=2022.3
FROM centos:latest AS base
RUN yum update -y \
&& yum upgrade -y \
&& yum install -y libXext libXrender libXtst \
&& yum clean all
RUN mkdir /tools
FROM base as final
ARG SOFTWARE_VER
ARG SOFTWARE_DIR
COPY ./install_config_${SOFTWARE_VER}.txt /tools/install_config.txt
RUN --mount=type=bind,target=/mnt/${SOFTWARE_DIR},readonly,source=${SOFTWARE_DIR} \
/mnt/${SOFTWARE_DIR}/setup --batch
ENTRYPOINT ["/tools/software/${SOFTWARE_VER}/bin/software"]
The error is:
ERROR: "/${SOFTWARE_DIR}" not found: not found
...
failed to computer cache key: "/${SOFTWARE_DIR}" not found: not found
This works:
ARG SOFTWARE_DIR=MySoftwareDirectory #this lives in the same directory as the *.docker
ARG SOFTWARE_VER=2022.3
FROM centos:latest AS base
RUN yum update -y \
&& yum upgrade -y \
&& yum install -y libXext libXrender libXtst \
&& yum clean all
RUN mkdir /tools
FROM base as final
ARG SOFTWARE_VER
ARG SOFTWARE_DIR
COPY ./install_config_${SOFTWARE_VER}.txt /tools/install_config.txt
RUN --mount=type=bind,target=/mnt/${SOFTWARE_DIR},readonly,source=MySoftwareDirectory \
/mnt/${SOFTWARE_DIR}/setup --batch
ENTRYPOINT ["/tools/software/${SOFTWARE_VER}/bin/software"]
I am building with:
DOCKER_BUILDKIT=1 docker build -t software -f software.docker .
My directory structure looks like this:
software.docker
MySoftwareDirectory
I did chmod 777 on MySoftwareDirectory to correct permissions issue. (I know not the best way)
Docker version is 20.10.21. Host is CentOS 7 fully patched.

Install Java runtime in Debian based docker image

I am trying to install the java runtime in a Debian based docker image (mcr.microsoft.com/dotnet/core/sdk:3.1-buster). According to various howtos this should be possible by running
RUN apt update
RUN apt-get install openjdk-11-jre
The latter command comes back with
E: Unable to locate package openjdk-11-jre
However according to https://packages.debian.org/buster/openjdk-11-jre the package does exist. What am I doing wrong?
Unsure from which image your are pulling. I used slim, Dockerfile.
from debian:buster-slim
ENV DEBIAN_FRONTEND=noninteractive
RUN mkdir -p /usr/share/man/man1 /usr/share/man/man2
RUN apt-get update && \
apt-get install -y --no-install-recommends \
openjdk-11-jre
# Prints installed java version, just for checking
RUN java --version
NOTE: If you don't run the mkdir -p /usr/share/man/man1 /usr/share/man/man2 you'll run into dependency problems with ca-certificates, openjdk-11-jre-headless etc. I've been using this fix provided by community, haven't really checked the permanent fix.

Prevent nvidia-docker from installing nvidia drivers with debian package

I am trying to create an nvidia-docker image with installed TensorRT for my specific application. I can't use any of the provided TensortRT base images, as they are using CUDA version not compatible with the application, but I have a custom TensorRT debian package which is used in my organization. The problem is, when I install it from the Dockerfile, it also installs nvidia drivers. As a result, the container is successfully created, but can't be started - the result is:
svc_moma_usr#PL1LXD-529389:~/gutkowsp/Docker_projects/test_cuda$ nvidia-docker run tensorrt-test
docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "process_linux.go:449: container init caused \"process_linux.go:432: running prestart hook 1 caused \\\"error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: mount error: file creation failed: /var/lib/docker/overlay2/97f449ff2535b1ad304520dae75c613931888658a66b89235b0d040a872a625c/merged/usr/bin/nvidia-smi: file exists\\\\n\\\"\"": unknown.
ERRO[0001] error waiting for container: context canceled
The dockerfile is:
FROM nvidia/cuda:9.1-devel-ubuntu16.04
ENV DEBIAN_FRONTEND noninteractive
ENV CUDNN_VERSION 7.0.5.15
LABEL com.nvidia.cudnn.version="${CUDNN_VERSION}"
RUN apt update -y && \
apt install software-properties-common -y && \
apt-add-repository --yes --update ppa:ansible/ansible && \
apt install ansible -y
RUN apt update -y && \
apt install -y --no-install-recommends \
libcudnn7=$CUDNN_VERSION-1+cuda9.1 \
libcudnn7-dev=$CUDNN_VERSION-1+cuda9.1
RUN apt update -y && \
apt install tensorrt -y
How this problem of unnecessary drivers is solved? This seems to me like a common issue, as in general nvidia docker images typically have installed nvidia software, which usually comes with drivers. Maybe someone can share the dockerfiles for the TensorRT images for reference?
For anyone who facing the same issue:
If necessary use CUDNN enabled docker image, like 11.7.1-cudnn8-runtime-ubuntu18.04 to avoid the necessity to install it using apt
Run apt update
Run apt install <your package> -y --dry-run | grep nvidia
Add all listed nvidia packages to apt ignore list - add a dash after the package name with an asterisk in place of version number
apt install <your package> libnvidia-compute-*-server- \
libnvidia-compute-*- --dry-run | grep nvidia
Make sure that none of nvidia packages will be installed. If necessary add newly discovered packages to ignore list.
If everything is OK then remove --dry-run flag and install your package
apt install <your package> libnvidia-compute-*-server- libnvidia-compute-*-

Trouble installing fuse on Debian stretch Docker image

I am attempting to fuse a dir in a Docker image using gcsfuse. I am using a Debian stretch image, and having trouble working with the fuse package.
I have attempted to install fuse both via apt-get as well as build from the source via the git repo. Both have had their respective problems.
1: After apt-get I receive indication that fuse was successfully installed.
root#a7d6f712fab9:/queue# apt-get install fuse
Reading package lists... Done
Building dependency tree
Reading state information... Done
fuse is already the newest version (2.9.7-1+deb9u2).
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
root#a7d6f712fab9:/queue# apt-get install libfuse-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
libfuse-dev is already the newest version (2.9.7-1+deb9u2)
However when running modprobe fuse (what fails during the gcsfuse mount attempt):
root#a7d6f712fab9:/queue# modprobe fuse
modprobe: ERROR: ../libkmod/libkmod.c:586 kmod_search_moddep() could not open moddep file '/lib/modules/4.9.125-linuxkit/modules.dep.bin'
modprobe: FATAL: Module fuse not found in directory /lib/modules/4.9.125-linuxkit
2: When using the tar.gz from source, meson is only available as version 0.37, whereas libfuse requires meson > 0.38 to build properly (from earlier versions).
Here's my Dockerfile:
FROM python:3.6-slim
RUN apt-get update \
&& apt-get install -y libfuse-dev \
curl \
gnupg \
apt-utils \
lsb-release \
kmod
RUN export GCSFUSE_REPO=gcsfuse-`lsb_release -c -s` \
&& echo "deb http://packages.cloud.google.com/apt $GCSFUSE_REPO main" | tee /etc/apt/sources.list.d/gcsfuse.list \
&& curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
RUN apt-get update \
&& apt-get install -y gcsfuse
COPY . /queue
WORKDIR /queue
I'd like modprobe fuse to actually work, or to understand how I can build fuse/modprobe in a way where the package is identified via modprobe.
Thanks!
Docker containers use the host kernel. So if a kernel module needs loading you have to load it on the host machine and not in Docker.

How to create the smallest possible Docker image after installing apt dependencies

I've created a Docker image using debian as the parent image. In my Dockerfile I've installed some dependencies using apt and pip.
Now, I want to get rid off everything that is not completely necessary to run my app, which of course, needs the dependencies installed.
For now I have the following lines in my Dockerfile after installing the dependencies.
RUN rm -rf /var/lib/apt/lists/* \
&& rm -Rf /usr/share/doc && rm -Rf /usr/share/man \
&& apt-get clean
I've also installed the dependencies using the --no-install-recommends option.
Anything else I can do to reduce the footprint of my Docker image?
PS: just in case, this is how I installed the dependencies:
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
sudo systemd \
build-essential libffi-dev libssl-dev \
python-pip python-dev python-setuptools python-wheel
To reduce the size of the image, you need to combine your RUN commands into one. When you create files in one layer and delete them in another, the files still exist on the drive and are shipped over the network. Their existence is just hidden when the layers of the filesystem are assembled for your container.
The Dockerfile best practices explain this in more detail: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
I'd also recommend building with docker build --rm=false --no-cache . (temporarily) and then reviewing the output of docker diff on each of the created images to see what files are created in each layer.

Resources