docker entrypoint executando script bash obtém “permissão negada”


122

Estou tentando encaixar meu aplicativo node.js. Quando o contêiner for criado, quero que ele execute um git clonee, em seguida, inicie o servidor de nó. Portanto, coloquei essas operações em um script .sh. E execute o script como um único comando no 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"] 

Meu docker-entrypoint.sh se parece com isto:

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

/usr/bin/node server.js

Depois de construir esta imagem e executar:

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

Estou entendendo:

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

Eu despejo no contêiner e a permissão de docker-entrypoint.sh é:

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

três questões:

  1. Meu script bash tem sintaxe errada?

  2. Como altero a permissão de um arquivo bash antes de adicioná-lo a uma imagem?

  3. Qual é a melhor maneira de executar vários comandos git no entrypoint sem usar um script bash?

Obrigado.


Precisamos ver as permissões do arquivo para responder a esta pergunta.
— Charles Duffy de

BTW, se este for um script bash , não um script sh , uma .shextensão deixa uma impressão enganosa sobre quais intérpretes podem executá-la. Você pode considerar tirar isso - não é convencional que os comandos do UNIX tenham extensões (você não executa ls.elf, por exemplo).
— Charles Duffy de

Podemos execuma concha assim? não precisaria do bashprefixo.
— Jean-François Fabre

@ Jean-FrançoisFabre, o que exatamente você quer dizer com sua pergunta? (Não entendo o que "exec um shell dessa maneira" significa - o que é "dessa forma" neste contexto?)
— Charles Duffy

2
A propósito, pergunta boba - as permissões do script estão corretas antes de você adicioná-las à imagem?
— Charles Duffy de

Respostas:


183
  1. "Permissão negada" impede o seu script de ser invocado em tudo . Portanto, a única sintaxe possivelmente pertinente é a da primeira linha (o "shebang"), que deve ser semelhante a #!/usr/bin/env bash, ou #!/bin/bashou semelhante, dependendo do layout do sistema de arquivos de destino.

  2. Provavelmente as permissões do sistema de arquivos não foram definidas para permitir a execução. Também é possível que o shebang faça referência a algo que não é executável, mas isso é muito menos provável.

  3. Suscitado pela facilidade de reparar os problemas anteriores.


A simples leitura de

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

... é que o script não está marcado como executável.

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

resolverá isso dentro do contêiner. Como alternativa, você pode garantir que a cópia local referenciada pelo Dockerfile seja executável e, em seguida, usar COPY(que é explicitamente documentado para reter metadados).


Eu acho que você está certo. Devo usar COPY em vez disso. Mas parece que ainda preciso alterar a permissão após copiar o script bash.
— Calvin Hu de

Eu tenho um arquivo phar que cria scripts .bash com base em um comando e os remove depois de concluídos. Portanto, a necessidade de volumes compartilhados para ter a permissão de execução definida é algo com que ainda estou lutando.
— raupie

@raupie, se você deseja executar um script a partir de um ponto de montagem com o noexecsinalizador, execute em bash yourscriptvez de ./yourscript.
— Charles Duffy

1
Eu não entendo, quando eu executo docker buildo contêiner imediato funciona bem. Mas quando eu faço docker run, ele lança tal erro. Parece um recipiente intermediário mágico que tenho.
— Tiina

46

Um arquivo executável precisa ter permissões para executar definidas antes que você possa executá-lo.

Na máquina em que você está criando a imagem do docker (não dentro da própria imagem do docker), tente executar:

ls -la path/to/directory

A primeira coluna da saída do seu executável (neste caso docker-entrypoint.sh) deve ter os bits executáveis ​​definidos da seguinte forma:

-rwxrwxr-x

Se não, tente:

chmod +x docker-entrypoint.sh

e, em seguida, crie sua imagem docker novamente.

O Docker usa seu próprio sistema de arquivos, mas copia tudo (incluindo bits de permissão) dos diretórios de origem.


13
chmod +x docker-entrypoint.shno host é realmente a solução recomendada, pois é muito mais simples do que alterar o seu Dockerfile.
— jotrocken

16

Eu enfrentei o mesmo problema e foi resolvido por

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

Para o Dockerfile na pergunta original, deveria ser assim:

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

5
Esta é uma solução alternativa, mas não excelente - interpreta o script com sh, ignorando a especificação de um interpretador; portanto, se usar #!/bin/bash, dizendo que deseja ser interpretado com bash, isso será ignorado e será interpretado com sh, portanto, não permitindo recursos de linguagem como [[ ]]matrizes, etc.
— Charles Duffy

Usei sua abordagem e funcionou. Talvez também dos2unix
— funcione

1

Se você não usa DockerFile, pode simplesmente adicionar permissão como argumento de linha de comando do bash:

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

1

Esta é uma pergunta antiga feita dois anos antes da minha resposta, vou postar o que funcionou para mim de qualquer maneira.

Em meu diretório de trabalho, tenho dois arquivos: 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

Consegui tornar o arquivo executável no contêiner do docker definindo o arquivo fora do contêiner como executável chmod 700 provision.she em execução docker build ..

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.