skip to Main Content

Look at this c program:

   #include <stdio.h>
   #include <unistd.h>
   #include <signal.h>

   int stop = 0;

   void handle_signal(int sig)
   { 
      stop = 1;
   }

   void main() {
     signal(SIGINT, handle_signal);
     signal(SIGTERM, handle_signal);

     while (stop==0) {
       printf("Hellon");
       sleep(1);
     }
   }

I am compiling this program statically:

gcc -static test.c -o test

And I am creating this Dockerfile:

   FROM scratch
   COPY test /test
   ENTRYPOINT ["/test"]

I am building the docker image:

   docker build -t myimage .

Finally, I run a container from this image:

  docker run --name mycontainer myimage

I have a problem: It is impossible to stop this container.

I have tried:

  • CTRL-C
  • docker stop mycontainer
  • docker kill mycontainer
  • exiting c loop when the program receives unix signals.

I am running Docker version 20.10.25 under kali Linux. gcc version: 13.3.0

I have this error when I try to run:

docker kill --signal=SIGINT mycontainer

Cannot kill container xxxx: Unknown error after kill: runc did not
terminate successfully: exit status 1: unable to signal init:
permission denied.

Please note there is only 1 file in my container. I have nothing else (bash, sh, …)

My goal is to understand why the program is not exiting and why the container is not stopping.
Do you have any idea ? What’s wrong in what I have done ?

Thanks

2

Answers


  1. Maybe the program is not exiting, and the container is not stopping because processes running as PID 1 in Linux ignore default signals like SIGTERM and SIGINT unless explicitly handled.

    If this is the problem, the solutions is to use a minimal init system like tini to properly forward signals.

    Modify your Dockerfile to include tini:

    FROM scratch
    COPY --from=busybox /sbin/tini /tini
    COPY test /test
    ENTRYPOINT ["/tini", "--", "/test"]
    

    This ensures that signals are correctly forwarded to your program, and the container will stop as expected.

    Login or Signup to reply.
  2. In a container built from scratch, there’s no init system or shell to properly handle signals. Your program becomes PID 1 inside the container, which behaves differently regarding signal handling. I would use a minimal base image like alpine if using tini as a lightweight init system failed.

    So instead of scratch, alpine that includes an init system:

    FROM alpine:latest
    COPY test /test
    CMD ["/test"]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search