【问题标题】:How to get access to a containerized postgresql database from outside / apps如何从外部/应用程序访问容器化的 postgresql 数据库
【发布时间】:2020-10-11 12:44:31
【问题描述】:

我一直在努力从本地主机和外部连接到 postgresql 容器。

这是一个非常不错的演示,它在https://linuxhint.com/postgresql_docker/ 上演示的效果非常好。下面是 docker-compose.yml,postgres:12.2 和 pgadmin 通过它被容器化并运行。事实上,在运行 docker-compose.yml 文件(通过 docker-compose up -d)之后,它们就可以工作了。

然后您可以在浏览器中访问 http://localhost:8080/ 并直接访问 pgadmin(使用给定的凭据,即 admin@linuxhint.com、secret)并开始在您的 postgres:12.2 安装上运行在码头上。

但是,当我尝试直接从 localhost 或外部/某些应用程序/ip(如 Java Spring Boot)找到与此 postgres:12.2 数据库的连接时,我的困难就开始了。

诚然,我不是 docker 方面的专家,只是一名学生——所以,我寻求帮助。希望有人可以告诉我应该做些什么来使从外部/应用程序连接到(这个)容器化 postgres 数据库成为可能。我正在使用 Win 10。

更新:

  • 谁能说出为什么一个网络应用(添加到 docker.compose.yml,见下文)在启动后持续关闭?

  • docker logs 给出以下错误:

    原因:org.springframework.beans.factory.BeanCreationException:在类路径资源 [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class] 中定义名称为“dataSource”的 bean 创建错误:bean 的初始化失败的;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker' 的 bean 时出错:调用 init 方法失败;嵌套异常是 org.springframework.jdbc.datasource.init.UncategorizedScriptException: 无法执行数据库脚本;嵌套异常是 org.springframework.jdbc.CannotGetJdbcConnectionException: 获取 JDBC 连接失败;嵌套异常是 org.postgresql.util.PSQLException: Connection to localhost:5433 denied。检查主机名和端口是否正确,以及 postmaster 是否接受 TCP/IP 连接。

  • 这里是应用的 Dockerfile

    来自 maven:3-jdk-11

    音量/tmp

    暴露 8095

    添加/target/spring-boot-demo-0.0.1-SNAPSHOT.jar app.jar

    运行 ls -ls

    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

  • 这是 application.properties 文件中的连接详细信息:

    spring.datasource.url=jdbc:postgresql://db:5432/postgres

    spring.datasource.username=admin

    spring.datasource.password=secret

  • 另外两个服务(db和pgadmin正常启动)

docker-compose.yml

version: "3.7"

services:

# ========== ADDED APP ===============
 web:
   #restart: on-failure
   image: app-springboot-postgresql
   build: ./
   ports:
     - "8095:8095"
   environment:
     WAIT_HOSTS: postgres:5432
   depends_on:
    - db  
# ========== ADDED APP ===============

  db:
    image: postgres:12.2
    restart: always
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      PGDATA: /var/lib/postgresql/data
    volumes:
      - db-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
 
  pgadmin:
    image: dpage/pgadmin4:4.18
    restart: always
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@linuxhint.com
      PGADMIN_DEFAULT_PASSWORD: secret
      PGADMIN_LISTEN_PORT: 80
    ports:
      - "8080:80"
    volumes:
      - pgadmin-data:/var/lib/pgadmin
    links:
      - "db:pgsql-server"

volumes:
  db-data:
  pgadmin-data:

【问题讨论】:

  • 你不能用容器名连接吗?
  • 仅表示我已经能够连接到容器化的 postgresql(如上面在 yml 文件中定义的那样)是:“docker-compose run db bash”。然后:“psql -h db -U admin -d postgres”和“用户管理员密码:secret”。
  • 来自错误:Connection; nested exception is org.postgresql.util.PSQLException: Connection to localhost:5433 refused. 你在 5433 上配置了 postgresql,从 yaml 你在 5432 上启动它
  • Edwin,你是对的,错误信息和代码不一致。该错误与我在下面的评论中报告的一些奇怪的内存更新错误有关。感谢您的敏锐观察。

标签: postgresql docker docker-compose


【解决方案1】:

docker-compose.yml 将 Postgres 的 5432 端口发布到运行 docker daemon 的机器上。

所以应用程序应该连接到 127.0.0.1 作为 Postgres 主机和 5432 作为 Postgres 端口,假设它们在机器上运行。

【讨论】:

  • 通过这个我可以从本地主机连接:psql -h 127.0.0.1 -p 5432 -U postgres,但连接不会转到容器化 postgresql 中的应用程序(即上面 yml 文件中定义的那个)但相反,它打开了与本地非容器化 postgresql 的连接。
  • 如果您在docker-compose.yml文件所在的文件夹中成功运行docker-compose up命令,则容器化Postgres的容器化Postgres端口5432映射到docker主机(您运行docker守护程序的机器)的端口5432当您以发布的方式运行 psql 时,您将连接到容器化 Postgres
  • 我可以成功运行“docker-compose up”(在同一个文件夹中),然后如果我运行“psql -h 127.0.0.1 -p 5432 -U postgres”,我只能连接到我的非容器化数据库(与容器化数据库中的数据库和表完全不同)。如果将用户名更改为 admin 并使用相应的密码(这些是 docker-compose.yml 文件中给出的凭据)并且当我运行 psql -h 127.0.0.1 -p 5432 -U admin 时,就会出现密码提示我收到错误:无法连接到服务器:致命:用户“admin”的密码验证失败。
  • 如果您在主机上运行单独的 PostgreSQL,则需要更改已发布的ports:;仅将第一个数字更改为某个不同的端口,例如 5433:5432。但是,如果存在主机端口冲突,我希望您在启动时会遇到问题。你在运行 Docker Toolbox 还是 Docker Desktop?
  • 我如何知道我运行的是 Docker Toolbox 还是 Docker Desktop?
【解决方案2】:

检查它们是否在同一个网络中:

docker network ls

# Output

NETWORK ID          NAME                DRIVER              SCOPE
e094bb99be32        bridge              bridge              local
cde9fb0d3fef        django              bridge              local
1aeb83753889        host                host                local
f152a346ca96        none                null                local
348c59c37462        web                 bridge              local

然后检查网络:

docker network inspect django

# Output

[
    {
        "Name": "django",
        "Id": "6f5fd395946d1bff8583a4ddbe4fb8ea1204875124679f878d24a57f3601b0e6",
        "Created": "2020-10-11T13:16:42.750571609+02:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.20.0.0/16",
                    "Gateway": "172.20.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "079d303b3c2d17196e7cb49056ec7cfc7385c480c3cbf225dc51e53ebeb43f10": {
                "Name": "pgadmin",
                "EndpointID": "10e1f181f18e751ce0b3521f537e30948433e62b454fb9707b96333395f5ba36",
                "MacAddress": "02:42:ac:14:00:04",
                "IPv4Address": "172.20.0.4/16",
                "IPv6Address": ""
            },
            "bff75ff8e23ab998cfc99bc87bec05ea9fb55adbcae1993da1cbc719eea90fd3": {
                "Name": "postgres",
                "EndpointID": "edd547148b50c6c3319f2b65ec151816e14f9ea9e7dd9acb9b5895d44fcd6cda",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

在上面的例子中,postgres 和 pgadmin 在同一个网络中,所以它们可以互相看到。

如果在您的情况下它们不在同一个网络中,请明确定义。

# docker-compose.yml

services:
  django:
    container_name: dj
    build:
      context: ./server
    restart: unless-stopped
    volumes:
      - staticfiles:/app/staticfiles
      - mediafiles:/app/media
    command: gunicorn nohchi_mott.wsgi:application --bind 0.0.0.0:8000
    env_file: ./server/.env
    expose:
      - 8000
    networks:
      - web
      - django
    depends_on:
      - db
  db:
    container_name: postgres
    image: postgres:12.0-alpine
    restart: unless-stopped
    labels:
      - "traefik.enable=false"
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    expose:
      - 5432
    networks:
      - django
    env_file: ./db/.env
  pgadmin:
    container_name: pgadmin
    image: dpage/pgadmin4:latest
    restart: unless-stopped
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    env_file: ./db/pgadmin/.env
    links:
      - db:pgsql-server
    networks:
      - web
      - django
    depends_on:
      - db

volumes:
  staticfiles:
  mediafiles:
  postgres_data:
  pgadmin_data:

networks:
  web:
    external: true
  django:
    external: false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2015-05-16
    相关资源
    最近更新 更多