Перенаправление выходных данных скрипта в журналы docker

#javascript #node.js #docker #logging

#javascript #node.js #docker #ведение журнала

Вопрос:

У меня есть node.js скрипт, запущенный в контейнере node docker, который в данный момент сбрасывает свои выходные данные в файл журнала внутри контейнера и стандартный вывод. Многие официальные образы docker позволяют запускать docker logs container , чтобы увидеть ошибки всего, что выполняется в этом контейнере.

Я вижу много ссылок на то, что Docker просто фиксирует вывод STD, и это то, что docker logs container видит, но я не могу найти никакой документации о том, как правильно настроить это из скрипта, запущенного в контейнере.

В настоящее время мой Dockerfile настроен для разработки, причем последняя строка является

 ENTRYPOINT [ "npm", "run", "watch"]
  

который просматривает мои файлы на предмет изменений для запуска сценария сборки в контейнере. Таким образом, для разработки я в настоящее время использую docker exec -it container /bin/sh и выполняю скрипт вручную.

Когда я использую docker logs container , я вижу ошибки из цепочки сборки npm, но ничего из моего скрипта при запуске его вручную из контейнера.

Мой скрипт использует

 process.stdout.write(data)
process.stderr.write(data)
  

Прежде чем я полностью переделаю свой Dockerfile для своего скрипта, прав ли я, полагая, что он docker logs перенаправляет STDOUT и STDERR из процесса с PID 1, но не любых других процессов, запущенных с другими PID?

И если я хочу записать выходные данные моего скрипта, используя docker logs это просто случай изменения ENTRYPOINT , чтобы он запускал мой скрипт напрямую?

 ENTRYPOINT [ "node", "myscript" ]
  

Ответ №1:

Ваше предположение близко — Docker регистрирует выходные данные из любого процесса, который использовался для запуска контейнера. Это действительно PID 1, но некоторые контейнеры будут использовать «поддельный» процесс инициализации, поэтому основной процесс не запускается как таковой (например, Tini), что также имеет место при использовании docker run --init .

В вашем случае, если вы docker exec заходите в контейнер и выполняете команды, выходные данные не будут регистрироваться, потому что они отправляются в ваш сеанс командной оболочки. Если вы измените свой ENTRYPOINT на прямой запуск вашего скрипта, то Docker увидит выходные данные вашего скрипта.

В качестве альтернативы, если вы хотите отправить выходные данные сборщику журналов контейнера без изменения точки входа в контейнер, вы можете отправить выходные данные в потоки stdio с идентификатором PID 1 внутри контейнера. Например, для отправки выходных данных в стандартный вывод PID 1:

 $ docker exec -it $RUNNING_CONTAINER bash
container$ echo test >> /proc/1/fd/1          # fd/1 for stdout
  

Комментарии:

1. Этот ответ отличный, за исключением того, что вывод должен быть направлен в /proc / 1 / fd / 1 (стандартный вывод), а не в / proc / 1 / fd / 0 (стандартный вывод)

2. Есть ли способ вместо этого записать журналы docker в файл внутри контейнера?

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