2016-06-15 12 views
7

Mam obraz dokowania, który używa skryptu (/bin/bash /init.sh) jako punktu wejścia. Chciałbym wykonać ten skrypt tylko przy pierwszym uruchomieniu kontenera. Należy go pominąć, gdy kontenery zostaną ponownie uruchomione lub uruchomione ponownie po awarii demona dokowania.Uruchom polecenie w Docker Container tylko przy pierwszym uruchomieniu

Czy jest jakiś sposób, aby to zrobić z samym dokiem, lub jeśli trzeba wprowadzić jakiś rodzaj kontroli w skrypcie?

Odpowiedz

9

Punkt wejścia do kontenera dokera informuje demona docker, co należy uruchomić, aby "uruchomić" konkretny kontener. Zadajmy sobie pytania: "co kontener powinien uruchomić po uruchomieniu po raz drugi?" lub "co kontener powinien uruchomić po ponownym uruchomieniu?"

Prawdopodobnie to, co robisz, jest zgodne z tym samym podejściem, które stosujesz w przypadku mechanizmów "starej szkoły". Twój skrypt "instaluje" potrzebne skrypty, a uruchomisz aplikację jako usługę systemd/upstart, prawda? Jeśli to robisz, powinieneś zmienić to w bardziej "zderarchizowaną" definicję.

Punktem początkowym dla tego kontenera powinien być skrypt, który faktycznie uruchamia aplikację, zamiast konfigurowania. Powiedzmy, że musisz zainstalować java, aby móc uruchomić twoją aplikację. Więc w dockerfile skonfigurowaniu kontenera bazowego, aby zainstalować wszystkie potrzebne rzeczy jak:

FROM alpine:edge 

RUN apk --update upgrade && apk add openjdk8-jre-base 
RUN mkdir -p /opt/your_app/ && adduser -HD userapp 

ADD target/your_app.jar /opt/your_app/your-app.jar 
ADD scripts/init.sh /opt/your_app/init.sh 

USER userapp 
EXPOSE 8081 

CMD ["/bin/bash", "/opt/your_app/init.sh"] 

naszych kontenerach, w firmie, w której pracuję, przed uruchomieniem rzeczywistą aplikację w init.sh skryptu oni pobrać konfiguruje konsul (zamiast dostarczania punktu montowania i umieszczania konfiguracji wewnątrz hosta lub osadzania ich w kontenerze). Więc skrypt będzie wyglądać mniej więcej tak:

#!/bin/bash 

echo "Downloading config from consul..." 
confd -onetime -backend consul -node $CONSUL_URL -prefix /cfgs/$CONSUL_APP/$CONSUL_ENV_NAME 
echo "Launching your-app..." 
java -jar /opt/your_app/your-app.jar 

Jedna rada, jaką mogę dać ci to (w moim bardzo krótkim doświadczenia w pracy z kontenerami) traktować swoje pojemniki tak, jakby były bezpaństwowcem, gdy są one zabezpieczony (wszystkie polecenia, które działają przed punktem wejścia).

+1

Całkowicie zgadzam się na uznanie kontenerów za bezpaństwowców. Jeśli istnieją dane do zainicjowania, umieść je w woluminie. – BMitch

+2

Bardzo chciałbym skorzystać z Twojej rady, ale to nie jest takie proste. Mam niewielki wpływ na zmiany w aplikacji i musiałem zmienić DUŻĘ, aby używać jej tak, jak opisałeś. Na przykład: za każdym razem, gdy kontener się uruchamia, skrypt inicjujący tworzy bazę danych dla aplikacji. Nie powinno się to zdarzyć, gdy kontener zostanie zrestartowany, ponieważ nadpisuje dane, które już tam są ... Niestety, bardzo trudno było nauczyć twórców aplikacji, jak korzystać z funkcji dokowania. Dlatego staram się, aby był dla nich wyjątkowo prosty. – christian

+0

jak to zrobić? – StarWind0

1

Chciałem zrobić to samo na pojemniku Windows. Można to osiągnąć za pomocą harmonogramu zadań w oknach. Odpowiednikiem Linux dla zadania Scheduler jest cron. Możesz użyć tego w swojej sprawie. Aby wykonać tę edycję w dockerfile i dodaj następujący wiersz na końcu

WORKDIR /app 
COPY myTask.ps1 . 
RUN schtasks /Create /TN myTask /SC ONSTART /TR "c:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe C:\app\myTask.ps1" /ru SYSTEM 

Stwarza to zadanie o nazwie myTask uruchamia go onStart a zadaniem jego jest wykonanie skryptu powershell umieszczony w „c: \ app \ myTask.ps1 ".

Ten skrypt myTask.ps1 wykona dowolną inicjalizację, którą należy wykonać przy starcie kontenera. Upewnij się, że usuniesz to zadanie po jego pomyślnym wykonaniu, bo inaczej uruchomi się przy każdym starcie. Aby go usunąć, możesz użyć następującego polecenia na końcu skryptu myTask.ps1.

schtasks /Delete /TN myTask /F 
0

musiałem to zrobić i skończyło się robi docker run -d który właśnie utworzony jednorodzinnego pojemnik i zaczęła bash (w tle), a następnie przez docker exec, że zrobił to niezbędne inicjalizacji. oto przykład

docker run -itd --name=myContainer myImage /bin/bash 
docker exec -it myContainer /bin/bash -c /init.sh 

Teraz, kiedy ponownie uruchomić pojemnik mogę tylko zrobić

docker start myContainer 
docker attach myContainer 

może nie być idealne, ale działa dobrze dla mnie.

Powiązane problemy