-1

I have this project:

script.sh:

#!/bin/sh
echo "test"

Dockerfile:

FROM ubuntu
RUN ["sh", "script.sh"]

With build command docker build -t test ., I get this error:

 => [internal] load .dockerignore                                                                                  0.1s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load build definition from Dockerfile                                                               0.1s
 => => transferring dockerfile: 118B                                                                               0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                   2.3s
 => [auth] library/ubuntu:pull token for registry-1.docker.io                                                      0.0s
 => CACHED [1/2] FROM docker.io/library/ubuntu@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44f  0.0s
 => ERROR [2/2] RUN ["sh", "script.sh"]                                                                            0.9s
------
 > [2/2] RUN ["sh", "script.sh"]:
#0 0.791 sh: 0: cannot open script.sh: No such file
------
Dockerfile:2
--------------------
   1 |     FROM ubuntu
   2 | >>> RUN ["sh", "script.sh"]
--------------------
ERROR: failed to solve: process "sh script.sh" did not complete successfully: exit code: 2

However if I change the Dockerfile to:

FROM ubuntu
CMD ["sh", "script.sh"]

Then it works:

[+] Building 1.2s (5/5) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.1s
 => => transferring dockerfile: 73B                                                                                0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                   1.0s
 => CACHED [1/1] FROM docker.io/library/ubuntu@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44f  0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:d9bf124a17e507c73f6defde7b046fff153fb464c2cad8a57333a0966ddf07c1                       0.0s
 => => naming to docker.io/library/test                                                                            0.0s

From Difference between RUN and CMD in a Dockerfile:

RUN - command triggers while we build the docker image.

CMD - command triggers while we launch the created docker image.

Still, I can't explain why RUN doesn't work but CMD does.

Ooker
  • 1,969
  • 4
  • 28
  • 58
  • 1
    Your Dockerfile doesn't `COPY` the `script.sh` file into the container; how is it getting there? – Charles Duffy Aug 28 '23 at 15:55
  • 1
    (Answer: It's not there at all; the only reason you don't find out in the `CMD` case is that when you only `build` but don't run the container, the `CMD` never gets run, so you aren't finding out that it's broken). – Charles Duffy Aug 28 '23 at 15:56
  • You find out that `docker run` fails too – Diego Torres Milano Aug 28 '23 at 16:37
  • @CharlesDuffy I see, thanks. Why doesn't it automatically take all files in the project to build the image, like how bundlers work? Anyway, if you make it an answer I'll accept it. – Ooker Aug 28 '23 at 17:13
  • "Why doesn't it..." -- because that's not always desirable. Sometimes you have a multi-stage build, and you only use files A and B in stage-1 and then use file C in stage-2; sometimes a file is documentation and not actually used in the build at all; sometimes... etc, etc. In general, requiring the user to be explicit rather than doing things implicitly (aka "behind their back") is better form. – Charles Duffy Aug 28 '23 at 17:37

1 Answers1

2

Docker doesn't implicitly COPY contents into the container, so with your current code, your container doesn't contain any script.sh file at all.

Consider instead:

FROM ubuntu
COPY ./script.sh .
RUN ["./script.sh"]

Because you aren't running sh, the script's choice of interpreter (#!/bin/sh, #!/usr/bin/bash, #!/usr/bin/env zsh, #!/usr/bin/env python, or whatever else it might want) will be honored. (It's good practice to drop the .sh extension, so if you later rewrite to a non-shell language you won't need to choose between changing the calling convention and having a misleading filename).

Note that this does require your script to have executable permissions and a valid shebang line; you may need to use chmod +x if it does not.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441