skip to Main Content

I have a dockerfile which ends

ENTRYPOINT ["sh"]
CMD ["runscript.sh"]

I can run docker with an argument (a shell script) that overrides "runscript.sh" (if i wish). Note: the shell scripts are provided by a --bind mount

I am translating my Dockerfile to a Singularity recipe. From my understanding i can replicate this ENTRYPOINT/CMD functionality using the "%startscript" label. I am trying:

%startscript
exec "$@"

then run an instance of the container using

singularity instance start --bind /hostpath:/containerpath model.sif instancename script.sh

When i do this i get the message:

/.singularity.d/startscript: 4: exec: script.sh: not found

I know i am doing this all wrong, but cant seem to work out what.

Note: if i replace exec "$@" with ./script.sh then the script is executed but i am limited to having a script with this name. I want the flexibility to pass any named script.

2

Answers


  1. Chosen as BEST ANSWER

    You need to use

    %runscript
    

    and not

    %startscript
    

    Then you can pass an argument to run command which will be used in place of the default value in the recipe,

    singularity exec image argument
    

    eg. in the recipe file

     %runscript
    ./runscript.sh
    

    then use either

    singularity exec image.sif 
    

    or

    singularity exec image.sif newscript.sh
    

    depending on whether you want to run the default container script or the "newscript"


  2. In your original Dockerfile:

    1. Remove the ENTRYPOINT
    2. Make sure the CMD includes some sort of path, like CMD ["./runscript.sh"]
    3. Make sure the first line of the script is a "shebang" line, #!/bin/sh
    4. On the host system, make sure the script is executable, chmod +x runscript.sh, and check that change into source control

    This is the same set of steps you’d need to do to be able to run ./runscript.sh on the host system, without Docker, and the same rules apply.

    In the script you show, you’re just running exec "$@", presumably as an entrypoint script being passed the CMD as arguments. Your original Dockerfile prepended whatever CMD it was given with sh (the ENTRYPOINT value), but this wrapper doesn’t, and that’s why you’re getting different behavior.

    In general I wouldn’t encourage splitting out the name of a language interpreter into ENTRYPOINT. I prefer a pattern of CMD being a complete command, which is compatible with the sort of entrypoint wrapper script you show. There’s also a pattern of ENTRYPOINT being a complete command and CMD its arguments (Kubernetes calls these options command: and args:). What you have here is kind of a half way, though: if you override CMD then you must repeat the program name, but you can only actually run programs that are implemented as shell scripts.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search