Невозможно перехватить сигналы в скрипте точки входа docker - PullRequest
2 голосов
/ 13 марта 2020

У меня есть docker скрипт точки входа, который должен перехватывать сигналы, отправляемые процессам в контейнере. Основным приложением является tomcat - java процесс, встроенный в docker -входную точку. sh, который передается в dumb-init. Отображение процесса в контейнере выглядит так:

root@mycontainer:/usr/local/tomcat/webapps/datarouter-example# ps -ef
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         1     0  0 05:21 ?        00:00:00 dumb-init -- /docker-entrypoint.sh
    root         6     1  0 05:21 ?        00:00:00 bash /docker-entrypoint.sh
    root        14     6  1 05:21 ?        00:08:57 /jdk-13.0.1/bin/java -Djava.util.logging.config.file=....

Dockerfile:

FROM maven:3.6.3-jdk-13 as maven_builder

WORKDIR /app
COPY . /app
RUN ["mvn","clean","install","-T","2C","-DskipTests=true"]


FROM tomcat:9.0.31-jdk13-openjdk-buster

ARG dumbInitVersion='1.2.2'

# install dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        sudo \
        wget \
        dpkg-dev \
    && rm -rf /var/lib/apt/lists/*

ARG webappDir
WORKDIR $CATALINA_HOME/webapps/$webappDir/
ENV CATALINA_OUT $CATALINA_HOME/logs/catalina.out
ENV CATALINA_PID $CATALINA_HOME/catalina.pid
COPY docker-entrypoint.sh /
COPY --from=maven_builder /app/target/datarouter-example $CATALINA_HOME/webapps/$webappDir/

RUN wget https://github.com/Yelp/dumb-init/releases/download/v"$dumbInitVersion"/dumb-init_"$dumbInitVersion"_amd64.deb; \
    dpkg -i dumb-init_*.deb; \
    rm dumb-init_*.deb

EXPOSE 8080
ENTRYPOINT ["dumb-init", "--", "/docker-entrypoint.sh"]

И это упрощенная docker -входная точка. sh:

        #!/usr/bin/env bash

        start(){
                echo "$(date +'%F %T,%3N') Starting tomcat..." >> "$CATALINA_OUT"
                catalina.sh start && tail -f "$CATALINA_OUT"
        }

        stop(){
                echo "$(date +'%F %T,%3N') starting stop" >> "$CATALINA_OUT"

   # some fancy shutdown logic, e.g. calling our application's shutdown endpoint to cleanup (does not stop tomcat)

                echo "$(date +'%F %T,%3N') Stopping tomcat..." >> "$CATALINA_OUT"
                catalina.sh stop  >> "$CATALINA_OUT"

                wait $(cat "${CATALINA_PID}")

                tailId=$(pgrep tail)
                if [[ -n "$tailId" ]]; then
                        kill "$tailId"
                fi
                exit
        }

        trap stop SIGINT SIGQUIT SIGHUP SIGTERM

    start

Теперь вопрос. Каждый раз, когда выдается команда docker stop или kill 1 изнутри контейнера, приложению java отправляется сигнал, и он сначала выключается, прежде чем функция stop попадает даже в первую строку. Я уверен, что из-за Terminated log:

Terminated
++ stop
+++ date '+%F %T,%3N'
++ echo '2020-03-13 14:34:54,480 starting stop'

и в catalina.out:

2020-03-12 04:08:27.079 INFO [Thread-13] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-apr-8080"]
2020-03-12 04:08:27,079 starting stop
2020-03-12 04:08:27.085 INFO [Thread-13] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-apr-8081"]
2020-03-12 04:08:27.090 INFO [Thread-13] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["https-openssl-apr-8443"]
2020-03-12 04:08:27.096 INFO [Thread-13] org.apache.catalina.core.StandardService.stopInternal Stopping service [Catalina]
......

Я действительно не понимаю, почему это происходит и как это исправить чтобы выполнить catalina.sh stop.

1 Ответ

0 голосов
/ 16 марта 2020

После нескольких изменений следующий скрипт перехватывает SIGTERM и выполняет ожидаемые шаги.

Изменения от исходного docker -входного пункта, Dockerfile:

  • Переключено с немого -init to tini, просто чтобы попробовать.
  • Переключился с каталитического запуска на каталиновый запуск и поставил его в фоновом режиме и жду на нем
  • Удален хвостовой процесс

Я думаю, что хвост был причиной первоначального описанного поведения. Самым большим недостатком нового сценария точки входа является то, что я потерял журналы контейнеров при запуске docker logs .... Так как мы связываем монтируем каталог журналов, мы все еще можем получить журналы, но продолжим исследование, чтобы получить обратно docker logs ...

Я все еще в поиске более хорошего решения, если у кого-то есть совет или другие решения.

#!/usr/bin/env bash

trap stop SIGTERM SIGINT SIGQUIT SIGHUP ERR

start(){
   local catalinaPid

   touch "${CATALINA_PID}"
   catalina.sh run >> ${CATALINA_OUT} 2>&1 &
   catalinaPid=$!
   echo "$catalinaPid" > "${CATALINA_PID}"

   wait "$catalinaPid"
}

stop(){
   echo "$(date +'%F %T,%3N') starting stop" >> "$CATALINA_OUT"

   # some fancy shutdown logic, e.g. calling our application's shutdown endpoint to cleanup (does not stop tomcat)

   echo "$(date +'%F %T,%3N') Stopping tomcat..." >> "$CATALINA_OUT"
   catalina.sh stop 20 >> "$CATALINA_OUT"

   wait $(cat "${CATALINA_PID}")

   exit
}

start
...