I have written a python script to run the commands to execute nerdctl shell commands using subprocess,
res = subprocess.run(
f"nerdctl --host '/host/run/containerd/containerd.sock' --namespace k8s.io commit {container} {image}",
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/bash')
I'm running this python script inside a ubuntu container, When I sh inside the conatiner and run this script by passing arguments
python3 run_script.py b3425e7a0d1e image1
it executes properly, but when I run it using debug mode
kubectl debug node/pool-93oi9uqaq-mfs8b -it --image=registry.digitalocean.com/test-registry-1/nerdctl@sha256:56b2e5690e21a67046787e13bb690b3898a4007978187800dfedd5c56d45c7b2 -- python3 run_script.py b3425e7a0d1e image1
I'm getting the error
b'/bin/bash: line 1: nerdctl: command not found\n'
can some one help/suggest where it is going wrong?
run_script.py
import subprocess
import sys
container = sys.argv[1]
image = sys.argv[2]
res = subprocess.run(
f"nerdctl --host '/host/run/containerd/containerd.sock' --namespace k8s.io commit {container} {image}",
shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/bash')
print(res)
Dockerfile
FROM ubuntu:latest
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
LABEL version="0.1.0"
RUN apt-get -y update
RUN apt-get install wget curl -y
RUN wget -q "https://github.com/containerd/nerdctl/releases/download/v1.0.0/nerdctl-full-1.0.0-linux-amd64.tar.gz" -O /tmp/nerdctl.tar.gz
RUN mkdir -p ~/.local/bin
RUN tar -C ~/.local/bin/ -xzf /tmp/nerdctl.tar.gz --strip-components 1 bin/nerdctl
RUN echo -e '\nexport PATH="${PATH}:~/.local/bin"' >> ~/.bashrc
RUN source ~/.bashrc
Mechanically: the binary you're installing isn't in $PATH
anywhere. You unpack it into probably /root/.local/bin
in the container filesystem but never add that to $PATH
. The final RUN source
line has no effect since each RUN
command runs in a new shell (and technically a new container) and so the changes it makes are lost immediately. The preceding line tries to change a shell dotfile, but most paths to running things in Docker don't read shell dotfiles at all.
The easiest solution here is to unpack the binary into a directory that's already in $PATH
, like /usr/local/bin
.
FROM ubuntu:latest
LABEL version="0.1.0"
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install --no-install-recommends --assume-yes \
wget
RUN wget -q "https://github.com/containerd/nerdctl/releases/download/v1.0.0/nerdctl-full-1.0.0-linux-amd64.tar.gz" -O /tmp/nerdctl.tar.gz \
&& tar -C /usr/local -xzf /tmp/nerdctl.tar.gz bin/nerdctl \
&& rm /tmp/nerdctl.tar.gz
WORKDIR /app
...
CMD ["./run_script.py"]
You'll have a second bigger problem running this, though. A container doesn't normally have access to the host's container runtime to be able to manipulate containers. In standard Docker you can trivially root the host system if you can launch a container; it's possible to mount the Docker socket into a container but does require thinking hard about the security implications.
Your question has several hints at Kubernetes and I'd expect a responsible cluster administrator to make it hard-to-impossible to bypass the cluster container runtime and potentially compromise nodes this way. If you're using Kubernetes you probably can't access the host container runtime at all, whether it's Docker proper or something else.
Philosophically, it looks like you're trying to script a commit
command. Using commit
at all is almost never a best practice. Again, there are several practical problems with it around Kubernetes (which replica would you be committing? how would you save the resulting image? how would you reuse it?) but having an image you can't recreate from source can lead to later problems around for example taking security updates.