首页 > 解决方案 > 通过docker连接数据库

问题描述

我知道这是一个有很多答案的问题,但我尝试过的都没有解决我的问题。我正在使用这个 Dockerfile 创建一个测试数据库:

FROM postgres
ENV POSTGRES_USER postgres
ENV POSTGRES_PASSWORD postgres
ENV POSTGRES_DB training_db
COPY create_test_database.sql /docker-entrypoint-initdb.d/
docker build -t my-postgres-image .
docker run -d --name training-db my-postgres-image
docker start training-db

创建并启动后,我可以通过 dbeaver 访问它,但不能从另一个项目访问它,Dockerfile 如下所示:

FROM 613615412341.dkr.ecr.ap-southeast-2.amazonaws.com/cv-image:latest

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Minsk
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt-get update && apt-get install -y \
        python3-dev \
        python3-tk \
        python3-pip \
        libglib2.0-0\
        libsm6 \
        postgresql-server-dev-all \
        postgresql-common \
        openssh-client \
        libxext6 \
        nano \
        pkg-config \
        rsync \
        && \
    apt-get clean && \
    apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

RUN apt update && apt install -y git pkg-config libgl1-mesa-glx tcl libopencv-dev python-opencv

RUN pip3 install  --upgrade  setuptools
RUN pip3 install numpy
ADD requirements.txt /requirements.txt
RUN pip3 install -r /requirements.txt && rm /requirements.txt

ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8

ADD . /code
WORKDIR /code

RUN echo $(ip -4 route list match 0/0 | cut -d' ' -f3)

使用 docker-compose:

  version: '2.3'
  services:
    training_pipeline:
      build:
        context: .
        dockerfile: Dockerfile.service
      runtime: nvidia
      environment:
        - AWS_DEFAULT_REGION=ap-southeast-2
        - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
        - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}

      network_mode: host
      ports:
        - "5432:5432"
      entrypoint: ["python3", "main.py"]
   training-db:
     image: postgres
     environment:
       POSTGRES_PASSWORD: postgres
       POSTGRES_USER: postgres
       POSTGRES_DB: training_db
     volumes:
       - postgres:/var/lib/postgresql/data
  volumes:
    postgres:

但是,我不断得到:

training_pipeline_1  |     args.func(args)  # call the default function
training_pipeline_1  |   File "/code/functions.py", line 46, in label_batch
training_pipeline_1  |     pre_labeling = PreLabeling(site, connection_config, detector_config)
training_pipeline_1  |   File "/code/pre_label/label.py", line 43, in __init__
training_pipeline_1  |     connection_config, set_isolation_level=True, set_profiles=True
training_pipeline_1  |   File "/code/helpers/data_base_connection.py", line 37, in __init__
training_pipeline_1  |     database=config["database"],
training_pipeline_1  |   File "/usr/local/lib/python3.6/dist-packages/psycopg2/__init__.py", line 127, in connect
training_pipeline_1  |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
training_pipeline_1  | psycopg2.OperationalError: could not connect to server: Connection refused
training_pipeline_1  |  Is the server running on host "172.17.0.1" and accepting
training_pipeline_1  |  TCP/IP connections on port 5432?

这是我的数据连接器类的片段(跳过不必要的方法):

import logging
from typing import Any, Dict, List, Optional

import psycopg2




class DataBaseConnection:
    """
    Class to perform transactions with training database.
    """


    def __init__(
        self,
        config: dict,
    ):
        """
        Args:
            config: configuration file to connect to the database where annotations are stored.
        """
        self._connection = psycopg2.connect(
            user=config["user"],
            password=config["password"],
            host=config["host"],
            port=config["port"],
            database=config["database"],
        )
        self._cursor = None
        self._next = None

if __name__=="__main__":
    config = {
       "database": "training_db",
       "host": "172.17.0.1",
       "password": "postgres",
       "port": 5432,
       "user": "postgres"
    }
    data_connector: DataBaseConnection = DataBaseConnection(
        config
    )
    

标签: pythonpostgresqldocker

解决方案


如我所见,您有 2 个容器

  • 一个用于数据库(training-db)
  • 一个用于应用程序(培训管道)

Docker-compose 允许你在同一个网络中运行多个容器,它为你创造了魔力。最简单的方法是更新 docker-compose 以包含数据库:

版本:'2.3'
服务:
  培训管道:
    建造:
      语境: 。
      dockerfile: Dockerfile.service
    运行时:英伟达
    环境:
      - AWS_DEFAULT_REGION=ap-southeast-2
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}

    网络模式:主机
    端口:
      - “5432:5432”
    入口点:[“python3”,“main.py”]
  训练数据库:
    图片:postgres
    环境:
      POSTGRES_PASSWORD:我的密码
      POSTGRES_USER:我的用户
      POSTGRES_DB:mydb
    卷:
      - postgres:/var/lib/postgresql/data

卷:
  postgres:

您可以使用以下命令启动数据库:docker-compose up -d training-db. 而且,在 python 中,数据库将与 DNS 一起使用training-db

另一种解决方案是手动创建一个网络并在网络内运行您的容器:

docker network create training-network
docker run -d --name training-db --net training-network my-postgres-image

并且,在 docker-compose 文件中,将网络添加为外部(别名,不由 compose 管理):

version: '2.4'
services:
  training_pipeline:
    [...]
    networks:
      - training-network

networks:
  training-network:
    external: true

推荐阅读