在官方的Postgres Docker镜像中记录所有查询

101

我有一个基于Postgres官方docker映像的docker容器。我希望在使用docker logs -f查看docker容器日志时能够看到传入的查询语句。下面是我的Dockerfile:

FROM postgres:11.1-alpine

COPY mock_data.sql /docker-entrypoint-initdb.d/mock_data.sql

ENV PGDATA=/data

以下是我docker-compose.yml文件中与此服务相关的部分:

version: '3'
services:
  mock_data:
    image: mock_data
    container_name: mock_data
    ports:
         - 5434:5432/tcp

如何在Docker日志中最简单地包含传入的查询?

5个回答

175

如果使用Docker Compose,您可以将此行添加到您的docker-compose.yaml文件中:

command: ["postgres", "-c", "log_statement=all"]

并且所有的查询都会被写入容器日志文件。


52

log_destination 设置为 stderr 对我有用,而不需要创建新的镜像:

version: "2.2"
services:
  db:
    image: postgres:12-alpine
    command: ["postgres", "-c", "log_statement=all", "-c", "log_destination=stderr"]

然后我使用docker-compose logs -f db追踪这些语句。应该也适用于其他版本,但我只在postgres:12-alpine上进行了测试。


7
"log_destination=stderr" 不是必需的,因为默认的目标地是 "stderr"。请参考 - https://www.postgresql.org/docs/current/runtime-config-logging.html - Ashishkumar Pandey
你是否使用 postgres:12-alpine 镜像进行测试了?因为我记得在2019年12月这样做并没有起作用... - Florian Fida
是的,我正在使用 postgre:12.3-alpine - Ashishkumar Pandey
遇到了postgres:12.3(PostgreSQL 12.3(Debian 12.3-1.pgdg100+1))的问题。升级到postgres:12.4解决了我的问题。 - Jonas Knobloch

37

如果直接从Docker命令运行docker run,尝试以下命令:

docker run -d -e POSTGRES_USER=user -e POSTGRES_PASSWORD=pass -e POSTGRES_DB=postgres -p 5432:5432 --name db postgres:10 postgres -c log_statement=all

尾随部分是覆盖命令,如此处所述覆盖docker文件

祝好运!


-c log_statement=all 对我来说完美无缺。它完全符合我的需求。 - undefined

13

参考这篇文章,您应该启用logging_collector,然后您就可以在log_directorylog_filename中看到传入的查询。

为了在docker logs中启用它,您需要进行一些技巧操作,其中一种解决方案如下:

wrapper.sh:

#!/usr/bin/env bash
mkdir /logs
touch /logs/postgresql.log
chmod -R 777 /logs
tail -f /logs/* &
/docker-entrypoint.sh "$@"

上述代码将使用 tail 监控 /logs/postgresql.log,这将被 postgresqllogging_collector 使用,并在 docker logs 中显示。 Dockerfile:
FROM postgres:11.1-alpine
COPY wrapper.sh /
RUN chmod +x /wrapper.sh
ENTRYPOINT ["/wrapper.sh"]
CMD ["postgres", "-c", "logging_collector=on", "-c", "log_directory=/logs", "-c", "log_filename=postgresql.log", "-c", "log_statement=all"]

上面将使用定制的 wrapper.sh,它将首先监视 postgre 日志,打印出来,然后继续执行默认的 docker-entrypoint.sh 来启动 postgresql 服务器。
容器启动后,在进入查询之前显示日志:
orange@orange:~/abc$ docker build -t abc:1 .
orange@orange:~/abc$ docker run -idt abc:1
orange@orange:~/abc$ docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS               NAMES
c9112eb785e5        abc:1                  "/wrapper.sh postgre…"   2 seconds ago       Up 1 second         5432/tcp            loving_joliot
orange@orange:~/abc$ docker logs loving_joliot
The files belonging to this database system will be owned by user "postgres".
......
2019-07-13 03:38:14.030 UTC [46] LOG:  database system was shut down at 2019-07-13 03:38:13 UTC
2019-07-13 03:38:14.034 UTC [10] LOG:  database system is ready to accept connections

模拟一些传入的查询,并再次查看日志:

orange@orange:~/abc$ docker exec -it -u postgres loving_joliot psql -c "SELECT datname FROM pg_database;"
  datname
-----------
 postgres
 template1
 template0
(3 rows)
orange@orange:~/abc$ docker logs loving_joliot
The files belonging to this database system will be owned by user "postgres".
......
2019-07-13 03:38:14.030 UTC [46] LOG:  database system was shut down at 2019-07-13 03:38:13 UTC
2019-07-13 03:38:14.034 UTC [10] LOG:  database system is ready to accept connections
2019-07-13 03:41:22.859 UTC [62] LOG:  statement: SELECT datname FROM pg_database;

你可以看到,上面我们模拟了一个 SQL 执行 SELECT datname FROM pg_database;,在 docker logs 中我们已经可以看到这个 SQL。

wrapper.sh 文件中的这一行是做什么用的? /docker-entrypoint.sh "$@" 因为它会出现错误 /docker-entrypoint.sh: not found - uberrebu
这是基础镜像postgres:11.1-alpine中的默认入口点:docker run --rm postgres:11.1-alpine ls -alh /docker-entrypoint.shlrwxrwxrwx 1 root root 34 Feb 5 2019 /docker-entrypoint.sh -> usr/local/bin/docker-entrypoint.sh。但是,如果默认的postgres镜像具有log_statement功能(我当时不知道),那么接受的答案已经包含了此日志记录的嵌入式功能,因此使用接受的答案就足够了。 - atline
我能够获取实时日志,而无需像你那样创建入口脚本。只需要设置 log_statement=allpg_stat_statements.track = all 即可,这对于 postgres:13 就足够了。 - uberrebu
是的<就像被接受的答案一样,请移步到那个答案。 - atline

11
根据官方Postgres镜像的文档(数据库配置部分),您可以执行以下操作:
  • 注入自定义配置文件(例如通过调整默认配置文件)或
  • 启动容器并设置所需的配置参数。
在后一种情况下,只需使用以下命令启动容器:
$ docker run -d --name some-postgres postgres -c log_statement=all

它利用覆盖Dockerfile镜像默认值

如果您想启用其他日志记录选项,请查看PostgreSQL文档的错误报告和日志记录部分


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接