นักเทียบท่า: ไม่พบไฟล์ปฏิบัติการใน $ PATH


216

ฉันมีภาพนักเทียบท่าที่ติดตั้งgruntแต่เมื่อฉันพยายามเรียกใช้ฉันได้รับข้อผิดพลาด:

Error response from daemon: Cannot start container foo_1: \
    exec: "grunt serve": executable file not found in $PATH

ถ้าฉันใช้ bash ในโหมดอินเตอร์แอคทีฟgruntก็สามารถใช้ได้

ผมทำอะไรผิดหรือเปล่า?

นี่คือ Dockerfile ของฉัน:

# https://registry.hub.docker.com/u/dockerfile/nodejs/ (builds on ubuntu:14.04)
FROM dockerfile/nodejs

MAINTAINER My Name, me@email.com

ENV HOME /home/web
WORKDIR /home/web/site

RUN useradd web -d /home/web -s /bin/bash -m

RUN npm install -g grunt-cli
RUN npm install -g bower

RUN chown -R web:web /home/web
USER web

RUN git clone https://github.com/repo/site /home/web/site

RUN npm install
RUN bower install --config.interactive=false --allow-root

ENV NODE_ENV development

# Port 9000 for server
# Port 35729 for livereload
EXPOSE 9000 35729
CMD ["grunt"]

คุณลองสร้างนักเทียบท่าได้CMD gruntไหม หรือคุณอาจลองใช้คำสั่ง grunt โดยผ่านเส้นทางแบบเต็ม?
mgaido

@ mark91 โปรดที่คุณสามารถทำอย่างละเอียดในสิ่งที่คุณขออีกครั้งโดยใช้การสร้างCMD grunt?คุณหมายถึงวาง["และ"]?
Steve Lorimer

เพิ่งลอง - และใช้งานได้ - ขอบคุณ! ดังนั้นสำหรับคนอื่นที่เข้ามาเปลี่ยนCMD ["grunt"]เป็นCMD grunt
Steve Lorimer

10
นี่เป็นเพราะถ้าคุณCMD ["grunt"]ใช้เชลล์อื่นเพื่อรันคำสั่งดังนั้นในเชลล์ $ PATH นั้นไม่น่าจะถูกตั้งค่า
mgaido

คำตอบ:


198

เมื่อคุณใช้รูปแบบ exec สำหรับคำสั่ง (เช่นCMD ["grunt"]อาร์เรย์ JSON พร้อมเครื่องหมายคำพูดคู่) มันจะถูกเรียกใช้โดยไม่มีเชลล์ ซึ่งหมายความว่าตัวแปรสภาพแวดล้อมส่วนใหญ่จะไม่ปรากฏ

ถ้าคุณระบุคำสั่งของคุณเป็นสตริงปกติ (เช่นCMD grunt) แล้วสตริงหลังจากที่จะมีการดำเนินการด้วยCMD/bin/sh -c

ข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้สามารถใช้ได้ในส่วน CMD ของการอ้างอิง Dockerfile


2
นี่คือลิงค์ไปยังส่วน CMD ของdocs.docker.com/engine/reference/builder/#cmd
Calvin

แก้คำถามโง่นี้ แต่คุณจะรันคำสั่ง linux โดยไม่ใช้เชลล์ได้อย่างไร สิ่งที่เทียบเท่ากับการทำเช่นนี้บนเครื่อง linux (ไม่ได้ใช้นักเทียบท่า)?
wisbucky

1
เพื่อที่จะตอบคำถามของฉันเองก็มีความคล้ายคลึงกับการทำหรือsudo set (exec set)สิ่งเหล่านี้จะล้มเหลวเนื่องจากพวกเขาดำเนินการคำสั่งโดยไม่มีเชลล์ (และsetเป็นเชลล์ในตัว) อย่างไรก็ตามsudo lsและ(exec ls)จะทำงานเพราะเป็นไฟล์ไบนารีที่เกิดขึ้นจริงls /bin/ls
wisbucky

315

นี่เป็นผลลัพธ์แรกใน google เมื่อฉันวางข้อความแสดงข้อผิดพลาดและเป็นเพราะข้อโต้แย้งของฉันไม่เป็นไปตามที่กำหนด

ชื่อคอนเทนเนอร์ต้องอยู่หลังอาร์กิวเมนต์ทั้งหมด

แย่:

docker run <container_name> -v $(pwd):/src -it

ดี:

docker run -v $(pwd):/src -it <container_name>

132
หากคุณอ่านเอกสารอย่างละเอียดก่อนที่จะเริ่มเขียนโค้ดคุณจะไม่ทำอะไรเลย เมื่อคุณซื้อรถใหม่คุณอ่านคู่มือ 200 หน้าก่อนขับรถกลับบ้านหรือไม่? ไม่และเมื่อมีปัญหาเกี่ยวกับรถยนต์ของคุณคุณเป็น google ก่อนหรือคุณได้รับคู่มือหรือไม่ นี่เป็นเหตุผลทั้งหมดฉันสามารถจินตนาการได้ว่าทุกคนที่พบว่ามีประโยชน์ แต่ยังไม่ได้คลิกปุ่ม upvote! สิ่งที่ไม่สมเหตุสมผลก็คือคำตอบที่ไม่เกี่ยวข้องทั้งหมดนี้เป็นผลลัพธ์แรกของ Google สำหรับข้อความแสดงข้อผิดพลาดนี้หรือ cli นักเทียบท่านั้นไม่ได้ใช้งานง่ายและไม่สามารถให้อภัยได้ ไชโย
sarink

8
ในสคริปต์จำนวนมากลำดับของแฟล็กไม่สำคัญดังนั้นฉันสามารถเห็นได้ว่าทำไมสิ่งนี้ถึงเกิดขึ้นได้กับทุกคน คำตอบมีประโยชน์มาก จำเป็นต้องพูดว่าข้อความแสดงข้อผิดพลาดจากนักเทียบท่าไม่มีประโยชน์เลย
marios

9
ว้าวฉันจะดิ้นรนซักพักหนึ่งถ้าไม่ใช่สำหรับคำตอบนี้ ทำไมไม่ UNIX มีมาตรฐานและมีความยืดหยุ่นและมีประสิทธิภาพ CLI อาร์กิวเมนต์ parser แล้ว ... ?
lleaff

1
นี่คือปัญหาสำหรับฉัน การใส่ชื่อคอนเทนเนอร์ในตอนท้ายดูเหมือนจะใช้ได้
Rob Segal

3
ฉันเข้าใจผิดโดยคำตอบที่ยอมรับต้องการที่จะเขียนของฉันเอง แต่ดูเหมือนว่ามันอยู่ที่นี่แล้ว ดังนั้นฉันสามารถยืนยันได้ว่านี่จะช่วยแก้ปัญหาได้ ...
Arturas M

24

ฉันพบปัญหาเดียวกัน ฉันทำต่อไปนี้:

docker run -ti devops -v /tmp:/tmp /bin/bash

เมื่อฉันเปลี่ยนมันเป็น

docker run -ti -v /tmp:/tmp devops /bin/bash

มันใช้งานได้ดี


1
มันใช้งานได้สำหรับผู้ชายฉัน แต่ฉันไม่เข้าใจการใช้-vที่นี่ -vคือการผูกโวลุ่ม (ตามที่อธิบายไว้docker run --help | grep "\-v") สำหรับฉันฉันได้/tmpติดตั้งในFile Sharing(การตั้งค่านักเทียบท่า) แล้วทำไมฉันต้องใช้อีกครั้ง?
Ahmad

12

มีสาเหตุที่เป็นไปได้หลายประการสำหรับข้อผิดพลาดเช่นนี้

ในกรณีของฉันมันเป็นเพราะไฟล์ปฏิบัติการ ( docker-entrypoint.shจากGhost blog Dockerfile ) ขาดโหมดไฟล์ปฏิบัติการหลังจากที่ฉันดาวน์โหลด

สารละลาย: chmod +x docker-entrypoint.sh


นี่คือความคิดเห็นที่ชี้ให้ฉันเห็นคำตอบที่ถูกต้อง ฉันต้องคัดลอกไฟล์แล้ว chmod มัน
Beyondtheteal

7

คอนเทนเนอร์นักเทียบท่าอาจถูกสร้างขึ้นโดยไม่มีเชลล์ (เช่นhttps://github.com/fluent/fluent-bit-docker-image/issues/19 )

ในกรณีนี้คุณสามารถคัดลอกเชลล์ที่รวบรวมไว้แบบสแตติกและดำเนินการได้เช่น

docker create --name temp-busybox busybox:1.31.0
docker cp temp-busybox:/bin/busybox busybox
docker cp busybox mycontainerid:/busybox
docker exec -it mycontainerid /bin/busybox sh

4

ด้วยเหตุผลบางอย่างฉันได้รับข้อผิดพลาดนั้นยกเว้นว่าฉันเพิ่มตัวขยาย "bash" แม้การเพิ่ม "#! / bin / bash" ที่ด้านบนของไฟล์จุดเข้าใช้งานของฉันก็ไม่ได้ช่วยอะไร

ENTRYPOINT [ "bash", "entrypoint.sh" ]

@SteveLorimer ใช่ ฉันได้COPYแล้วRUN chmod +x /compile_nibbler.shก่อนที่จะโทรจุดเข้า
Beyondtheteal

1

ฉันมีปัญหาเดียวกันหลังจาก googling มากมายฉันไม่สามารถหาวิธีแก้ไขได้

ทันใดนั้นฉันก็สังเกตเห็นความผิดพลาดโง่ ๆ ของฉัน :)

ดังที่กล่าวไว้ในเอกสารส่วนสุดท้ายdocker runคือคำสั่งที่คุณต้องการเรียกใช้และอาร์กิวเมนต์หลังจากโหลดคอนเทนเนอร์

ไม่ใช่ชื่อคอนเทนเนอร์ !!!

นั่นเป็นความผิดพลาดที่น่าอายของฉัน

ด้านล่างฉันให้รูปภาพของบรรทัดคำสั่งของคุณแก่คุณเพื่อดูสิ่งที่ฉันทำผิด

และนี่คือการแก้ไขเป็นที่กล่าวถึงในเอกสาร

ป้อนคำอธิบายรูปภาพที่นี่


-7

เพื่อให้มันทำงานเพิ่มการอ้างอิงอ่อนไปยัง / usr / bin:

ln -s $ (โหนดใด) / usr / bin / node

ln -s $ (npm) / usr / bin / npm


1
โปรดเพิ่มคำอธิบายเกี่ยวกับวิธีที่จะช่วยเขา
แมทธิวส์ซันนี่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.