il punto di ingresso docker che esegue lo script bash ottiene "permesso negato"


122

Sto provando a dockerizzare la mia app node.js. Quando il contenitore viene creato, desidero che esegua git clonee quindi avvii il server del nodo. Pertanto inserisco queste operazioni in uno script .sh. Ed esegui lo script come un singolo comando in 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"] 

Il mio docker-entrypoint.sh ha questo aspetto:

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

/usr/bin/node server.js

Dopo aver costruito questa immagine ed eseguire:

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

Sto ottenendo:

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

Eseguo la shell nel container e il permesso di docker-entrypoint.sh è:

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

tre domande:

  1. Il mio script bash ha una sintassi sbagliata?

  2. Come posso modificare l'autorizzazione di un file bash prima di aggiungerlo a un'immagine?

  3. Qual è il modo migliore per eseguire più comandi git nel punto di ingresso senza utilizzare uno script bash?

Grazie.


Dobbiamo vedere le autorizzazioni del file per poter rispondere a questa domanda.
Charles Duffy

A proposito, se questo è uno script bash , non uno script sh , .shun'estensione lascia un'impressione fuorviante su quali interpreti possono eseguirlo. Potresti considerare di toglierlo: non è convenzionale che i comandi UNIX abbiano estensioni (non esegui ls.elf, ad esempio).
Charles Duffy

Possiamo execun guscio in questo modo? non sarebbe necessario il bashprefisso.
Jean-François Fabre

@ Jean-FrançoisFabre, cosa intendi esattamente con la tua domanda? (Non capisco cosa significhi "eseguire una shell in quel modo" - cosa significa "in quel modo" in questo contesto?)
Charles Duffy

2
Domanda stupida, a proposito: i permessi dello script sono corretti prima di aggiungerli all'immagine?
Charles Duffy

Risposte:


185
  1. "Permesso negato" impedisce lo script da essere invocato a tutti . Pertanto, l'unica sintassi che potrebbe essere pertinente è quella della prima riga ("shebang"), che dovrebbe essere simile a #!/usr/bin/env bash, o #!/bin/bash, o simile a seconda del layout del filesystem di destinazione.

  2. Molto probabilmente i permessi del filesystem non sono stati impostati per consentire l'esecuzione. È anche possibile che lo shebang faccia riferimento a qualcosa che non è eseguibile, ma questo è molto meno probabile.

  3. Motivato dalla facilità di riparare i problemi precedenti.


La semplice lettura di

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

... è che lo script non è contrassegnato come eseguibile.

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

affronterà questo problema all'interno del contenitore. In alternativa, puoi assicurarti che la copia locale a cui fa riferimento il Dockerfile sia eseguibile e quindi utilizzarla COPY(che è documentata esplicitamente per conservare i metadati).


Penso che tu abbia ragione. Dovrei invece usare COPY. Ma sembra che sia ancora necessario modificare l'autorizzazione dopo aver COPIATO lo script bash.
Calvin Hu

Ho un file phar che crea script .bash in base a un comando e quindi li rimuove una volta completati. Quindi la necessità che i volumi condivisi abbiano il set di autorizzazioni di esecuzione è qualcosa con cui sto ancora lottando.
raupie

@raupie, se vuoi eseguire uno script da un punto di montaggio con il noexecflag, esegui bash yourscriptinvece di ./yourscript.
Charles Duffy

1
Non capisco, quando docker buildeseguo il contenitore immediato funziona bene. Ma quando lo faccio docker run, genera un tale errore. Sembra un magico contenitore intermedio che ho.
Tiina

46

Un file eseguibile deve disporre delle autorizzazioni per eseguire il set prima di poterlo eseguire.

Nella macchina in cui stai creando l'immagine docker (non all'interno dell'immagine docker stessa) prova a eseguire:

ls -la path/to/directory

La prima colonna dell'output per il tuo eseguibile (in questo caso docker-entrypoint.sh) dovrebbe avere i bit eseguibili impostati qualcosa come:

-rwxrwxr-x

In caso contrario, prova:

chmod +x docker-entrypoint.sh

e quindi crea nuovamente la tua immagine finestra mobile.

Docker utilizza il proprio file system ma copia tutto (inclusi i bit di autorizzazione) dalle directory di origine.


13
chmod +x docker-entrypoint.shsu tzhe host è effettivamente la soluzione consigliata, in quanto è molto più semplice che cambiare il tuo Dockerfile.
jotrocken

17

Ho affrontato lo stesso problema e è stato risolto da

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

Per il Dockerfile nella domanda originale dovrebbe essere come:

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

5
Questa è una soluzione alternativa, ma non eccezionale: interpreta la sceneggiatura con sh, ignorando la specifica di un interprete nel suo shebang; quindi se usa #!/bin/bash, dicendo che vuole essere interpretato con bash, verrà ignorato e sarà interpretato con shinvece, disabilitando così le funzionalità del linguaggio come [[ ]], array, ecc.
Charles Duffy

Ho usato il tuo approccio e ha funzionato. Forse anche dos2unix fa il trucco
Wakan Tanka

1

Se non utilizzi DockerFile, puoi semplicemente aggiungere l'autorizzazione come argomento della riga di comando della bash:

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

1

Questa è una vecchia domanda posta due anni prima della mia risposta, pubblicherò comunque ciò che ha funzionato per me.

Nella mia directory di lavoro ho due file: Dockerfile e 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

Sono stato in grado di rendere eseguibile il file nel contenitore docker impostando il file all'esterno del contenitore come eseguibile e chmod 700 provision.shquindi eseguendolo docker build ..

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.