Skip to content

Bug: postgres container expects English log line to ensure started #695

@dhofstetter

Description

@dhofstetter

Describe the bug

When starting a Postgres Testcontainer, the implementation expects a log line like the latter to ensure its properly started

.*database system is ready to accept connections.*

In case you have a custom Postgres image (e.g. with lang/locales changed) this log line might not appear as expected.

To Reproduce

FROM postgres:16

RUN locale-gen de_AT.utf8 \
    && localedef -i de_AT -c -f UTF-8 -A /usr/share/locale/locale.alias de_AT.UTF-8
ENV LANG=de_AT.utf8

use the dockerfile above, and the log lines are more like

2024-09-03 15:35:48.551 UTC [1] LOG:  erwarte Verbindungen auf IPv4-Adresse »0.0.0.0«, Port 5432
2024-09-03 15:35:48.551 UTC [1] LOG:  erwarte Verbindungen auf IPv6-Adresse »::«, Port 5432
2024-09-03 15:35:48.554 UTC [1] LOG:  erwarte Verbindungen auf Unix-Socket »/var/run/postgresql/.s.PGSQL.5432«
2024-09-03 15:35:48.557 UTC [63] LOG:  Datenbanksystem wurde am 2024-09-03 15:35:48 UTC heruntergefahren
2024-09-03 15:35:48.561 UTC [1] LOG:  Datenbanksystem ist bereit, um Verbindungen anzunehmen

I think that using pg_isready is sufficient - so changing the code of PostgresContainer to

@wait_container_is_ready()
    def _connect(self) -> None:
        # postgres itself logs these messages to the standard error stream:
        #
        # $ /opt/homebrew/opt/postgresql@14/bin/postgres -D /opt/homebrew/var/postgresql@14 \
        # > | grep -o -a -m 1 -h 'database system is ready to accept connections'
        # 2024-08-03 00:13:02.799 EDT [70226] LOG:  starting PostgreSQL 14.11 (Homebrew) ....
        # 2024-08-03 00:13:02.804 EDT [70226] LOG:  listening on IPv4 address "127.0.0.1", port 5432
        # ...
        # ^C2024-08-03 00:13:04.226 EDT [70226] LOG:  received fast shutdown request
        # ...
        #
        # $ /opt/homebrew/opt/postgresql@14/bin/postgres -D /opt/homebrew/var/postgresql@14 2>&1 \
        # > | grep -o -a -m 1 -h 'database system is ready to accept connections'
        # database system is ready to accept connections
        #
        # and the setup script inside docker library postgres
        # uses pg_ctl:
        # https://github.com/docker-library/postgres/blob/66da3846b40396249936938ee17e9684e6968a57/16/alpine3.20/docker-entrypoint.sh#L261-L282
        # which prints logs to stdout:
        # https://www.postgresql.org/docs/current/app-pg-ctl.html#:~:text=the%20server%27s%20standard%20output%20and%20standard%20error%20are%20sent%20to%20pg_ctl%27s%20standard%20output
        #
        # so we must wait for both the setup and real startup:
        predicate_streams_and = True

        # as the wait for logs is commented out, we can start all kinds of containers (even non English ones)
        #wait_for_logs(
        #    self,
        #    ".*database system is ready to accept connections.*",
        #    c.max_tries,
        #    c.sleep_time,
        #    predicate_streams_and=predicate_streams_and,
        #    #
        #)

        count = 0
        while count < c.max_tries:
            status, _ = self.exec(f"pg_isready -hlocalhost -p{self.port} -U{self.username}")
            if status == 0:
                return

            sleep(c.sleep_time)
            count += 1

        raise RuntimeError("Postgres could not get into a ready state")

works like a charm.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions