运行bash脚本的docker入口点“权限被拒绝”


122

我正在尝试将我的node.js应用程序码头化。构建容器后,我希望它运行a git clone,然后启动节点服务器。因此,我将这些操作放在.sh脚本中。并在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"] 

我的docker-entrypoint.sh看起来像这样:

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

/usr/bin/node server.js

构建此映像并运行后:

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

我越来越:

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

我将其装入容器,并且docker-entrypoint.sh的许可为:

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

三个问题:

  1. 我的bash脚本语法错误吗?

  2. 在将bash文件添加到图像之前,如何更改其权限?

  3. 在不使用bash脚本的情况下在入口点运行多个git命令的最佳方法是什么?

谢谢。


我们需要查看文件权限才能回答这个问题。
查尔斯·达菲

顺便说一句,如果这是bash脚本,而不是sh脚本,则.sh扩展名会给人以误解,即解释器可以执行它。您可能会考虑将其删除-UNIX命令具有扩展名(ls.elf例如,不运行)是不常见的。
查尔斯·达菲

我们可以这样exec壳吗?它不需要bash前缀。
让·弗朗索瓦·法布尔

@Jean-FrançoisFabre,您的问题是什么意思?(我不明白“以这种方式执行shell”的意思-在这种情况下是“以这种方式”?)
Charles Duffy

2
顺便说一句愚蠢的问题-在将脚本添加到映像之前,脚本的权限是否正确?
查尔斯·达菲

Answers:


183
  1. “权限被拒绝” 根本阻止您的脚本被调用。因此,唯一可能与之相关的语法是第一行(“ shebang”)的语法,该语法应类似于#!/usr/bin/env bash,或#!/bin/bash或类似,具体取决于目标的文件系统布局。

  2. 文件系统权限很可能未设置为允许执行。shebang也可能引用了不可执行的内容,但这是远远不太可能。

  3. 解决以前的问题很容易。


简单阅读

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

...是该脚本未标记为可执行。

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

将在容器中解决此问题。或者,您可以确保Dockerfile引用的本地副本是可执行文件,然后使用COPY(明确记录为保留元数据)。


我想你是对的。我应该改用COPY。但是似乎在复制bash脚本后我仍然需要更改权限。
加尔文·胡

我有一个phar文件,该文件可基于命令创建.bash脚本,并在完成后将其删除。因此,仍然需要为共享卷设置执行权限设置。
raupie

@raupie,如果要从带有noexec标志的安装点运行脚本,请运行bash yourscript而不是./yourscript
Charles Duffy

1
我不理解,当我运行docker build即时容器时效果很好。但是当我这样做时docker run,它会抛出这样的错误。好像我有一个神奇的中间容器。
蒂娜(Tiina)

46

可执行文件必须具有执行权限集,然后才能执行。

在要构建Docker映像的计算机中(不在Docker映像本身内部)尝试运行:

ls -la path/to/directory

可执行文件输出的第一列(在本例中为docker-entrypoint.sh)应将可执行位设置为:

-rwxrwxr-x

如果没有,请尝试:

chmod +x docker-entrypoint.sh

然后再次构建您的docker映像。

Docker使用它自己的文件系统,但是它从源目录中复制所有内容(包括权限位)。


13
chmod +x docker-entrypoint.sh在tzhe主机上实际上是推荐的解决方案,因为它比更改您的容易得多Dockerfile
jotrocken

16

我遇到了同样的问题,并且解决了

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

对于原始问题中的Dockerfile,它应类似于:

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

5
这是一种解决方法,但不是一个很好的解决方法–使用来解释脚本sh,而忽略了shebang的解释器规范;所以如果它使用了#!/bin/bash,说必须要使用bash来解释,那将被忽略,它就会用解释sh代替,从而不允许的语言特性,比如[[ ]],阵列等
查尔斯·达菲

我已经使用了您的方法,并且有效。也许dos2unix也能解决问题
Wakan Tanka

1

如果使用DockerFile,则可以简单地将权限添加为bash的命令行参数:

docker run -t <image>  /bin/bash -c "chmod +x /usr/src/app/docker-entrypoint.sh; /usr/src/app/docker-entrypoint.sh"

1

这是我回答之前两年提出的一个老问题,无论如何我都会发布对我有用的东西。

在我的工作目录中,我有两个文件: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

通过将容器外部的文件设置为可执行文件chmod 700 provision.sh然后运行,我能够使Docker容器中的文件可执行docker build .

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.