Korzystanie z instrukcji RUN w Dockerfile z „source” nie działa

274

Mam plik Docker, który przygotowuję, aby zainstalować waniliowe środowisko python (w którym będę instalować aplikację, ale w późniejszym terminie).

FROM ubuntu:12.04

# required to build certain python libraries
RUN apt-get install python-dev -y

# install pip - canonical installation instructions from pip-installer.org
# http://www.pip-installer.org/en/latest/installing.html
ADD https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py /tmp/ez_setup.py
ADD https://raw.github.com/pypa/pip/master/contrib/get-pip.py /tmp/get-pip.py
RUN python /tmp/ez_setup.py
RUN python /tmp/get-pip.py
RUN pip install --upgrade pip 

# install and configure virtualenv
RUN pip install virtualenv 
RUN pip install virtualenvwrapper
ENV WORKON_HOME ~/.virtualenvs
RUN mkdir -p $WORKON_HOME
RUN source /usr/local/bin/virtualenvwrapper.sh

Kompilacja działa poprawnie do ostatniej linii, gdzie otrzymuję następujący wyjątek:

[previous steps 1-9 removed for clarity]
...
Successfully installed virtualenvwrapper virtualenv-clone stevedore
Cleaning up...
 ---> 1fc253a8f860
Step 10 : ENV WORKON_HOME ~/.virtualenvs
 ---> Running in 8b0145d2c80d
 ---> 0f91a5d96013
Step 11 : RUN mkdir -p $WORKON_HOME
 ---> Running in 9d2552712ddf
 ---> 3a87364c7b45
Step 12 : RUN source /usr/local/bin/virtualenvwrapper.sh
 ---> Running in c13a187261ec
/bin/sh: 1: source: not found

Jeśli przejdę lsdo tego katalogu (tylko w celu sprawdzenia, czy poprzednie kroki zostały popełnione), widzę, że pliki istnieją zgodnie z oczekiwaniami:

$ docker run 3a87 ls /usr/local/bin
easy_install
easy_install-2.7
pip
pip-2.7
virtualenv
virtualenv-2.7
virtualenv-clone
virtualenvwrapper.sh
virtualenvwrapper_lazy.sh

Jeśli spróbuję po prostu uruchomić sourcepolecenie, pojawia się ten sam błąd „nie znaleziono” jak powyżej. Jeśli jednak uruchomię interaktywną sesję powłoki, źródło działa:

$ docker run 3a87 bash
source
bash: line 1: source: filename argument required
source: usage: source filename [arguments]

Mogę uruchomić skrypt stąd, a następnie szczęśliwie dostępu workon, mkvirtualenvitd.

Zrobiłem trochę kopania i początkowo wydawało się, że problem może polegać na różnicy między bash jako powłoką logowania Ubuntu , a dash jako powłoką systemu Ubuntu , dash nie obsługuje sourcepolecenia.

Jednak wydaje się, że odpowiedzią na to jest użycie „”. zamiast source, ale to tylko powoduje, że środowisko wykonawcze Dockera wysadza się w powietrze z wyjątkiem paniki typu go.

Jaki jest najlepszy sposób na uruchomienie skryptu powłoki z instrukcji RUN Dockerfile, aby obejść ten problem (uruchamiam domyślny obraz podstawowy dla Ubuntu 12.04 LTS).

Hugo Rodger-Brown
źródło
2
Więc nie „źródła”, po prostu uruchom polecenie. Lub w szczególności uruchom skrypt powłoki za pomocą polecenia „bash”.
Alister Bulman,
Próbowałem - chociaż skrypt nie zawodzi, nie mam dostępu do różnych poleceń, których chciałem. Ten problem jest taki sam - github.com/dotcloud/docker/issues/2847
Hugo Rodger-Brown
2
Co, myśląc o tym, jest poprawne. Virtualenvwrapper prawdopodobnie nie ma sensu w środowisku kontenerowym. Mam zamiar to wycofać i zamiast tego użyć „native” virtualenv.
Hugo Rodger-Brown
1
Bardziej fundamentalnym sposobem podejścia do tego jest stackoverflow.com/questions/4732200/...
Gaurav Ojha
SpróbujCMD source activate django-py35
Belter

Odpowiedzi:

315

RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh"

chobo
źródło
66
Co? Jeśli skrypt zostanie umieszczony w powłoce, która istnieje tylko dla komendy, nie będzie w stanie wywierać trwałego wpływu na żadne przyszłe komendy, przy założeniu, że suma jego akcji określa zmienne środowiskowe. Dlaczego więc sourcew ogóle używałbyś , a nie tylko bash /usr/local/bin/virtualenvwrapper.sh, w takim przypadku?
Charles Duffy
13
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh; my_command; my_command; my_command;"
Leo
29
To nie jest poprawne, chociaż działa. Przeczytaj docs.docker.com/engine/reference/builder/#run i nie przestawaj po drugim przykładzie kodu. Przeczytaj notatkę: natychmiast po tym. Ponieważ /bin/sh -cjest to domyślna powłoka, ta „forma powłoki” RUN tłumaczy RUN ["/bin/sh", "-c", "/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]. Powinieneś iść dalej i użyć „formularza shRUN ["/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]
egzekucyjnego
8
Zobacz stackoverflow.com/a/45087082/117471, aby zrozumieć, dlaczego powoduje to bashzagnieżdżenie w shi dlatego należy tego unikać.
Bruno Bronosky,
4
Znacznie lepsza odpowiedź jest tutaj: stackoverflow.com/a/42216046/1663462
Chris Stryczyński
150

Oryginalna odpowiedź

FROM ubuntu:14.04
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

Powinno to działać dla każdego podstawowego obrazu dokera Ubuntu. Zazwyczaj dodam ten wiersz do każdego pliku Dockerfile, który piszę.

Edytuj przez zainteresowanego obserwatora

Jeśli chcesz uzyskać efekt „używania bashzamiast przez shcały ten plik Docker”, bez zmiany i prawdopodobnie uszkodzenia * systemu operacyjnego w kontenerze, możesz po prostu powiedzieć Dockerowi o swoim zamiarze . Odbywa się to w następujący sposób:

SHELL ["/bin/bash", "-c"]

* Możliwe uszkodzenie polega na tym, że wiele skryptów w Linuksie (przy świeżej instalacji Ubuntu grep -rHInE '/bin/sh' /zwraca ponad 2700 wyników) oczekuje pełnej powłoki POSIX /bin/sh. Powłoka bash to nie tylko POSIX i dodatkowe wbudowane funkcje. Są wbudowane (i więcej), które zachowują się zupełnie inaczej niż te w POSIX. W PEŁNI popieram unikanie POSIX (i błąd, że każdy skrypt, którego nie testowałeś na innej powłoce, zadziała, ponieważ uważasz, że unikałeś basmism) i po prostu używa bashism. Ale robisz to z właściwym shebangiem w swoim skrypcie. Nie poprzez wyciąganie powłoki POSIX spod całego systemu operacyjnego. (Chyba że masz czas na zweryfikowanie wszystkich skryptów 2700 plus dostarczonych z Linuksem oraz wszystkich skryptów we wszystkich instalowanych pakietach).

Więcej szczegółów w tej odpowiedzi poniżej. https://stackoverflow.com/a/45087082/117471

Anubhav Sinha
źródło
18
Można to nieco uprościć:ln -snf /bin/bash /bin/sh
apottere
2
@ user1442219 zastępuje domyślny interpreter poleceń od shdobash
Bhargav Nanekalva,
27
ln -s /bin/bash /bin/shto okropny pomysł. ubuntu target / bin / sh do dash z jakiegoś powodu. dash jest całkowicie posixową powłoką, która jest o rząd wielkości szybsza niż bash. linkowanie / bin / sh do bash drastycznie obniży wydajność twojego serwera. przytoczyć: wiki.ubuntu.com/DashAsBinSh
Xero
7
To brudny hack, a nie rozwiązanie. Jeśli skrypt jest prowadzony przez w shskorupkach, ale chcesz bash, prawidłowe rozwiązanie jest albo mieć shInvoke procesu bashjako jednorazowy, np bash -c 'source /script.sh && …', lub można nawet iść tak daleko, aby bashisms uniknąć (jak source) w całości, a zamiast zdecyduj się na używanie tylko prawidłowych odpowiedników POSIX, np . /script.sh. (Przestrzegaj miejsca po .!) Na koniec, jeśli skrypt jest wykonywalny (nie tylko źródłowy), nigdy nie zmuszaj skryptu do #!/bin/shshebang, jeśli w rzeczywistości nie jest zgodny z sh. Użyj #!/bin/bashzamiast tego.
Mark G.
7
A teraz jak mogę głosować za oryginalną odpowiedzią i głosować nad poprawką przez „zainteresowanego”?
Slava
65

Domyślną powłoką RUNinstrukcji jest ["/bin/sh", "-c"].

RUN "source file"      # translates to: RUN /bin/sh -c "source file"

Korzystając z instrukcji SHELL , możesz zmienić domyślną powłokę dla kolejnych RUNinstrukcji w Dockerfile:

SHELL ["/bin/bash", "-c"] 

Teraz domyślna powłoka uległa zmianie i nie trzeba jej jawnie definiować w każdej instrukcji RUN

RUN "source file"    # now translates to: RUN /bin/bash -c "source file"

Dodatkowa uwaga : Możesz również dodać --loginopcję, która uruchomi powłokę logowania. Oznacza to ~/.bachrcna przykład, że zostanie przeczytany i nie musisz go jawnie pozyskiwać przed wydaniem polecenia

Ahmad Abdelghany
źródło
1
Świetny wskaźnik używania --login- właśnie sam to
odkryłem
Dzięki temu SHELL ["/bin/bash", "-c", "-l"] mogłem korzystać z dalszych aktualizacji pliku .bashrc, co pozwoliło mi na łatwe uruchamianie poleceń asdf.
Rowinson Gallego
46

Miałem ten sam problem i aby wykonać instalację pip w virtualenv musiałem użyć tego polecenia:

RUN pip install virtualenv virtualenvwrapper
RUN mkdir -p /opt/virtualenvs
ENV WORKON_HOME /opt/virtualenvs
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh \
    && mkvirtualenv myapp \
    && workon myapp \
    && pip install -r /mycode/myapp/requirements.txt"

Mam nadzieję, że to pomoże.

Andrea Grandi
źródło
Jeśli przyszedłeś z odpowiedzi ROS, tak, to działa. Coś w stylu:RUN /bin/bash -c "source /opt/ros/melodic/setup.bash && \ cd /home && \ git clone https://angelos.p:[email protected]/inno/grpc-comms.git && \ cd grpc-comms && \ mkdir build && \ cd build && \ cmake .. && make"
angelos.p.
44

Najprostszym sposobem jest użycie operatora kropki zamiast źródła, który jest odpowiednikiem sh sourcepolecenia bash :

Zamiast:

RUN source /usr/local/bin/virtualenvwrapper.sh

Posługiwać się:

RUN . /usr/local/bin/virtualenvwrapper.sh
mixja
źródło
„source jest wbudowaną powłoką Bourne'a i„ specjalną ”wbudowaną funkcją POSIX - ss64.com/bash/source.html linux.die.net/man/1/sh ... . / sourceakceptuje również parametry pozycyjne po nazwie pliku
Wes Turner
5
To nie działa, ponieważ każde polecenie RUN działa niezależnie. Zmiany z sourcelub .są tracone po zakończeniu polecenia RUN. Zobacz: stackoverflow.com/a/40045930/19501
amit
26

Jeśli używasz Dockera 1.12 lub nowszego, po prostu użyj SHELL!

Krótka odpowiedź:

generał:

SHELL ["/bin/bash", "-c"] 

dla python vituralenv:

SHELL ["/bin/bash", "-c", "source /usr/local/bin/virtualenvwrapper.sh"]

Długa odpowiedź:

z https://docs.docker.com/engine/reference/builder/#/shell

SHELL ["executable", "parameters"]

Instrukcja SHELL pozwala na zastąpienie domyślnej powłoki używanej w postaci poleceń. Domyślna powłoka w systemie Linux to [„/ bin / sh”, „-c”], a w systemie Windows to [„cmd”, „/ S”, „/ C”]. Instrukcja SHELL musi być napisana w formacie JSON w pliku Dockerfile.

Instrukcja SHELL jest szczególnie przydatna w systemie Windows, w którym dostępne są dwie powszechnie używane i całkiem różne natywne powłoki: cmd i powershell, a także dostępne alternatywne powłoki, w tym sh.

Instrukcja SHELL może pojawić się wiele razy. Każda instrukcja SHELL zastępuje wszystkie poprzednie instrukcje SHELL i wpływa na wszystkie kolejne instrukcje. Na przykład:

FROM microsoft/windowsservercore

# Executed as cmd /S /C echo default
RUN echo default

# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default

# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello

# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello

Instrukcje SHELL mogą mieć wpływ na następujące instrukcje, gdy ich forma powłoki jest używana w Dockerfile: RUN, CMD i ENTRYPOINT.

Poniższy przykład jest typowym wzorem występującym w systemie Windows, który można usprawnić za pomocą instrukcji SHELL:

...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...

Polecenie wywoływane przez dokera to:

cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"

Jest to nieefektywne z dwóch powodów. Po pierwsze, wywoływany jest niepotrzebny procesor poleceń cmd.exe (inaczej powłoka). Po drugie, każda instrukcja RUN w formie powłoki wymaga dodatkowej komendy PowerShell, która poprzedza polecenie.

Aby uczynić to bardziej wydajnym, można zastosować jeden z dwóch mechanizmów. Jednym z nich jest użycie formularza JSON polecenia RUN, takiego jak:

...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...

Chociaż formularz JSON jest jednoznaczny i nie używa niepotrzebnego cmd.exe, wymaga większej szczegółowości poprzez podwójne cytowanie i ucieczkę. Alternatywnym mechanizmem jest użycie instrukcji SHELL i formularza powłoki, dzięki czemu użytkownicy systemu Windows stają się bardziej naturalną składnią, szczególnie w połączeniu z dyrektywą parsera Escape:

# escape=`

FROM microsoft/nanoserver
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'

Wynikające z:

PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 4.096 kB
Step 1/5 : FROM microsoft/nanoserver
 ---> 22738ff49c6d
Step 2/5 : SHELL powershell -command
 ---> Running in 6fcdb6855ae2
 ---> 6331462d4300
Removing intermediate container 6fcdb6855ae2
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
 ---> Running in d0eef8386e97


    Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       10/28/2016  11:26 AM                Example


 ---> 3f2fbf1395d9
Removing intermediate container d0eef8386e97
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
 ---> a955b2621c31
Removing intermediate container b825593d39fc
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
 ---> Running in be6d8e63fe75
hello world
 ---> 8e559e9bf424
Removing intermediate container be6d8e63fe75
Successfully built 8e559e9bf424
PS E:\docker\build\shell>

Instrukcja SHELL może również służyć do modyfikowania sposobu działania powłoki. Na przykład przy użyciu SHELL cmd / S / C / V: ON | OFF w systemie Windows można zmodyfikować semantykę opóźnionego rozszerzania zmiennych środowiskowych.

Instrukcja SHELL może być również użyta w systemie Linux, jeśli wymagana jest alternatywna powłoka, taka jak zsh, csh, tcsh i inne.

Funkcja SHELL została dodana w Docker 1.12.

Mithril
źródło
20

Opierając się na odpowiedziach na tej stronie, dodam, że musisz pamiętać, że każda instrukcja RUN działa niezależnie od innych /bin/sh -ci dlatego nie otrzyma żadnych zmiennych środowiskowych, które normalnie byłyby pozyskiwane w powłokach logowania.

Najlepszym sposobem, jaki do tej pory znalazłem, jest dodanie skryptu, /etc/bash.bashrca następnie wywołanie każdego polecenia jako logowania bash.

RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc
RUN /bin/bash --login -c "your command"

Możesz na przykład zainstalować i skonfigurować virtualenvwrapper, utworzyć wirtualną env, aktywować ją podczas korzystania z logowania bash, a następnie zainstalować moduły python w tej env:

RUN pip install virtualenv virtualenvwrapper
RUN mkdir -p /opt/virtualenvs
ENV WORKON_HOME /opt/virtualenvs
RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc
RUN /bin/bash --login -c "mkvirtualenv myapp"
RUN echo "workon mpyapp" >> /etc/bash.bashrc
RUN /bin/bash --login -c "pip install ..."

Czytanie instrukcji na temat plików startowych bash pomaga zrozumieć, co jest pozyskiwane.

TomDotTom
źródło
1
Fajnie, w oparciu o twoje rozwiązanie, co właśnie zilustrowałem, to: ADD env-file /etc/profile.d/installerenv.sh RUN /bin/bash --login -c 'env' RUN /bin/bash -c 'rm /etc/profile.d/installerenv.sh' Jeśli czyjś przypadek użycia dodaje więcej zmiennych środowiskowych wstrzykiwania do perspektywy budowania okna dokowanego, tak jak moje, polecam zajrzeć na docs.docker.com/compose/yml / # plik env też.
daniel.kahlenberg
1
Wierzę, że problem polega na tym, że nie kończysz buforowania wyników każdego RUNpolecenia, co oznacza, że ​​nie możesz zainstalować wielu zależności projektu, a następnie skopiować kod źródłowy i skorzystać z zalet Buforowanie pośredniego kroku Dockera. Za każdym razem będzie ponownie instalować wszystkie zależności projektu.
erewok
Użyj /etc/bashrcdla Redhat, zamiast /etc/bash.bashrcjak wspomniano powyżej (dla Ubuntu)
Jordan Gee
Użyłem /root/.bashrc dla centos.
schmudu,
Uruchom polecenie echo „source /yourscript.bash” >> /etc/bash.bashrc. jeśli używasz ros wewnątrz dokera i chcesz skonfigurować środowisko, powinieneś to zrobić
27221
17

Według https://docs.docker.com/engine/reference/builder/#run domyślną powłoką [Linux] RUNjest /bin/sh -c. Wygląda na to, że spodziewasz się bashism, więc powinieneś użyć „exec formularza”, RUNaby określić swoją powłokę.

RUN ["/bin/bash", "-c", "source /usr/local/bin/virtualenvwrapper.sh"]

W przeciwnym razie użycie „formy powłoki” programu RUN i określenie innej powłoki spowoduje utworzenie zagnieżdżonych powłok.

# don't do this...
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh"
# because it is the same as this...
RUN ["/bin/sh", "-c", "/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]

Jeśli masz więcej niż 1 polecenie wymagające innej powłoki, powinieneś przeczytać https://docs.docker.com/engine/reference/builder/#shell i zmienić domyślną powłokę, umieszczając ją przed poleceniami RUN:

SHELL ["/bin/bash", "-c"]

Na koniec, jeśli umieściłeś coś w .bashrcpliku użytkownika root , którego potrzebujesz, możesz dodać -lflagę do polecenia SHELLlub, RUNaby uczynić z niego powłokę logowania i upewnić się, że zostanie pozyskana.

Uwaga: Celowo zignorowałem fakt, że nie ma sensu pozyskiwać skryptu jako jedynego polecenia w poleceniu RUN.

Bruno Bronosky
źródło
SHELL ["/bin/sh", "-c", "-l"]więc źródła ~ / .bashrc itp. na wypadek, gdybyś miał ustawienia środowiska z podstawowego kontenera
MortenB
1
@MortenB, ale określiłeś (literówka?), /bin/shCo nie rozwiąże problemu, że bash nie będzie używany. Ponadto, podczas wykonywania docker buildnie jest prawdopodobne, aby w pliku root użytkownika .bashrc znajdowało się coś, czego potrzebujesz. Ale jeśli umieścisz coś tam wcześniej w Dockerfile (na przykład może JAVA_HOME, a potem tak). W mojej odpowiedzi
dodam notatkę
Przepraszam za literówkę, używam pyenv, który potrzebuje źródła ~ / .bashrc, aby ustawić ścieżki dla prawidłowej wersji Pythona w moich podstawowych obrazach. to sprawia, że ​​używam jakiejkolwiek bazy linux i dwie linie dodają dowolną wersję na Pythonie. Podobnie jak python 3.7 na ubuntu16.04, gdzie podstawowym pythonem jest 3.5.2
MortenB
11

Zgodnie z dokumentacją Dockera

Aby użyć innej powłoki, innej niż „/ bin / sh”, użyj formularza exec przekazującego żądaną powłokę. Na przykład,

RUN ["/bin/bash", "-c", "echo hello"]

Zobacz https://docs.docker.com/engine/reference/builder/#run

Gianluca Casati
źródło
To jest RZECZYWISTA poprawna odpowiedź. Autor wybranej odpowiedzi stackoverflow.com/a/25086628/117471 wydaje się czytać tylko pierwszy przykład w dokumentacji, do której prowadzi łącze. Wydaje się, że nie przeczytali następnego akapitu, który właśnie zacytowałeś.
Bruno Bronosky,
4

Jeśli masz SHELLdostęp, powinieneś skorzystać z tej odpowiedzi - nie używaj tej, która zmusi cię do umieszczenia reszty pliku docker w jednym poleceniu dla tego komentarza .

Jeśli używasz starej wersji Dockera i nie masz do niej dostępu SHELL, będzie to działać, dopóki niczego nie potrzebujesz .bashrc(co jest rzadkim przypadkiem w Dockerfiles):

ENTRYPOINT ["bash", "--rcfile", "/usr/local/bin/virtualenvwrapper.sh", "-ci"]

Zauważ, że -ijest potrzebne, aby bash w ogóle odczytał plik rc.

Mohan
źródło
3

Możesz pobiec, bash -vaby zobaczyć, co jest pozyskiwane.

Wykonałbym następujące czynności zamiast bawić się dowiązaniami symbolicznymi:

RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc

vimdude
źródło
3

Miałem również problemy z uruchomieniem sourcew Dockerfile

Działa to doskonale w przypadku budowania kontenera Docker CentOS 6.6, ale powodowało problemy w kontenerach Debian

RUN cd ansible && source ./hacking/env-setup

Tak sobie z tym poradziłem, może nie jest to elegancki sposób, ale to działało dla mnie

RUN echo "source /ansible/hacking/env-setup" >> /tmp/setup
RUN /bin/bash -C "/tmp/setup"
RUN rm -f /tmp/setup
vikas027
źródło
2

Może się tak zdarzyć, ponieważ sourcejest to wbudowany system bash zamiast pliku binarnego w systemie plików. Czy chcesz, aby skrypt, który pozyskujesz, zmienił później kontener?

Paul Morie
źródło
1
Skrypt aktualizuje kontener - ale szczerze mówiąc, próbowałem zrobić coś, co nie miało sensu, więc ominąłem ten problem.
Hugo Rodger-Brown,
1

Skończyło się na tym, że włożyłem swoje rzeczy związane z env .profilei zmutowałem SHELLcoś takiego

SHELL ["/bin/bash", "-c", "-l"]

# Install ruby version specified in .ruby-version
RUN rvm install $(<.ruby-version)

# Install deps
RUN rvm use $(<.ruby-version) && gem install bundler && bundle install

CMD rvm use $(<.ruby-version) && ./myscript.rb
mattexx
źródło
3
„-c” musi być ostatnim argumentem (przed wykonaniem polecenia.to)
peterk
0

Jeśli próbujesz tylko użyć pipa, aby zainstalować coś w virtualenv, możesz zmodyfikować env PATH, aby najpierw przeglądał folder bin virtualenv

ENV PATH="/path/to/venv/bin:${PATH}"

Następnie wszelkie pip installpolecenia znajdujące się w pliku Docker najpierw znajdą / path / to / venv / bin / pip i użyją tego, który zainstaluje się w tym virtualenv, a nie w Pythonie systemowym.

shadfc
źródło