Docker Compose utrzymuje działanie kontenera

101

Chcę uruchomić usługę za pomocą docker-compose i utrzymać kontener w ruchu, abym mógł uzyskać jego adres IP przez „docker inspect”. Jednak kontener zawsze wychodzi zaraz po uruchomieniu.

Próbowałem dodać "command: [" sleep "," 60 "]" i inne rzeczy do docker-compose.yml, ale ilekroć dodam wiersz z "command: ..." Nie mogę wywołać "docker-compose up" ponieważ otrzymam komunikat „Nie można uruchomić kontenera ..... Błąd systemu: nieprawidłowy znak 'k' szukający początku wartości”

Próbowałem też dodać "CMD sleep 60" i inne rzeczy do samego Dockerfile, ale te polecenia nie wydają się być wykonywane.

Czy istnieje łatwy sposób na utrzymanie pojemnika przy życiu lub rozwiązanie jednego z moich problemów?

EDYCJA: Oto plik tworzenia, który chcę uruchomić:

version: '2'
services:
  my-test:
    image: ubuntu
    command: bash -c "while true; do echo hello; sleep 2; done"

Działa dobrze Jeśli zacznę to od docker-compose pod OS X, ale jeśli spróbuję tego samego pod Ubuntu 16.04, pojawi się powyższy komunikat o błędzie.

Jeśli spróbuję podejścia z plikiem Dockerfile, plik Dockerfile wygląda następująco:

FROM ubuntu:latest
CMD ["sleep", "60"]

Co wydaje się nic nie robić

EDYCJA 2: Muszę się poprawić, okazało się, że to ten sam problem z plikiem Dockerfile i docker-compose.yml: Za każdym razem, gdy dodaję „CMD ...” do Dockerfile LUB dodaję „polecenie ...” do plik tworzenia, otrzymuję powyższy błąd z nieprawidłowym znakiem. Jeśli usunę oba polecenia, działa bezbłędnie.

dingoglotz
źródło
1
Dołącz plik docker-compose.yml, plik Dockerfile i wszelkie skrypty, które próbujesz debugować.
BMitch

Odpowiedzi:

128

Aby utrzymać kontener uruchomiony po uruchomieniu docker-compose, użyj następującego polecenia

command: tail -F anything

Więc twój docker-compose.yml staje się

version: '2'
services:
  my-test:
    image: ubuntu
    command: tail -F anything

i możesz uruchomić powłokę, aby dostać się do kontenera, używając następującego polecenia

docker exec -i -t composename_my-test_1 bash

gdzie composenamejest nazwa docker-composedodawana do twoich kontenerów.

Nick Settje
źródło
1
Jak zatrzymać pojemnik, kiedy skończysz? Czy istnieje polecenie typu Ctrl + C, Ctrl + Z? Teraz muszę zamknąć terminal, aby wyjść.
mac10688
Jeśli jesteś w kontenerze, możesz pisać, exitaby wrócić do komputera głównego. Jeśli jesteś na swoim hoście, możesz zatrzymać kontener za pomocą Docker ( docker stop composename_my-test_1) lub Docker Compose ( docker-compose stop).
Nick Settje
2
@ Alexis.Rolland Jeśli chcesz zadać nowe pytanie SO i podać więcej szczegółów, z chęcią zajrzę. Domyślam się, że twój błąd ma coś wspólnego z wewnętrznymi elementami jednego z twoich kontenerów, a nie z problemem z Dockerem lub systemem operacyjnym twojego hosta.
Nick Settje
1
@ mac10688, jeśli nie ma monitu w dołączonej sesji kontenera, spróbuj ctrl-d, aby odłączyć
Stark
7
/dev/nullbyłoby lepiej na miejscu dla anythingodniesienia ogona. stackoverflow.com/a/48732671/248616
Nam G VU
90

Możesz skorzystać z ttyopcji konfiguracji.

version: '3'

services:
  app:
    image: node:8
    tty: true           # <-- This option

Uwaga: jeśli używasz Dockerfile dla obrazu i CMDDockerfile, ta opcja nie będzie działać; jednak możesz użyć entrypointopcji w pliku redagowania, która czyści plik CMDz Dockerfile.

wysoki skok
źródło
9
To działa i wydaje się mniej hakerskie niż tail -f /dev/null. Dzięki temu jestem w stanie uruchomić kontenerowane środowisko programistyczne z bazą danych postgres podłączoną za pośrednictwem docker-compose upi uruchomić powłokę za pośrednictwem innego terminala za pomocą docker exec.
Psiloc
1
Chociaż obecnie NIE jest dobrze udokumentowane. To jest oficjalna opcja, która przyniesie taki sam efekt jak tail -f /dev/nulllub tail -f anything, patrz tutaj: docs.docker.com/compose/compose-file
b01
2
@ABMRuman & Psiloc, Działa tylko wtedy, gdy nie używasz „polecenia” w pliku docker-compose.yml. Używając "komendy" potrzebujesz kolejnego hacka - stąd hack ogonowy -F jest tutaj idealnie dopasowany.
asafel
1
To musi być najlepsza odpowiedź, jeśli używasz punktu wejścia w pliku dockerfile.
DDKV587,
54

Opierając się na komentarzu @aanand na GitHub 26 sierpnia 2015 r. , Można by użyć tail -f /dev/nullw docker-compose, aby utrzymać działający kontener.

Przykład docker-compose.yml

version: '3'
services:
  some-app:
    command: tail -f /dev/null

Dlaczego to polecenie?

Jedynym powodem wyboru tej opcji było to, że otrzymała ona wiele pozytywnych opinii na GitHubie, ale najwyższa odpowiedź nie oznacza, że ​​jest to najlepsza odpowiedź. Drugi powód był pragmatyczny, ponieważ problemy musiały być rozwiązane jak najszybciej ze względu na terminy.

030
źródło
2
dlaczego akurat to polecenie? Co sprawia, że ​​jest lepszy od innych? W moim przypadku samo rozpoczęcie basha też się udało ...
N4ppeL
@ N4ppeL Dobre pytanie. Jedynym powodem, dla którego wybrałem tę opcję, było to, że otrzymała ona dużo aprobaty na githubie, ale najwyższa odpowiedź nie oznacza, że ​​jest to najlepsza odpowiedź. Drugi powód był pragmatyczny, ponieważ ze względu na terminy musiałem rozwiązać problem jak najszybciej.
030
17
  • Utwórz plik o nazwie docker-compose.yml
  • Dodaj następujące elementy do pliku
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • Pozostając w tym samym katalogu, uruchom docker-compose up -dz terminala
  • Uruchom, docker psaby uzyskać identyfikator lub nazwę kontenera
  • Możesz biec docker inspect $container_id
  • Możesz wejść do kontenera i uruchomić powłokę bash docker-compose exec ubuntu /bin/bashlubdocker-compose exec ubuntu /bin/sh
  • Po zakończeniu upewnij się, że jesteś poza pojemnikiem i biegnij docker-compose down

Oto mały skrypt bash ( my-docker-shell.sh) służący do tworzenia pliku docker compose, uruchamiania kontenera, logowania do kontenera, a następnie czyszczenia kontenera docker i pliku redagowania docker po wylogowaniu.

#!/bin/bash

cat << 'EOF' > ./docker-compose.yml
---

version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    command: /bin/bash
    # tty: true

...
EOF

printf "Now entering the container...\n"
docker-compose run ubuntu bash
docker-compose down

rm -v ./docker-compose.yml
GMaster
źródło
1
Chociaż nie była to właściwa odpowiedź na pytanie, uznałem ją za niezwykle cenną! Poszedłem dalej, aby użyć globalnych funkcji bashrc dla tego podejścia: gist.github.com/loopmode/4d59a4e9a0a2ffacaec2dd14db4ae8bd
loopmode
8

W Dockerfile możesz użyć polecenia:

{CMD sleep infinity}
Jan
źródło
2

Jak stwierdził komentator, musielibyśmy zobaczyć dany plik Dockerfile, aby udzielić pełnej odpowiedzi, ale jest to bardzo częsty błąd. Mogę prawie zagwarantować, że polecenie, które próbujesz uruchomić, uruchamia proces w tle. Może to być polecenie, które można uruchomić w sytuacjach innych niż Docker, ale jest to niewłaściwa czynność w pliku Dockerfile. Na przykład, jeśli to, co uruchamiasz, jest zwykle definiowane jako usługa systemowa, możesz użyć czegoś takiego jak „systemctl start”. To uruchomiłoby proces w tle, co nie zadziała. Musisz uruchomić proces na pierwszym planie, więc cały proces zostanie zablokowany.

David M. Karr
źródło
0

Tylko krótka notatka

Przetestowałem pojedynczy obraz na podstawie golang, więc kiedy dzwonię docker-compose downtutaj to co otrzymuję:

version: "3.1"
...
command: tail -f /dev/null   # stopping container takes about 10 sec.
tty: true                    # stopping container takes about 2 sec.

Informacje o moim systemie:

Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659
wędzarnia
źródło
-3

Okej, znalazłem swój błąd. W pliku Dockerfile dla obrazu używanego do komponowania określiłem, że obraz podstawowy powinien być ubuntu: najnowszy, ale wcześniej utworzyłem samodzielnie obraz o nazwie ubuntu i ten obraz nie działa. Więc nie użyłem oryginalnego obrazu ubuntu, ale raczej uszkodzoną wersję mojego własnego obrazu, zwaną również ubuntu.

dingoglotz
źródło