Solution below
I am trying to containerise an old legacy Python application using Nix. I managed to use stdenv.mkDerivation
to create a derivation that builds the program and I can run it when using nix run .#myService
.
I cannot share very much code because this is company code, but here is the derivation a bit changed that is to build the container:
{ pkgs ? import <nixpkgs> { }, myService, registryPrefix ? "" }:
pkgs.dockerTools.buildLayeredImage {
name = "${registryPrefix}${myService.name}";
tag = myService.version;
contents = [
myService
];
config = {
Entrypoint = [
"${myService}/bin/myService"
];
};
}
This builds fine, but when I docker load
and docker run
it, I get:
/nix/store/3w9plzigvyakxixm7jrgbrk1sglhqwsq-myService/bin/myService: line 3: /nix/store/ja6aizw3kd02a8xiv7qxw7gphhpknv3i-myService-env-0.0.6/bin/python3.8: cannot execute: required file not found
The python3.8
executable exists at this location in the container, and ldd
also shows nothing suspicious:
linux-vdso.so.1 (0x00007ffffff89000)
libpthread.so.0 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib/libpthread.so.0 (0x00007ff9b7116000)
libdl.so.2 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib/libdl.so.2 (0x00007ff9b7111000)
libutil.so.1 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib/libutil.so.1 (0x00007ff9b710c000)
libm.so.6 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib/libm.so.6 (0x00007ff9b7026000)
libc.so.6 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib/libc.so.6 (0x00007ff9b6e2f000)
librt.so.1 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib/librt.so.1 (0x00007ff9b6e28000)
/lib64/ld-linux-x86-64.so.2 => /nix/store/0wydilnf1c9vznywsvxqnaing4wraaxp-glibc-2.39-52/lib64/ld-linux-x86-64.so.2 (0x00007ff9b7482000)
What should I try next, before using our Company Gitlab, Dockerfiles and classic imperative gitlab-ci and Kaniko to build the container?
Solution
Yesterday I remembered having had this problem with a container I built with classic Dockerfiles and using Alpine as a base image, and it went away when I changed that to Ubuntu. So I tried just using an Ubuntu image as a fromImage
:
{ pkgs ? import <nixpkgs> { }, myService, registryPrefix ? "" }:
pkgs.dockerTools.buildLayeredImage {
name = "${registryPrefix}${myService.name}";
tag = myService.version;
# Solution:
fromImage = pkgs.dockerTools.pullImage {
imageName = "docker.io/ubuntu";
imageDigest = "sha256:c920ba4cfca05503764b785c16b76d43c83a6df8d1ab107e7e6610000d94315c";
finalImageName = "ubuntu";
finalImageTag = "24.04";
sha256 = "sha256-HYcO+KPBczsykZj5TkVuIzGnvHqb1ujE4fJuvLKATB0=";
os = "linux";
arch = "x86_64";
};
contents = [
myService
];
config = {
Entrypoint = [
"${myService}/bin/myService"
];
};
}
With the Ubuntu in the image, the Conda Python is happy.