điểm nhập docker đang chạy tập lệnh bash bị "từ chối quyền"


122

Tôi đang cố gắng hoàn thiện ứng dụng node.js của mình. Khi vùng chứa được tạo, tôi muốn nó chạy a git clonevà sau đó khởi động máy chủ nút. Do đó, tôi đặt các thao tác này trong một tập lệnh .sh. Và chạy tập lệnh dưới dạng một lệnh duy nhất trong 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 của tôi trông như thế này:

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

/usr/bin/node server.js

Sau khi xây dựng hình ảnh này và chạy:

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

Tôi nhận được:

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

Tôi đưa vào vùng chứa và quyền của docker-entrypoint.sh là:

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

ba câu hỏi:

  1. Tập lệnh bash của tôi có sai cú pháp không?

  2. Làm cách nào để thay đổi quyền của tệp bash trước khi thêm nó vào hình ảnh?

  3. Cách tốt nhất để chạy nhiều lệnh git trong entrypoint mà không sử dụng tập lệnh bash là gì?

Cảm ơn.


Chúng tôi cần xem các quyền của tệp để có thể trả lời câu hỏi này.
Charles Duffy

BTW, nếu đây là một tập lệnh bash , không phải là một tập lệnh sh , thì .shphần mở rộng sẽ để lại ấn tượng sai lệch về việc trình thông dịch có thể thực thi nó. Bạn có thể cân nhắc loại bỏ điều đó - thông thường các lệnh UNIX có phần mở rộng ( ls.elfví dụ như bạn không chạy ).
Charles Duffy

Chúng tôi có thể execmột vỏ theo cách đó? nó sẽ không cần bashtiền tố.
Jean-François Fabre

@ Jean-FrançoisFabre, ý bạn chính xác là câu hỏi của bạn là gì? (Tôi không hiểu những gì "exec một vỏ như vậy" có nghĩa là - gì "như vậy" trong bối cảnh này?)
Charles Duffy

2
Nhân tiện, một câu hỏi ngớ ngẩn - các quyền của tập lệnh có chính xác trước khi bạn thêm chúng vào hình ảnh không?
Charles Duffy

Câu trả lời:


184
  1. "Permission denied" ngăn chặn kịch bản của bạn không bị gọi ở tất cả . Do đó, cú pháp duy nhất có thể phù hợp là cú pháp của dòng đầu tiên ("shebang"), trông giống #!/usr/bin/env bashhoặc #!/bin/bashhoặc tương tự tùy thuộc vào bố cục hệ thống tệp của mục tiêu.

  2. Nhiều khả năng các quyền của hệ thống tệp không được đặt để cho phép thực thi. Nó cũng có thể là tài liệu tham khảo công việc gì đó mà không phải là thực thi, nhưng điều này là xa ít có khả năng.

  3. Được thúc đẩy bởi sự dễ dàng sửa chữa các vấn đề trước đó.


Cách đọc đơn giản của

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

... là tập lệnh không được đánh dấu là có thể thực thi.

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

sẽ giải quyết vấn đề này trong vùng chứa. Ngoài ra, bạn có thể đảm bảo rằng bản sao cục bộ được Dockerfile tham chiếu là có thể thực thi được và sau đó sử dụng COPY(được ghi rõ ràng bằng tài liệu để giữ lại siêu dữ liệu).


Tôi nghĩ bạn đúng. Tôi nên sử dụng COPY để thay thế. Nhưng có vẻ như tôi vẫn cần thay đổi quyền sau khi SAO CHÉP tập lệnh bash.
Calvin Hu

Tôi có một tệp phar tạo các tập lệnh .bash dựa trên một lệnh và sau đó xóa chúng khi chúng đã hoàn thành. Vì vậy, nhu cầu về khối lượng được chia sẻ để có quyền thực thi là điều tôi vẫn đang gặp khó khăn.
raupie

@raupie, nếu bạn muốn chạy tập lệnh ngoài điểm gắn kết với noexeccờ, hãy chạy bash yourscriptthay vì ./yourscript.
Charles Duffy

1
Tôi không thực hiện và, khi tôi chạy docker buildvùng chứa ngay lập tức hoạt động tốt. Nhưng khi tôi làm docker run, nó ném ra lỗi như vậy. Có vẻ như một vật chứa trung gian ma thuật mà tôi có.
Tiina

46

Một tệp thực thi cần có các quyền để thực thi được đặt trước khi bạn có thể thực thi nó.

Trong máy của bạn, nơi bạn đang tạo hình ảnh docker (không phải bên trong chính hình ảnh docker), hãy thử chạy:

ls -la path/to/directory

Cột đầu tiên của đầu ra cho tệp thực thi của bạn (trong trường hợp này là docker-entrypoint.sh) phải có các bit thực thi được đặt giống như:

-rwxrwxr-x

Nếu không, hãy thử:

chmod +x docker-entrypoint.sh

và sau đó xây dựng lại hình ảnh docker của bạn.

Docker sử dụng hệ thống tệp của riêng nó nhưng nó sao chép mọi thứ (bao gồm các bit quyền) từ các thư mục nguồn.


13
chmod +x docker-entrypoint.shtrên máy chủ tzhe thực sự là giải pháp được đề xuất, vì nó đơn giản hơn nhiều so với thay đổi của bạn Dockerfile.
jotrocken

17

Tôi đã gặp phải vấn đề tương tự và nó đã được giải quyết bằng cách

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

Đối với Dockerfile trong câu hỏi ban đầu, nó sẽ giống như sau:

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

5
Đây là một cách giải quyết, nhưng không phải là một giải pháp tuyệt vời - điều này giải thích tập lệnh với sh, bỏ qua đặc điểm kỹ thuật của nó về trình thông dịch; vì vậy nếu nó sử dụng #!/bin/bash, nói rằng nó muốn được giải thích với bash, đó sẽ bị bỏ qua và nó sẽ được giải thích với shthay vào đó, do đó không cho phép các tính năng ngôn ngữ như [[ ]], mảng vv
Charles Duffy

Tôi đã sử dụng cách tiếp cận của bạn và nó hoạt động. Có thể dos2unix cũng làm được thủ thuật
Wakan Tanka

1

Nếu bạn không sử dụng DockerFile, bạn có thể chỉ cần thêm quyền làm đối số dòng lệnh của bash:

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

1

Đây là một câu hỏi cũ được hỏi hai năm trước khi tôi có câu trả lời, tôi sẽ đăng những gì phù hợp với tôi.

Trong thư mục làm việc của tôi, tôi có hai tệp: Dockerfile & cung cấp.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"]

cung cấp.sh:

#!/usr/bin/env bash

yum upgrade

Tôi có thể làm cho tệp trong vùng chứa docker có thể thực thi được bằng cách đặt tệp bên ngoài vùng chứa là tệp thực thi chmod 700 provision.shsau đó chạy docker build ..

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.