У меня есть 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-файлов. Есть ли способ предотвратить это? Или я неправильно интерпретирую эту ситуацию?
Обратите внимание, что единственная цель Dockerfile — создать образ Docker. Не ожидается, что он запустит какую-либо постоянную службу. Если вы хотите взаимодействовать со своим кодом, вам нужно запустить контейнер с помощью docker run.
when I do it in the wrapper.sh it doesn't
wrapper.sh
будет выполняться внутри докер-контейнера, зачем вам docker exec
"изнутри" его? Какую именно команду вы выполнили?
Последним RUN должен быть CMD.
@JohnKugelman Когда я меняю RUN на CMD, даже httpd перестает работать. Я езжу так CMD ["bash", "wrapper.sh"].
Вы, вероятно, захотите запустить это как три отдельных контейнера; вы должны быть в состоянии docker run your-image java -jar aquarium_fish-0.0.1-SNAPSHOT.jar переопределить изображение по умолчанию CMD. Вы можете создать его как три отдельных изображения. Настройка этого с помощью Docker Compose может помочь упростить сборку и запуск этого набора контейнеров.
Короткий ответ: вы этого не сделаете. 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 и передать имя службы в контейнер в качестве переменной среды или аргумента.
Промежуточный контейнер?