точка входа в докер, на которой запущен сценарий bash, получает сообщение «Отказано в разрешении»

122

Я пытаюсь докеризовать свое приложение node.js. Когда контейнер построен, я хочу, чтобы он запустил, 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. Какой лучший способ запустить несколько команд git в точке входа без использования сценария bash?

Спасибо.

Кальвин Ху
источник
Нам нужно увидеть права доступа к файлам, чтобы ответить на этот вопрос.
Чарльз Даффи,
Кстати, если это сценарий bash , а не сценарий sh , .shрасширение оставляет неверное представление о том, какие интерпретаторы могут его выполнить. Вы можете подумать о том, чтобы убрать это - для команд UNIX не принято иметь расширения (например, вы не запускаете ls.elf).
Чарльз Даффи,
Можно ли так execоболочку? не нужен ли ему bashпрефикс.
Жан-Франсуа Фабр
@ Jean-FrançoisFabre, что именно вы имеете в виду под своим вопросом? (Я не понимаю, что означает «выполнить оболочку таким образом» - что «так» в этом контексте?)
Чарльз Даффи
2
Между прочим, глупый вопрос - правильные ли разрешения скрипта перед добавлением их в изображение?
Чарльз Даффи,

Ответы:

185
  1. «Permission denied» вообще запрещает запуск вашего скрипта . Таким образом, единственный синтаксис, который может быть уместным, - это синтаксис первой строки («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.
Calvin Hu
У меня есть файл phar, который создает сценарии .bash на основе команды, а затем удаляет их после завершения. Так что необходимость для общих томов иметь набор разрешений на выполнение - это то, с чем я все еще борюсь.
raupie 03
@raupie, если вы хотите запустить скрипт из точки монтирования с noexecфлагом, запустите bash yourscriptвместо ./yourscript.
Чарльз Даффи
1
Я не понимаю, когда я запускаю docker buildнемедленный контейнер, он работает нормально. Но когда я это делаю docker run, выдает такую ​​ошибку. Похоже на волшебный промежуточный контейнер, который у меня есть.
Tiina
46

У исполняемого файла должны быть установлены разрешения на выполнение, прежде чем вы сможете его выполнить.

На вашем компьютере, на котором вы создаете образ докера (не внутри самого образа докера), попробуйте запустить:

ls -la path/to/directory

В первом столбце вывода для вашего исполняемого файла (в данном случае docker-entrypoint.sh) должны быть установлены биты исполняемого файла, например:

-rwxrwxr-x

Если нет, попробуйте:

chmod +x docker-entrypoint.sh

а затем снова создайте образ докера.

Docker использует собственную файловую систему, но копирует все (включая биты разрешений) из исходных каталогов.

Сами Старт
источник
13
chmod +x docker-entrypoint.shна tzhe host на самом деле является рекомендуемым решением, так как это намного проще, чем изменить ваш Dockerfile.
jotrocken
18

Я столкнулся с той же проблемой, и она была решена

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

Для Dockerfile в исходном вопросе это должно быть так:

ENTRYPOINT ["sh", "/usr/src/app/docker-entrypoint.sh"]
Saurabhcdt
источник
5
Это обходной путь, но не лучший - он интерпретирует скрипт с помощью sh, игнорируя спецификацию интерпретатора, указанную в его шебанге; поэтому, если он использует #!/bin/bash, говоря, что он хочет интерпретироваться с помощью bash, это будет проигнорировано и будет интерпретировано shвместо этого, тем самым запретив языковые функции, такие как [[ ]]массивы и т. д.
Чарльз Даффи
Я использовал ваш подход, и он сработал. Возможно, вам поможет dos2unix
Вакан Танка
2

Если вы не используете DockerFile, вы можете просто добавить разрешение в качестве аргумента командной строки bash:

docker run -t <image>  /bin/bash -c "chmod +x /usr/src/app/docker-entrypoint.sh; /usr/src/app/docker-entrypoint.sh"
betontalpfa
источник
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 build ..

BradChesney79
источник