Hi, Im stuck with translating a docker image into Nix.
I have this docker Image:
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install flask
EXPOSE 5000
ENV FLASK_APP=app.py
CMD ["python", "app.py"]
I started by making a nix file like this:
{ pkgs ? import <nixpkgs> { } }:
pkgs.dockerTools.buildImage {
name = "flask-app";
contents = [
pkgs.python312
pkgs.python312Packages.flask
./app.py
];
config = {
Cmd = [
"${pkgs.python312}/bin/python app.py"
];
ExposedPorts = [ "5000" ];
};
}
nix-build fail because of the app.py
I feel like I have searched the whole internet to get there, and I really dont know how to get this thing to work
I would also like to be able to build the image with the same base image python:3.12-slim.
Any help or working example would be appreciated
misuzu
August 28, 2024, 6:50pm
2
Try this:
{ pkgs ? import <nixpkgs> { } }:
pkgs.dockerTools.buildImage {
name = "flask-app";
config = {
Cmd = [
(pkgs.lib.getExe (pkgs.python3.withPackages (ps: with ps; [ flask ])))
./app.py
];
ExposedPorts = { "5000/tcp" = { }; };
};
}
I can also recommend using buildLayeredImage function instead.
1 Like
I get an exec /nix/store/rnbknf85mdk1dpd9baabn27lvvgbkzf5-python3-3.12.4-env/bin/python3.12: exec format error
when running docker load < /nix/store/.....
(I had to remove the exposedPorts btw)
misuzu
August 28, 2024, 7:02pm
4
JustAlternate:
exec format error
This probably means you’re building an image for one architecture but running it on a different one.
Ohhh yes, I’m on macos aarch64
Do you think i can use pkgs.pkgsCross.musl64 ?
I will try it
misuzu
August 28, 2024, 7:06pm
6
Probably not: Cross compilation — nix.dev documentation
macOS/Darwin is a special case, as not the whole OS is open-source. It’s only possible to cross compile between aarch64-darwin
and x86_64-darwin
. aarch64-darwin
support was recently added, so cross compilation is barely tested.
You’ll need to build on a linux machine
Ok I will try this, thank you for your help !
misuzu
August 28, 2024, 7:28pm
8
Here’s a weird trick: create a script nix-in-docker
#!/usr/bin/env bash
set -euo pipefail
if ! command -v docker &> /dev/null
then
echo "Please install docker first."
exit 1
fi
if ! docker container inspect nix-docker > /dev/null 2>&1; then
docker create --privileged --name nix-docker -it -w /work -v $(pwd):/work -v /var/run/docker.sock:/var/run/docker.sock nixos/nix
docker start nix-docker > /dev/null
docker exec nix-docker bash -c "git config --global --add safe.directory /work"
docker exec nix-docker bash -c "echo 'sandbox = true' >> /etc/nix/nix.conf"
docker exec nix-docker bash -c "echo 'filter-syscalls = false' >> /etc/nix/nix.conf"
docker exec nix-docker bash -c "echo 'max-jobs = auto' >> /etc/nix/nix.conf"
docker exec nix-docker bash -c "echo 'experimental-features = nix-command flakes' >> /etc/nix/nix.conf"
docker exec nix-docker bash -c "nix-env -iA nixpkgs.docker"
fi
docker start nix-docker > /dev/null
docker exec -it nix-docker "$@"
Then you can build for linux in docker using nix :
% cat app.py
print("hello")
% cat test.nix
{ pkgs ? import <nixpkgs> { } }:
pkgs.dockerTools.streamLayeredImage {
name = "flask-app";
tag = "latest";
config = {
Cmd = [
(pkgs.lib.getExe (pkgs.python3.withPackages (ps: with ps; [ flask ])))
./app.py
];
ExposedPorts = { "5000/tcp" = { }; };
};
}
% ./nix-in-docker bash -c '$(nix-build --no-out-link ./test.nix) | docker load'
No 'fromImage' provided
Creating layer 1 from paths: ['/nix/store/hv86slhk48azwbsrbhcj96hncmhhlivy-libunistring-1.1']
Creating layer 2 from paths: ['/nix/store/27vkyi25zyg389h30hlycg0d7cnvxdc4-libidn2-2.3.7']
Creating layer 3 from paths: ['/nix/store/lf4aygw01556s2rmc5r6bmvbk2csl1yw-xgcc-13.2.0-libgcc']
Creating layer 4 from paths: ['/nix/store/p852ydpr8zlq0szh5fpvvbzzjaq2ydp5-glibc-2.39-52']
Creating layer 5 from paths: ['/nix/store/6w326q1jsfx0am40pdpypv2vvamb1ga2-ncurses-6.4']
Creating layer 6 from paths: ['/nix/store/x5rjb9waw4rq71dawppzbwh665zz2v4l-zlib-1.3.1']
Creating layer 7 from paths: ['/nix/store/8vhl7vphcrrdbr4vq619z38pw6rldg40-gcc-13.2.0-libgcc']
Creating layer 8 from paths: ['/nix/store/2m7agxcdx1lxxb1j3s0ax08q25gpf42c-bash-5.2p26']
Creating layer 9 from paths: ['/nix/store/8imm5jfrj30a25c3k00w6hgp17kgmzly-gcc-13.2.0-lib']
Creating layer 10 from paths: ['/nix/store/w29ni1swl57igsdnrqd6dz3fg2k8n0bg-bzip2-1.0.8']
Creating layer 11 from paths: ['/nix/store/6slgfzsqii7pgf722hilrxqvrbd5x3gy-expat-2.6.2']
Creating layer 12 from paths: ['/nix/store/61niss1jsj0mji7kh953j9aywv2jqv93-gdbm-1.23']
Creating layer 13 from paths: ['/nix/store/l647q83z7wacl2akm2ismlkx0x9d36a0-libffi-3.4.6']
Creating layer 14 from paths: ['/nix/store/inrx2z41965zc4psk4n9h206hkn1fy3g-libxcrypt-4.4.36']
Creating layer 15 from paths: ['/nix/store/g0vm4hi04x3gjdz64b4a0rkvjii49q1g-mailcap-2.1.53']
Creating layer 16 from paths: ['/nix/store/viwacf92as039w84415shdhxyb69gfn3-mpdecimal-4.0.0']
Creating layer 17 from paths: ['/nix/store/m2c94nnyjhb20jdvb1671rhcrjywcxv4-openssl-3.0.14']
Creating layer 18 from paths: ['/nix/store/npawvy9rws8ifi2dd9c9z56j7lmd9b0f-readline-8.2p10']
Creating layer 19 from paths: ['/nix/store/p7skikz70hkik6w724fxcpvga8n5nccb-sqlite-3.45.3']
Creating layer 20 from paths: ['/nix/store/81rfrad1g90c5fk5s11mkxwnqh1x9ykm-tzdata-2024a']
Creating layer 21 from paths: ['/nix/store/4fanz2da3w8dcf41ji8g8x1yqd1dqx4w-xz-5.4.7']
Creating layer 22 from paths: ['/nix/store/1rnzwz9b7912c2dng6gswiaz0gwk8w7x-python3-3.11.9']
Creating layer 23 from paths: ['/nix/store/gpiwkk0dbvyhmvbskjxzljhncmqx6ay8-python3.11-markupsafe-2.1.5']
Creating layer 24 from paths: ['/nix/store/5crnmmvm1132hnril3js5rjx9ifkfhja-python3.11-blinker-1.7.0']
Creating layer 25 from paths: ['/nix/store/mpa371bynwna3fnivxfgrdhz5nyz793f-python3.11-click-8.1.7']
Creating layer 26 from paths: ['/nix/store/ck6b1fb2f765xbjazckrhwxzpfg7x9xv-python3.11-itsdangerous-2.2.0']
Creating layer 27 from paths: ['/nix/store/g72yf6r9q99qp8iny7fjgjs4a2sfnsz7-python3.11-jinja2-3.1.4']
Creating layer 28 from paths: ['/nix/store/ziklj6wlgx6s7xycha992z13mr87xbrj-python3.11-werkzeug-3.0.3']
Creating layer 29 from paths: ['/nix/store/zliqz38i91dsrffgxp6v301k8s0n7j60-python3.11-flask-3.0.3']
Creating layer 30 from paths: ['/nix/store/djgq94bi0ixcn8dhdrlx8qk70rm245m4-app.py']
Creating layer 31 from paths: ['/nix/store/ggkc81v0xs7q967xq1kd0ic2jr480xr7-python3-3.11.9-env']
Creating layer 32 with customisation...
Adding manifests...
Done.
Loaded image: flask-app:latest
% docker run --rm -it flask-app:latest
hello
2 Likes
Using docker to build the docker image ? lmao
1 Like