Есть приложение, которое включает в себя 5 Docker-контейнеров.
Для наблюдения за логами используется Loggly, но мне он жутко неудобен — в консоли логи удобнее смотреть и грепать.
Запущенное приложение выглядит так:
ubuntu@ip-10-5-3-54:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 63937e07a5cf tag-docker.jfrog.io/api-gateway:staging-test-eureka-cloud-versioning-124 "java -Djava.security" 30 minutes ago Up 30 minutes 0.0.0.0:8080->8080/tcp peaceful_blackwell cbf2394197bc tag-docker.jfrog.io/producers:staging-test-eureka-cloud-versioning-124 "java -Djava.security" 30 minutes ago Up 30 minutes 0.0.0.0:8090->8090/tcp cocky_nobel 1884543d61b1 tag-docker.jfrog.io/configuration:staging-test-eureka-cloud-versioning-124 "java -Djava.security" 30 minutes ago Restarting (1) 2 minutes ago 0.0.0.0:8084->8084/tcp kickass_kirch 65be0b7bb07e tag-docker.jfrog.io/profile:staging-test-eureka-cloud-versioning-124 "java -Djava.security" 30 minutes ago Up 30 minutes 0.0.0.0:8083->8083/tcp nauseous_kowalevski 947a92a1a629 tag-docker.jfrog.io/oauth2-authserver:staging-test-eureka-cloud-versioning-124 "java -Djava.security" 30 minutes ago Up 30 minutes 0.0.0.0:9999->9999/tcp nauseous_wescoff
Задача скрипта — создать файл лога для каждого сервиса и начать в него писать STDERR и STDOUT из контейнера.
Сам скрипт:
#!/usr/bin/env bash
# To catch STDERR and STDOUT from each Docker container with $API_SERVICES
# to a propriate log file from $API_LOGS
# run: tail -f *.log to watch them
# объявляем два именованных массива
declare -A API_SERVICES
declare -A API_LOGS
# наполняем их
API_SERVICES=( [GATEWAY]=api-gateway \
[PRODUCERS]=producers \
[CONFIGURATION]=configuration \
[PROFILE]=profile \
[AUTHSERVER]=oauth2-authserver )
API_LOGS=( [GATEWAY]=gateway.log \
[PRODUCERS]=producers.log \
[CONFIGURATION]=configuration.log \
[PROFILE]=profile.log \
[AUTHSERVER]=authserver.log )
# получаем имя ключа из массива (GATEWAY и т.д.)
for service in ${!API_SERVICES[@]}; do
# используя имя ключа в виде имени сервиса - получаем значение этой пары ключ-значение
# например, для GATEWAY - это будет api-gateway
# по значению находим контейнер (grep), и получаем его ID (awk - print первое поле)
container_id=$(docker ps | grep ${API_SERVICES[$service]} | awk '{print $1}')
# используя имя ключа в виде имени сервиса - находим в массиве API_LOGS значение
# например, для GATEWAY - это будет gateway.log
log_name=${API_LOGS[$service]}
echo Service: $service Container ID: $container_id Log file: $log_name
# и используя $container_id (666555444) и $log_name (gateway.log)
# выполняем docker logs -f перенаправляя STDERR и STDOUT в соответствующий файл
docker logs -f $container_id >> $log_name 2>&1 &
done
Запускаем:
ubuntu@ip-10-5-3-54:~$ ./logs.sh Service: CONFIGURATION Container ID: 1884543d61b1 Log file: configuration.log Service: PROFILE Container ID: 65be0b7bb07e Log file: profile.log Service: PRODUCERS Container ID: cbf2394197bc Log file: producers.log Service: GATEWAY Container ID: 63937e07a5cf Log file: gateway.log Service: AUTHSERVER Container ID: 947a92a1a629 Log file: authserver.log
Проверяем:
ubuntu@ip-10-5-3-54:~$ tail -f *.log
==> authserver.log <==
profile: 15:46:40.248 o.a.tomcat.util.net.NioSelectorPool - Using a shared selector for servlet write/read
==> configuration.log <==
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
at
==> gateway.log <==
profile: 16:05:11.247 o.s.b.a.e.mvc.EndpointHandlerMapping - Returning handler method [public java.lang.Object
...
Готово.