punkt wejścia docker, w którym uruchomiony jest skrypt bash, otrzymuje „odmowę uprawnień”

122

Próbuję dokerować moją aplikację node.js. Po zbudowaniu kontenera chcę, aby uruchamiał, git clonea następnie uruchamiał serwer węzłów. Dlatego umieściłem te operacje w skrypcie .sh. I uruchom skrypt jako pojedyncze polecenie w 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"] 

Mój docker-entrypoint.sh wygląda tak:

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

/usr/bin/node server.js

Po zbudowaniu tego obrazu i uruchomieniu:

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

Otrzymuję:

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

Otwieram do kontenera, a zgoda docker-entrypoint.sh to:

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

trzy pytania:

  1. Czy mój skrypt bash ma nieprawidłową składnię?

  2. Jak zmienić uprawnienia do pliku bash przed dodaniem go do obrazu?

  3. Jaki jest najlepszy sposób uruchamiania wielu poleceń git w punkcie wejścia bez użycia skryptu bash?

Dzięki.

Calvin Hu
źródło
Musimy zobaczyć uprawnienia do plików, aby móc odpowiedzieć na to pytanie.
Charles Duffy,
Przy okazji, jeśli jest to skrypt bash , a nie skrypt sh , .shrozszerzenie pozostawia mylące wrażenie na temat tego, którzy tłumacze mogą je wykonać. Możesz rozważyć usunięcie tego - nie jest konwencjonalne, że polecenia UNIX mają rozszerzenia ( ls.elfna przykład nie uruchamiasz ).
Charles Duffy,
Czy możemy execw ten sposób mieć muszlę? czy nie potrzebowałby bashprzedrostka.
Jean-François Fabre
@ Jean-FrançoisFabre, co dokładnie masz na myśli mówiąc o swoim pytaniu? (Nie rozumiem, co oznacza „wykonaj powłokę w ten sposób” - co oznacza „w ten sposób” w tym kontekście?)
Charles Duffy,
2
Swoją drogą, głupie pytanie - czy uprawnienia skryptu są poprawne przed dodaniem ich do obrazu?
Charles Duffy,

Odpowiedzi:

185
  1. „Odmowa uprawnień” całkowicie uniemożliwia wywołanie skryptu . Zatem jedyną składnią, która może być odpowiednia, jest składnia pierwszej linii („shebang”), która powinna wyglądać podobnie #!/usr/bin/env bashlub #!/bin/bashlub podobnie w zależności od układu systemu plików celu.

  2. Najprawdopodobniej uprawnienia systemu plików nie są ustawione na zezwalanie na wykonywanie. Możliwe jest również, że shebang odwołuje się do czegoś, co nie jest wykonywalne, ale jest to znacznie mniej prawdopodobne.

  3. Zepsuty przez łatwość naprawy poprzednich problemów.


Proste czytanie

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

... polega na tym, że skrypt nie jest oznaczony jako wykonywalny.

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

zajmie się tym w kontenerze. Alternatywnie możesz upewnić się, że lokalna kopia, do której odwołuje się plik Dockerfile, jest wykonywalna , a następnie użyć COPY(co jest jawnie udokumentowane w celu zachowania metadanych).

Charles Duffy
źródło
Myślę, że masz rację. Powinienem zamiast tego użyć COPY. Ale wygląda na to, że po skopiowaniu skryptu bash nadal muszę zmienić uprawnienia.
Calvin Hu
Mam plik phar, który tworzy skrypty .bash na podstawie polecenia, a następnie usuwa je po zakończeniu. Tak więc potrzeba, aby udostępnione woluminy miały ustawione uprawnienia do wykonywania, jest czymś, z czym wciąż się zmagam.
raupie
@raupie, jeśli chcesz uruchomić skrypt poza punktem montowania z noexecflagą, uruchom bash yourscriptzamiast ./yourscript.
Charles Duffy
1
Nie rozumiem, kiedy uruchomię docker buildpojemnik pośredni działa dobrze. Ale kiedy to robię docker run, wyrzuca taki błąd. Wygląda na to, że mam magiczny pojemnik pośredni.
Tiina
46

Plik wykonywalny musi mieć ustawione uprawnienia do wykonywania, zanim będzie można go wykonać.

Na komputerze, na którym tworzysz obraz Dockera (a nie wewnątrz samego obrazu Dockera), spróbuj uruchomić:

ls -la path/to/directory

Pierwsza kolumna danych wyjściowych dla twojego pliku wykonywalnego (w tym przypadku docker-entrypoint.sh) powinna mieć ustawione bity pliku wykonywalnego, takie jak:

-rwxrwxr-x

Jeśli nie, spróbuj:

chmod +x docker-entrypoint.sh

a następnie ponownie utwórz obraz Dockera.

Docker używa własnego systemu plików, ale kopiuje wszystko (w tym bity uprawnień) z katalogów źródłowych.

Sami Start
źródło
13
chmod +x docker-entrypoint.shna hoście jest w rzeczywistości zalecanym rozwiązaniem, ponieważ jest znacznie prostsze niż zmiana pliku Dockerfile.
jotrocken
17

Napotkałem ten sam problem i został on rozwiązany przez

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

Dla pliku Dockerfile w oryginalnym pytaniu powinno wyglądać następująco:

ENTRYPOINT ["sh", "/usr/src/app/docker-entrypoint.sh"]
Saurabhcdt
źródło
5
Jest to obejście, ale niezbyt dobre - interpretuje skrypt z sh, ignorując specyfikację interpretera zawartą w shebang; więc jeśli używa #!/bin/bash, mówiąc, że chce być interpretowane z bash, że będą ignorowane i będzie ona być interpretowane shw zamian, a więc wykluczający możliwości językowych jak [[ ]], tablic, itp
Charles Duffy
Wykorzystałem twoje podejście i zadziałało. Może też dos2unix załatwia sprawę
Wakan Tanka
1

Jeśli nie używasz DockerFile, możesz po prostu dodać uprawnienie jako argument wiersza poleceń bash:

docker run -t <image>  /bin/bash -c "chmod +x /usr/src/app/docker-entrypoint.sh; /usr/src/app/docker-entrypoint.sh"
betontalpfa
źródło
1

To jest stare pytanie zadane dwa lata przed moją odpowiedzią, i tak zamierzam opublikować, co zadziałało.

W moim katalogu roboczym mam dwa pliki: Dockerfile i 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

Mogłem uczynić plik w kontenerze Dockera wykonywalnym, ustawiając plik poza kontenerem jako wykonywalny, chmod 700 provision.sha następnie uruchamiając docker build ..

BradChesney79
źródło