【问题标题】:In testing.postgresql, cannot find initdb command inside Docker在 testing.postgresql 中,在 Docker 中找不到 initdb 命令
【发布时间】:2019-09-23 21:59:21
【问题描述】:

有一个similar thread 有同样的问题,但无法为我工作。基本上,我正在尝试使用 testing.postgresqlmyproject 进行单元测试,并且我在 docker 容器中运行它。

但是,当我运行我的命令时,我得到了 RuntimeError: command not found: initdb

docker-compose exec myproject python3 -m unittest

这适用于 WSL,但不适用于 docker。

看起来它无法找到 initdb。是否与在 docker-compose.yml 中创建的数据库存在冲突问题,还是我在 docker 文件中缺少某些行?

我从docs 中概述了我的测试示例:

class TestPostgresqlInteraction(unittest.TestCase):

    Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True)

    with testing.postgresql.Postgresql() as postgresql:
        engine = create_engine(postgresql.url())
        dbConn = psycopg2.connect(**postgresql.dsn())
        cursor = dbConn.cursor()
        def setUp(self):
            self.postgresql = self.Postgresql()

        def tearDown(self):
            self.postgresql.stop()

        def testMethod(self)
            conn = psycopg2.connect(**self.postgresql.dsn())
            cursor = conn.cursor()
            # execute cursor and do tests... 

        def tearDownModule(self):
            self.Postgresql.clear_cache()

docker-compose.yml

version: "3"
services:
    myproject:
        build:
            context: .
            dockerfile: ./myproject/Dockerfile
        depends_on:
            - database
        volumes:
            - ./myproject:/code
        stdin_open: true
        tty: true
    database:
        build:
            context: .
            dockerfile: ./database/Dockerfile
        environment:
            POSTGRES_USER_FILE: /secrets/dbUser.txt
            POSTGRES_PASSWORD_FILE: /secrets/dbPassword.txt
        ports:
            - "8765:5432"
        volumes:
            - otherdata:/var/lib/postgresql/data

我的项目/Dockerfile

FROM python:3.7.3-stretch

RUN apt-get update && apt-get install -y \
    poppler-utils

ARG moduleDir=myproject

WORKDIR /code

COPY secrets/ /secrets

# COPY $moduleDir/myproject/ ./

COPY $moduleDir/requirements.txt requirements.txt

RUN pip install -r requirements.txt

数据库/Dockerfile

FROM postgres:11.3

WORKDIR /secrets

COPY secrets/dbUser.txt dbUser.txt
COPY secrets/dbPassword.txt dbPassword.txt

RUN mkdir -p /docker-entrypoint-initdb.d

COPY database/schema.sql /docker-entrypoint-initdb.d

追溯:

ImportError: Failed to import test module: tests.testMyproject
  File "/usr/local/lib/python3.7/unittest/loader.py", line 436, in _find_test_path
    module = self._get_module_from_name(name)
  File "/usr/local/lib/python3.7/unittest/loader.py", line 377, in _get_module_from_name
    __import__(name)
  File "/code/tests/testmyProject.py", line 40, in <module>
    class TestPostgresqlInteraction(unittest.TestCase):
  File "/code/tests/testmyProject.py", line 46, in TestPostgresqlInteraction
    Postgresql = testing.postgresql.PostgresqlFactory(cache_initialized_db=True)
  File "/usr/local/lib/python3.7/site-packages/testing/common/database.py", line 52, in __init__
    self.cache = self.target_class(**settings_noautostart)
  File "/usr/local/lib/python3.7/site-packages/testing/common/database.py", line 92, in __init__
    self.initialize()
  File "/usr/local/lib/python3.7/site-packages/testing/postgresql.py", line 50, in initialize
    self.initdb = find_program('initdb', ['bin'])
  File "/usr/local/lib/python3.7/site-packages/testing/postgresql.py", line 144, in find_program
    raise RuntimeError("command not found: %s" % name)
RuntimeError: command not found: initdb

【问题讨论】:

    标签: python postgresql unit-testing docker


    【解决方案1】:

    使用testing.postgresql 意味着您将获得由该工具准备的新PG 实例——正如docs 中所述。您需要做的是指向另一个 docker。只需使用psycopg 并连接到database

    dsn = "dbname='" + RDS_DBNAME + "' user='" + RDS_USERNAME + "' host='database' password='" + RDS_PASSWORD + "'"
    dbConn = psycopg2.connect(dsn)
    

    除此之外 - 你with 看起来很奇怪。但这只是我的印象。

    【讨论】:

    • RDS_DBNAMERDS_USERNAMERDS_PASSWORD指的是我在secrets/目录中定义的内容吗?
    • @resolute - 是的RDS_DBNAMEschema.sql 创建的数据库的名称,要到达那里,您需要凭据、来自dbUser.txt 的用户和来自dbPassword.txt 的密码:)跨度>
    【解决方案2】:

    您的 Docker 容器可能缺少 which shell 命令。

    testing.postgresql调用testing.common.database.get_path_of,然后执行which命令定位initdb程序:

    def get_path_of(name):
        if os.name == 'nt':
            which = 'where'
        else:
            which = 'which'
        try:
            path = subprocess.Popen([which, name],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE).communicate()[0]
            if path:
                return path.rstrip().decode('utf-8')
            else:
                return None
        except Exception:
            return None
    

    如果缺少which,您可以使用包管理器添加它。这适用于我基于 CentOS 的容器:

    yum install which

    【讨论】:

      【解决方案3】:

      要使用testing.postgresql,您需要在myproject Docker 中访问postgresql 服务器,而不仅仅是在database Docker 中。本地临时测试数据库将连接到其他数据库以获取数据,但这仍然意味着您需要在 myproject 中使用本地 postgresql 服务器实例。

      在您的myproject/Dockerfile 中,只需更改第一个RUN 并在poppler-utils 之后添加postgresql

      【讨论】:

        猜你喜欢
        • 2020-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-01
        • 2018-02-02
        • 2021-06-12
        • 2019-04-12
        • 1970-01-01
        相关资源
        最近更新 更多