Как поддерживать работу промежуточного контейнера в Docker?

У меня есть Dockerfile, который выглядит так:

FROM centos/httpd
COPY ./aquarium-javascript/html/ /var/www/html/
RUN yum install -y java-11-openjdk
COPY ./aquarium_fish-0.0.1-SNAPSHOT.jar ./
COPY ./aquarium_species-0.0.1-SNAPSHOT.jar ./
COPY ./aquarium_gateway-0.0.1-SNAPSHOT.jar ./
COPY ./wrapper.sh ./
EXPOSE 8080
EXPOSE 80
RUN bash wrapper.sh

Wrapper.sh выглядит так:

java -jar aquarium_fish-0.0.1-SNAPSHOT.jar &
sleep 7;
java -jar aquarium_species-0.0.1-SNAPSHOT.jar &
sleep 7;
java -jar aquarium_gateway-0.0.1-SNAPSHOT.jar &
sleep 7;

Когда я запускаю java-файлы вручную с помощью sudo docker exec -it <container> /bin/bash, это работает, но когда я делаю это в wrapper.sh, это не работает. Я подумал, что это должно быть так, потому что промежуточный контейнер удаляется после выполнения java-файлов. Есть ли способ предотвратить это? Или я неправильно интерпретирую эту ситуацию?

Промежуточный контейнер?

John Kugelman 20.12.2020 17:43

Обратите внимание, что единственная цель Dockerfile — создать образ Docker. Не ожидается, что он запустит какую-либо постоянную службу. Если вы хотите взаимодействовать со своим кодом, вам нужно запустить контейнер с помощью docker run.

larsks 20.12.2020 17:48
when I do it in the wrapper.sh it doesn'twrapper.sh будет выполняться внутри докер-контейнера, зачем вам docker exec "изнутри" его? Какую именно команду вы выполнили?
KamilCuk 20.12.2020 17:49

Последним RUN должен быть CMD.

John Kugelman 20.12.2020 17:51

@JohnKugelman Когда я меняю RUN на CMD, даже httpd перестает работать. Я езжу так CMD ["bash", "wrapper.sh"].

Wojtek Wencel 20.12.2020 17:59

Вы, вероятно, захотите запустить это как три отдельных контейнера; вы должны быть в состоянии docker run your-image java -jar aquarium_fish-0.0.1-SNAPSHOT.jar переопределить изображение по умолчанию CMD. Вы можете создать его как три отдельных изображения. Настройка этого с помощью Docker Compose может помочь упростить сборку и запуск этого набора контейнеров.

David Maze 20.12.2020 20:22
Почему в Python есть оператор &quot;pass&quot;?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
6
265
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Короткий ответ: вы этого не сделаете. RUN команды выполняются во время сборки образа и в эфемерных контейнерах с целью изменения какой-то части образа. Предполагается, что они завершатся быстро, чтобы вы могли в конечном итоге получить готовый образ контейнера. Если вы хотите, чтобы все работало долго, используйте для этого docker run. Команда, которую будет запускать docker run, может быть установлена ​​в Dockerfile с помощью CMD или ENTRYPOINT.

Как предлагает Войтек Венсель, вы можете получить долго работающий контейнер, изменив RUN bash wrapper.sh на CMD ["bash", "wrapper.sh"] (добавив wait в конце wrapper.sh) и запустив образ с docker run --rm aquarium после его создания с помощью docker build -t aquarium. Проблема с этим подходом заключается в том, что не будет аккуратной обработки, когда один из процессов выйдет из строя, и выходные данные журнала будут перемешаны, иногда без простого способа различить строки.

Как предложил Дэвид Мейз, было бы правильнее дать каждому процессу свой собственный контейнер и запускать их вместе с docker-compose. Есть разные способы сделать это, я предпочитаю:

  • Изменить RUN bash wrapper.sh на ENTRYPOINT ["java", "-jar"]
  • Ставь docker-compose.yaml лайк
version: "2.4"
services:
  fish:
    command: aquarium_fish-0.0.1-SNAPSHOT.jar
    build:
      context: .
  species:
    command: aquarium_species-0.0.1-SNAPSHOT.jar
    build:
      context: .
  gateway:
    command: aquarium_gateway-0.0.1-SNAPSHOT.jar
    build:
      context: .
    ports:
      - 80:80 # Guessing here.

Это также сделало бы wrapper.sh ненужным.

Это довольно стандартный вариант использования, поэтому существует множество способов сделать это. Вы также можете сохранить wrapper.sh и передать имя службы в контейнер в качестве переменной среды или аргумента.

Другие вопросы по теме