doker: nie znaleziono pliku wykonywalnego w $ PATH

216

Mam obraz dokera, który instaluje się grunt, ale gdy próbuję go uruchomić, pojawia się błąd:

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

Jeśli uruchomię bash w trybie interaktywnym, gruntjest dostępny.

Co ja robię źle?

Oto mój plik Docker:

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

MAINTAINER My Name, [email protected]

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"]
Steve Lorimer
źródło
czy możesz spróbować zbudować dokera CMD grunt? A może możesz spróbować wykonać polecenie chrząkania, przechodząc pełną ścieżkę?
mgaido
@ mark91, proszę, czy mógłbyś rozwinąć to, o co prosisz, aby przebudować używając CMD grunt?Czy masz na myśli upuszczenie ["i "]?
Steve Lorimer
Właśnie wypróbowałem - i zadziałało - dzięki! Tak więc dla każdego, kto wejdzie, zmień CMD ["grunt"]naCMD grunt
Steve Lorimer,
10
Jest tak, ponieważ jeśli CMD ["grunt"]używasz innej powłoki do wykonania polecenia, więc w tej powłoce $ PATH prawdopodobnie nie zostanie ustawiona.
mgaido
Zobacz także stackoverflow.com/q/48001082/798677
Ten Brazylijczyk

Odpowiedzi:

198

Kiedy użyjesz formatu exec dla polecenia (np. CMD ["grunt"]Tablica JSON z podwójnymi cudzysłowami), zostanie on wykonany bez powłoki. Oznacza to, że większość zmiennych środowiskowych nie będzie obecnych.

Jeśli określisz swoje polecenie jako ciąg zwykły (np. CMD grunt), To ciąg po nim CMDzostanie wykonany za pomocą /bin/sh -c.

Więcej informacji na ten temat jest dostępnych w sekcji CMD w pliku Dockerfile .

Kevan Ahlquist
źródło
2
To jest link do części CMD referencji docs.docker.com/engine/reference/builder/#cmd
Calvin
Przepraszam za to głupie pytanie, ale jak możesz wykonać komendę Linux bez powłoki? Jaki byłby odpowiednik, aby to zrobić na maszynie z systemem Linux (nie używając dokera)?
wisbucky,
1
Aby odpowiedzieć na moje pytanie, jest to podobne do robienia sudo setlub (exec set). Te zawiodą, ponieważ wykonują polecenia bez powłoki (i setsą wbudowane w powłokę). Jednak sudo lsi (exec ls)będzie działać, ponieważ lsjest to rzeczywisty plik binarny /bin/ls.
wisbucky
315

To był pierwszy wynik w Google, kiedy wkleiłem komunikat o błędzie, a to dlatego, że moje argumenty były nie na miejscu.

Nazwa kontenera musi być po wszystkich argumentach.

Zły:

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

Dobry:

docker run -v $(pwd):/src -it <container_name>
sarink
źródło
132
Jeśli zawsze dokładnie czytasz dokumentację przed rozpoczęciem kodowania, nigdy nie będziesz w stanie nic zrobić. Czy kupując nowy samochód, przeczytałeś 200-stronicową instrukcję, zanim odwiozłeś ją do domu? Nie. A kiedy pojawił się problem z twoim samochodem, czy najpierw google, czy też otrzymałeś instrukcję? Jest to całkowicie rozsądne, mogę sobie tylko wyobrazić wszystkie osoby, które uznały to za przydatne, ale nie kliknęły przycisku upvote! Nieuzasadnione jest to, że ta całkowicie niezwiązana odpowiedź jest pierwszym wynikiem google dla tego komunikatu o błędzie, lub że kliknięcie dokera cli jest nieintuicyjne i bezlitosne. Twoje zdrowie.
sarink
8
W wielu skryptach kolejność flag nie jest ważna, więc rozumiem, dlaczego może się to przytrafić każdemu. Odpowiedź jest bardzo pomocna. Nie trzeba dodawać, że komunikat o błędzie z okna dokowanego w ogóle nie jest użyteczny.
marios
9
Wow, walczyłbym przez chwilę, gdyby nie ta odpowiedź. Dlaczego system UNIX nie ma już standardowego, elastycznego i wydajnego analizatora składni CLI? ...
lleaff
1
To był dla mnie problem. Umieszczanie nazwy kontenera na końcu wydawało się działać
Rob Segal,
3
Zostałem wprowadzony w błąd przez przyjętą odpowiedź, chciałem napisać własną, ale wydaje się, że już tu jest. Mogę więc potwierdzić, że to rozwiązuje problem ...
Arturas M
24

Znalazłem ten sam problem. Zrobiłem następujące:

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

Kiedy zmienię to na

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

to działa dobrze.

Keniee van
źródło
1
To zadziałało dla mnie człowieku, ale nie rozumiem zastosowania -vtutaj. -vjest powiązanie zamontować wolumin (jak opisano w docker run --help | grep "\-v"), dla mnie już mam /tmpzamontowany w File Sharing(Ustawienia Docker), więc dlaczego mam go używać ponownie?
Ahmad
12

Istnieje kilka możliwych przyczyn takiego błędu.

W moim przypadku było to spowodowane tym, że plik wykonywalny ( docker-entrypoint.shz Dockerfile blogu Ghost ) nie ma trybu pliku wykonywalnego po jego pobraniu.

Rozwiązanie: chmod +x docker-entrypoint.sh

Ben Creasy
źródło
To jest komentarz, który wskazał mi właściwą odpowiedź. Musiałem Skopiować plik, a następnie chmod go.
poza theteal
7

Kontener Docker może zostać zbudowany bez powłoki (np. Https://github.com/fluent/fluent-bit-docker-image/issues/19 ).

W takim przypadku możesz skopiować skompilowaną statycznie powłokę i wykonać ją, np

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
Gajus
źródło
4

Z jakiegoś powodu pojawia się ten błąd, chyba że dodam wyjaśnienie „bash”. Nawet dodanie „#! / Bin / bash” na górze mojego pliku punktu wejścia nie pomogło.

ENTRYPOINT [ "bash", "entrypoint.sh" ]
poza theteal
źródło
@ SteveLorimer, tak. Zrobiłem COPYa następnie RUN chmod +x /compile_nibbler.shprzed wywołaniem punktu wejścia.
poza theteal
1

Miałem ten sam problem: po wielu googlowaniach nie mogłem się dowiedzieć, jak to naprawić.

Nagle zauważyłem mój głupi błąd :)

Jak wspomniano w dokumentacji , ostatnia część docker runto polecenie, które chcesz uruchomić, i jego argumenty po załadowaniu kontenera.

NIE NAZWA KONTENERA !!!

To był mój zawstydzający błąd.

Poniżej przedstawiłem ci zdjęcie mojej linii poleceń, aby zobaczyć, co zrobiłem źle.

I to jest poprawka, jak wspomniano w dokumentach .

wprowadź opis zdjęcia tutaj

Parsa
źródło
-7

aby działało, dodaj miękkie odniesienie do / usr / bin:

ln -s $ (który węzeł) / usr / bin / node

ln -s $ (który npm) / usr / bin / npm

Vacavaca
źródło
1
Dodaj opis, w jaki sposób mu to pomoże.
Mathews Sunny,