275

I'm trying to dockerize my node.js app. When the container is built I want it to run a git clone and then start the node server. Therefore I put these operations in a .sh script. And run the script as a single command in the ENTRYPOINT:

FROM ubuntu:14.04

RUN apt-get update && apt-get install -y build-essential libssl-dev gcc curl npm git

#install gcc 4.9
RUN apt-get install -y software-properties-common python-software-properties
RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
RUN apt-get update
RUN apt-get install -y libstdc++-4.9-dev

#install newst nodejs
RUN curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
RUN apt-get install -y nodejs

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ADD package.json /usr/src/app/
RUN npm install

ADD docker-entrypoint.sh /usr/src/app/

EXPOSE 8080

ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"] 

My docker-entrypoint.sh looks like this:

git clone git@<repo>.git
git add remote upstream git@<upstream_repo>.git

/usr/bin/node server.js

After building this image and run:

docker run --env NODE_ENV=development -p 8080:8080 -t -i <image>

I'm getting:

docker: Error response from daemon: oci runtime error: exec: "/usr/src/app/docker-entrypoint.sh": permission denied.

I shell into the container and the permission of docker-entrypoint.sh is:

-rw-r--r-- 1 root root 292 Aug 10 18:41 docker-entrypoint.sh

three questions:

  1. Does my bash script have wrong syntax?

  2. How do I change the permission of a bash file before adding it into an image?

  3. What's the best way to run multiple git commands in entrypoint without using a bash script?

Thanks.

Calvin Hu
  • 3,595
  • 4
  • 18
  • 23
  • We need to see the file permissions to be able to answer this question. – Charles Duffy Aug 10 '16 at 20:15
  • 3
    BTW, if this is a **bash** script, not a **sh** script, a `.sh` extension leaves a misleading impression about which interpreters can execute it. You might consider taking that out -- it's not conventional for UNIX commands to have extensions (you don't run `ls.elf`, for instance). – Charles Duffy Aug 10 '16 at 20:17
  • Can we `exec` a shell that way? wouldn't it need the `bash` prefix. – Jean-François Fabre Aug 10 '16 at 20:20
  • @Jean-FrançoisFabre, what exactly do you mean by your question? (I don't understand what "exec a shell that way" means -- what's "that way" in this context?) – Charles Duffy Aug 10 '16 at 20:21
  • 2
    Silly question, by the way -- are the script's permissions correct *before* you add them to the image? – Charles Duffy Aug 10 '16 at 20:23
  • (...btw, editing a question in a way that makes a previously-given answer no longer make sense is frowned on a bit). – Charles Duffy Aug 10 '16 at 20:23
  • I mean: if I perform a exec of a script not within a shell, it refuses to execute. It works if the exec uses a shell to run. But maybe that's already covered. – Jean-François Fabre Aug 10 '16 at 20:52
  • @Jean-FrançoisFabre, that's something that happens when you don't have a valid shebang: Many shells will assume that a file with the executable bit set but no valid shebang (for which the `execv` call fails, meaning the OS can't figure out how to execute it) should be executed as a script with that shell itself, and will fall back to doing so, but the operating system won't make that assumption and will simply refuse to execute content without a proper shebang. – Charles Duffy Aug 10 '16 at 21:11
  • @Jean-FrançoisFabre, ...so, the simple mechanism to avoid that behavior is to ensure that your scripts always start with `#!/bin/bash` (if bash), `#!/bin/sh` (if POSIX sh), etc. – Charles Duffy Aug 10 '16 at 21:14
  • I encountered similar issue. However, running `RUN ["chmod", "+x", "/usr/src/app/docker-entrypoint.sh"]` doesn't work for me. It only works when i change the permission from my local source directory. I'm not sure why I can't change the executable permission from Dockerfile. Does anybody have similar issue ? – Arif Oyong Jun 08 '19 at 07:33

12 Answers12

356
  1. "Permission denied" prevents your script from being invoked at all. Thus, the only syntax that could be possibly pertinent is that of the first line (the "shebang"), which should look like #!/usr/bin/env bash, or #!/bin/bash, or similar depending on your target's filesystem layout.

  2. Most likely the filesystem permissions not being set to allow execute. It's also possible that the shebang references something that isn't executable, but this is far less likely.

  3. Mooted by the ease of repairing the prior issues.


The simple reading of

docker: Error response from daemon: oci runtime error: exec: "/usr/src/app/docker-entrypoint.sh": permission denied.

...is that the script isn't marked executable.

RUN ["chmod", "+x", "/usr/src/app/docker-entrypoint.sh"]

will address this within the container. Alternately, you can ensure that the local copy referenced by the Dockerfile is executable, and then use COPY (which is explicitly documented to retain metadata).

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • I think you are right. I should use COPY instead. But it seems I still need to change the permission after COPYing the bash script. – Calvin Hu Aug 10 '16 at 21:14
  • I have a phar file that creates .bash scripts based on a command and then removes them once they have completed. So the need for shared volumes to have the execute permission set is something I'm still struggling with. – raupie Dec 03 '17 at 23:19
  • 2
    @raupie, if you want to run a script off a mount point with the `noexec` flag, run `bash yourscript` instead of `./yourscript`. – Charles Duffy Dec 04 '17 at 15:55
  • 3
    I don't undertand, when I run `docker build` the imtermediate container works fine. But when I do `docker run`, it throws such error. Seems like a magical intermediate container I have got. – Tiina Mar 12 '19 at 09:58
  • 1
    Neither RUN ["chmod", "+x", "/usr/src/app/docker-entrypoint.sh"] nor RUN ["chmod", "a+x", "/usr/src/app/docker-entrypoint.sh"] did change the permissions in my docker image, it's still '-rw-r--r-- ' – niid Nov 21 '20 at 13:19
  • 1
    @niid, if you create a question with a Dockerfile that acts as a [mre] for the issue, feel free to @-notify me there. – Charles Duffy Nov 21 '20 at 21:18
  • "Alternately, you can ensure that the local copy referenced by the Dockerfile is executable" is the way to go if you're using rootless docker images (Since you won't be having permission to run `chmod` in the first place). – Kshitij Patil Sep 21 '21 at 14:36
92

An executable file needs to have permissions for execute set before you can execute it.

In your machine where you are building the docker image (not inside the docker image itself) try running:

ls -la path/to/directory

The first column of the output for your executable (in this case docker-entrypoint.sh) should have the executable bits set something like:

-rwxrwxr-x

If not then try:

chmod +x docker-entrypoint.sh

and then build your docker image again.

Docker uses it's own file system but it copies everything over (including permissions bits) from the source directories.

Sami Start
  • 1,755
  • 15
  • 9
  • 30
    `chmod +x docker-entrypoint.sh` on tzhe host is actually the recommended solution, as it is much simpler than changing your `Dockerfile`. – jotrocken May 02 '17 at 19:04
  • This worked for me. I did not really understand why though xD. If you reader end up in this at some point, I would appreciate the reasons behind this. – Fnaxiom Oct 22 '20 at 11:56
  • 1
    if you have a posix compatible filesystems (i.e. you run macos or linux or some bsd) then you docker will copy the rights from the host. on windows, for example, you don't have those, so it will just add them. – niid Nov 21 '20 at 13:13
54

I faced same issue & it resolved by

ENTRYPOINT ["sh", "/docker-entrypoint.sh"]

For the Dockerfile in the original question it should be like:

ENTRYPOINT ["sh", "/usr/src/app/docker-entrypoint.sh"]
Saurabhcdt
  • 1,010
  • 1
  • 12
  • 24
  • 9
    This is a workaround, but not a great one -- this interprets the script with `sh`, ignoring its shebang's specification of an interpreter; so if it uses `#!/bin/bash`, saying it wants to be interpreted with bash, that will be ignored and it'll be interpreted with `sh` instead, thus disallowing language features like `[[ ]]`, arrays, etc. – Charles Duffy Jul 11 '18 at 10:52
  • 1
    I've used your approach and it worked. Maybe also dos2unix does the trick – Wakan Tanka Jun 08 '20 at 10:06
  • This approach is the one that worked for me. I wonder what is the reason behind it. – Jake Armstrong Mar 16 '21 at 13:31
  • thank you, save me hours upon hours of research! – Kelvin Mar 28 '21 at 05:18
  • 1
    @CharlesDuffy What would be right solution instead? – Fernando Torres Jul 20 '21 at 20:12
  • @FernandoTorres, set the entrypoint to be _the script itself_. `ENTRYPOINT ["/docker-entrypoint"]` ([`.sh` extensions are bad practice](https://www.talisman.org/~erlkonig/documents/commandname-extensions-considered-harmful/)) -- with a valid shebang line specifying the interpreter to use, and `+x` permissions so that shebang gets used. – Charles Duffy Jul 20 '21 at 21:46
39

The problem is due to original file not having execute permission.

Check original file has permission.

run ls -al

If result get -rw-r--r-- ,

run
chmod +x docker-entrypoint.sh

before docker build!

rumbarum
  • 803
  • 7
  • 7
22

Remove Dot [.]

This problem take with me more than 3 hours finally, I just tried the problem was in removing dot from the end just.

problem was

docker run  -p 3000:80 --rm --name test-con test-app .

/usr/local/bin/docker-entrypoint.sh: 8: exec: .: Permission denied

just remove dot from the end of your command line :

docker run  -p 3000:80 --rm --name test-con test-app 
Abd Abughazaleh
  • 4,615
  • 3
  • 44
  • 53
7

Grant execution rights to the file docker-entrypoint.sh

sudo chmod 775 docker-entrypoint.sh
helvete
  • 2,455
  • 13
  • 33
  • 37
  • When we write dockerfile we try to run the script sometimes, so the script must have proper rights to run, while docker creates an image. 'docker-entrypoint.sh' – Muhammad Jamee Ghouri Mar 16 '23 at 15:38
4

This is a bit stupid maybe but the error message I got was Permission denied and it sent me spiralling down in a very wrong direction to attempt to solve it. (Here for example)

I haven't even added any bash script myself, I think one is added by nodejs image which I use.

FROM node:14.9.0

I was wrongly running to expose/connect the port on my local:

docker run -p 80:80 [name] . # this is wrong!

which gives

/usr/local/bin/docker-entrypoint.sh: 8: exec: .: Permission denied

But you shouldn't even have a dot in the end, it was added to documentation of another projects docker image by misstake. You should simply run:

docker run -p 80:80 [name]

I like Docker a lot but it's sad it has so many gotchas like this and not always very clear error messages...

OZZIE
  • 6,609
  • 7
  • 55
  • 59
3

If you do not use DockerFile, you can simply add permission as command line argument of the bash:

docker run -t <image>  /bin/bash -c "chmod +x /usr/src/app/docker-entrypoint.sh; /usr/src/app/docker-entrypoint.sh"
betontalpfa
  • 3,454
  • 1
  • 33
  • 65
3

This is an old question asked two years prior to my answer, I am going to post what worked for me anyways.

In my working directory I have two files: Dockerfile & provision.sh

Dockerfile:

FROM centos:6.8

# put the script in the /root directory of the container
COPY provision.sh /root

# execute the script inside the container
RUN /root/provision.sh

EXPOSE 80

# Default command
CMD ["/bin/bash"]

provision.sh:

#!/usr/bin/env bash

yum upgrade

I was able to make the file in the docker container executable by setting the file outside the container as executable chmod 700 provision.sh then running docker build . .

BradChesney79
  • 650
  • 7
  • 16
2

I faced the same issue. This works for me.

COPY ./entrypoint.sh /entrypoint
RUN sed -i 's/\r//' /entrypoint
RUN chmod +x /entrypoint

ENTRYPOINT ["/entrypoint"]
sharif_42
  • 511
  • 4
  • 11
0

If you still get Permission denied errors when you try to run your script in the docker's entrypoint, just try DO NOT use the shell form of the entrypoint:

Instead of: ENTRYPOINT ./bin/watcher write ENTRYPOINT ["./bin/watcher"]:

https://docs.docker.com/engine/reference/builder/#entrypoint

enter image description here

James Bond
  • 2,229
  • 1
  • 15
  • 26
0

I had 4 mysql docker images which was the cause. Removed them all & did a fresh image install.

docker images -a | grep "mysql" | awk '{print $3}' | xargs docker rmi -f