El punto de entrada de Docker que ejecuta el script bash obtiene "permiso denegado"

122

Estoy tratando de dockerizar mi aplicación node.js. Cuando se construye el contenedor, quiero que se ejecute git cloney luego inicie el servidor de nodo. Por lo tanto, pongo estas operaciones en un script .sh. Y ejecute el script como un solo comando en 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"] 

Mi docker-entrypoint.sh se ve así:

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

/usr/bin/node server.js

Después de construir esta imagen y ejecutar:

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

Me estoy poniendo:

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

Entro en el contenedor y el permiso de docker-entrypoint.sh es:

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

tres preguntas:

  1. ¿Mi script bash tiene una sintaxis incorrecta?

  2. ¿Cómo cambio el permiso de un archivo bash antes de agregarlo a una imagen?

  3. ¿Cuál es la mejor manera de ejecutar múltiples comandos git en el punto de entrada sin usar un script bash?

Gracias.

Calvin Hu
fuente
Necesitamos ver los permisos del archivo para poder responder esta pregunta.
Charles Duffy
Por cierto, si se trata de un script bash , no un script sh , una .shextensión deja una impresión engañosa sobre qué intérpretes pueden ejecutarlo. Podría considerar eliminar eso; no es convencional que los comandos de UNIX tengan extensiones (no se ejecutan ls.elf, por ejemplo).
Charles Duffy
¿Podemos execun caparazón de esa manera? ¿no necesitaría el bashprefijo?
Jean-François Fabre
@ Jean-FrançoisFabre, ¿qué quiere decir exactamente con su pregunta? (No entiendo qué significa "ejecutivo a shell de esa manera", ¿qué significa "de esa manera" en este contexto?)
Charles Duffy
2
Pregunta tonta, por cierto: ¿son correctos los permisos del script antes de agregarlos a la imagen?
Charles Duffy

Respuestas:

183
  1. "Permiso denegado" impide que la secuencia de comandos que se invoque en absoluto . Por lo tanto, la única sintaxis que podría ser pertinente es la de la primera línea (el "shebang"), que debería verse como #!/usr/bin/env bash, o #!/bin/bash, o similar dependiendo de la distribución del sistema de archivos de su objetivo.

  2. Lo más probable es que los permisos del sistema de archivos no estén configurados para permitir la ejecución. También es posible que el shebang haga referencia a algo que no es ejecutable, pero esto es mucho menos probable.

  3. Motivado por la facilidad de reparar los problemas anteriores.


La simple lectura de

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

... es que el script no está marcado como ejecutable.

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

abordará esto dentro del contenedor. Alternativamente, puede asegurarse de que la copia local a la que hace referencia el Dockerfile sea ejecutable y luego usar COPY(que está explícitamente documentada para retener metadatos).

Charles Duffy
fuente
Creo que tienes razón. Debería usar COPY en su lugar. Pero parece que todavía necesito cambiar el permiso después de COPIAR el script bash.
Calvin Hu
Tengo un archivo phar que crea scripts .bash basados ​​en un comando y luego los elimina una vez que se han completado. Entonces, la necesidad de que los volúmenes compartidos tengan el permiso de ejecución establecido es algo con lo que todavía estoy luchando.
raupie
@raupie, si desea ejecutar un script desde un punto de montaje con la noexecbandera, ejecute en bash yourscriptlugar de ./yourscript.
Charles Duffy
1
No lo entiendo, cuando ejecuto docker buildel contenedor inmediato funciona bien. Pero cuando lo hago docker run, arroja tal error. Parece un contenedor intermedio mágico que tengo.
Tiina
46

Un archivo ejecutable debe tener permisos de ejecución establecidos antes de que pueda ejecutarlo.

En su máquina donde está creando la imagen de la ventana acoplable (no dentro de la imagen de la ventana acoplable en sí) intente ejecutar:

ls -la path/to/directory

La primera columna de la salida de su ejecutable (en este caso docker-entrypoint.sh) debe tener los bits ejecutables configurados de forma similar a:

-rwxrwxr-x

Si no, intente:

chmod +x docker-entrypoint.sh

y luego vuelva a construir su imagen de Docker.

Docker usa su propio sistema de archivos, pero copia todo (incluidos los bits de permisos) de los directorios de origen.

Inicio Sami
fuente
13
chmod +x docker-entrypoint.shen tzhe host es en realidad la solución recomendada, ya que es mucho más simple que cambiar su Dockerfile.
jotrocken
16

Enfrenté el mismo problema y lo resolvió

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

Para el Dockerfile en la pregunta original debería ser como:

ENTRYPOINT ["sh", "/usr/src/app/docker-entrypoint.sh"]
Saurabhcdt
fuente
5
Esta es una solución alternativa, pero no excelente: interpreta el guión con sh, ignorando la especificación de intérprete de su shebang; así que si usa #!/bin/bash, diciendo que quiere ser interpretado con bash, eso será ignorado y será interpretado en su shlugar, por lo que no se permitirán características del lenguaje como [[ ]], matrices, etc.
Charles Duffy
He utilizado su enfoque y funcionó. Quizás también dos2unix haga el truco
Wakan Tanka
1

Si no usa DockerFile, simplemente puede agregar permiso como argumento de línea de comando de bash:

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

Esta es una vieja pregunta hecha dos años antes de mi respuesta, de todos modos voy a publicar lo que funcionó para mí.

En mi directorio de trabajo tengo dos archivos: 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

Pude hacer que el archivo en el contenedor de la ventana acoplable fuera ejecutable configurando el archivo fuera del contenedor como ejecutable y chmod 700 provision.shluego ejecutándose docker build ..

BradChesney79
fuente