Docker Compose поддерживает работу контейнера


94

Я хочу запустить службу с docker-compose и оставить контейнер работающим, чтобы я мог получить его IP-адрес с помощью docker inspect. Однако контейнер всегда выходит сразу после запуска.

Я пытался добавить «command: [« sleep »,« 60 »]» и другие вещи в docker-compose.yml, но всякий раз, когда я добавляю строку с «command: ...», я не могу вызвать «docker-compose up» так как я получу сообщение "Не удается запустить контейнер ..... Системная ошибка: недопустимый символ 'k' ищет начало значения"

Я также попытался добавить «CMD sleep 60» и еще много чего в сам Dockerfile, но эти команды, похоже, не выполняются.

Есть ли простой способ сохранить контейнер живым или решить одну из моих проблем?

EDIT: вот файл Compose, который я хочу запустить:

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

Он работает нормально. Если я начну с docker-compose под OS X, но если я попробую сделать то же самое под Ubuntu 16.04, он выдаст мне сообщение об ошибке выше.

Если я попробую использовать подход с Dockerfile, Dockerfile будет выглядеть так:

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

Который, кажется, ничего не делает

РЕДАКТИРОВАТЬ 2: Я должен исправить себя, оказалось, что это была та же проблема с Dockerfile и docker-compose.yml: каждый раз, когда я добавляю «CMD ...» в Dockerfile ИЛИ добавляю «command ...» в файл набора, я получаю ошибку выше с недопустимым символом. Если я удалю обе команды, все будет работать безупречно.


1
Включите docker-compose.yml, Dockerfile и любые скрипты, которые вы пытаетесь отлаживать.
BMitch

Ответы:


118

Чтобы контейнер продолжал работать при запуске docker-compose, используйте следующую команду

command: tail -F anything

Итак, ваш docker-compose.yml становится

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

и вы можете запустить оболочку, чтобы попасть в контейнер, используя следующую команду

docker exec -i -t composename_my-test_1 bash

где composenameимя, которое docker-composeпредшествует вашим контейнерам.


1
Как остановить контейнер, когда вы закончили с ним? Есть ли команды типа Ctrl + C, Ctrl + Z? Сейчас мне нужно закрыть терминал, чтобы выйти.
mac10688

Если вы находитесь внутри контейнера, вы можете ввести exitего, чтобы вернуться на свой хост-компьютер. Если вы находитесь на своем хосте, вы можете остановить контейнер с помощью Docker ( docker stop composename_my-test_1) или Docker Compose ( docker-compose stop).
Ник Сеттье 03

2
@ Alexis.Rolland Если вы хотите задать новый вопрос SO и поделиться некоторыми подробностями, я буду более чем счастлив взглянуть на него. Я предполагаю, что ваша ошибка как-то связана с внутренним устройством одного из ваших контейнеров, а не с проблемой с Docker или вашей операционной системой хоста.
Ник Сеттье

1
@ mac10688, если в подключенном сеансе контейнера нет приглашения, попробуйте отсоединить ctrl-d
Старк

5
/dev/nullбыло бы лучше для anythingхвостовой команды исх. stackoverflow.com/a/48732671/248616
Nam G VU

80

Вы можете использовать ttyопцию конфигурации.

version: '3'

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

Примечание. Если вы используете Dockerfile для изображения и CMDв Dockerfile, эта опция не будет работать; однако вы можете использовать entrypointпараметр в файле создания, который очищает файл CMDDockerfile.


7
Это работает и кажется менее хакерским, чем tail -f /dev/null. Благодаря этому я могу запустить контейнерную среду разработки с подключенной базой данных postgres docker-compose upи запустить оболочку через другой терминал, используя docker exec.
Псилок

1
Хотя в настоящее время НЕ хорошо документирован. Это официальные параметры, обеспечивающие тот же эффект, что и tail -f /dev/nullили tail -f anything, см. Здесь: docs.docker.com/compose/compose-file
b01

2
@ABMRuman & Psiloc, Работает только тогда, когда вы не используете "команду" в файле docker-compose.yml. При использовании "command" вам понадобится еще один хакер - поэтому здесь идеально подходит хак tail -F.
asafel

Это должен быть лучший ответ, если вы используете точку входа в dockerfile.
DDKV587,

53

Основываясь на комментарии @aanand на GitHub 26 августа 2015 г. , можно использовать tail -f /dev/nullв docker-compose, чтобы контейнер работал.

Пример docker-compose.yml

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

Почему эта команда?

Единственная причина выбора этого варианта заключалась в том, что он получил много положительных отзывов на GitHub, но самый высокий результат не означает, что это лучший ответ. Вторая причина была прагматичной, поскольку вопросы нужно было решать как можно быстрее из-за сроков.


2
почему именно эта команда? Что делает его лучше других? В моем случае просто начало bash тоже
помогло

@ N4ppeL Хороший вопрос. Единственная причина, по которой я выбрал этот вариант, заключалась в том, что он получил много положительных отзывов на github, но наибольшее количество голосов не означает, что это лучший ответ. Вторая причина была прагматической, так как мне пришлось решать вопрос как можно быстрее из-за сроков.
030

17
  • Создайте файл с именем docker-compose.yml
  • Добавьте в файл следующее
version: "3"

services:
  ubuntu:
    image: ubuntu:latest
    tty: true
  • Оставаясь в том же каталоге, запускаем docker-compose up -dиз терминала
  • Запустите, docker psчтобы получить идентификатор или имя контейнера
  • Вы можете запустить docker inspect $container_id
  • Вы можете войти в контейнер и запустить оболочку bash docker-compose exec ubuntu /bin/bashилиdocker-compose exec ubuntu /bin/sh
  • Когда закончите, убедитесь, что вы находитесь за пределами контейнера, и запустите docker-compose down

Вот небольшой сценарий bash ( my-docker-shell.sh) для создания файла компоновки докеров, запуска контейнера, входа в контейнер и, наконец, очистки контейнера докеров и файла компоновки докеров при выходе из системы.

#!/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

1
Хотя это и не был ответ на вопрос, я нашел его чрезвычайно ценным! Я пошел дальше, чтобы использовать глобальные функции bashrc для этого подхода: gist.github.com/loopmode/4d59a4e9a0a2ffacaec2dd14db4ae8bd
loopmode


2

Как заявил комментатор, нам нужно увидеть рассматриваемый файл Docker, чтобы дать вам полный ответ, но это очень распространенная ошибка. Я могу в значительной степени гарантировать, что команда, которую вы пытаетесь запустить, запускает фоновый процесс. Это может быть та команда, которую вы бы запускали в ситуациях, отличных от Docker, но это неправильно делать в Dockerfile. Например, если то, что вы используете, обычно определяется как системная служба, вы можете использовать что-то вроде «systemctl start». Это запустит процесс в фоновом режиме, что не сработает. Вы должны запустить процесс на переднем плане, поэтому весь процесс будет заблокирован.


0

Просто небольшое примечание

Я тестировал одно изображение на основе golang, поэтому, когда я называю docker-compose downздесь, что получаю:

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

Моя системная информация:

Ubuntu 18.04.4 LTS (64-bit)
Docker version 19.03.6, build 369ce74a3c
docker-compose version 1.26.0, build d4451659

-3

Хорошо, я нашел свою ошибку. В файле Dockerfile для образа, используемого для создания, я указал, что базовым образом должен быть ubuntu: latest, но ранее я сам создал образ под названием ubuntu, и этот образ не работал. Поэтому я использовал не исходный образ ubuntu, а скорее поврежденную версию моего собственного образа, также называемую ubuntu.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.