Как получить доступ к контейнерной базе данных postgresql извне / приложения

#postgresql #docker #docker-compose

#postgresql #docker #docker-compose

Вопрос:

Я изо всех сил пытался подключиться к контейнеру postgresql как с локального хоста, так и извне.

Вот очень хорошая демонстрация, которая работает как таковая очень хорошо, как показано на https://linuxhint.com/postgresql_docker /. А ниже приведен docker-compose.yml, с помощью которого postgres: 12.2 и pgadmin помещаются в контейнер и запускаются. И действительно, после запуска файла docker-compose.yml (с помощью docker-compose up -d) они работают.

Затем вы можете зайти в свой браузер, чтобы http://localhost:8080 / и иметь прямой доступ (с заданными критериями, т.е. admin@linuxhint.com , секретно) в pgadmin и начните работать с вашим postgres: установка 12.2 в docker.

Однако мои трудности начинаются, когда я пытаюсь найти подключение к этой postgres: 12.2 -database напрямую с локального хоста или извне / из какого-либо приложения / ip (например, Java Spring Boot).

По общему признанию, я не эксперт в docker, просто студент — поэтому я прошу о помощи. Надеюсь, кто-нибудь может показать мне, что нужно сделать, чтобы сделать возможным подключение к (этой) контейнерной базе данных postgres извне / app. Я использую Win 10.

Обновить:

  • Кто-нибудь может сказать, почему веб-приложение (добавленное ниже в docker.compose.yml, см. Ниже) постоянно завершает работу после его запуска?

  • журналы docker выдают следующую ошибку:

    Вызвано: org.springframework.beans.factory.Исключение BeanCreationException: ошибка при создании компонента с именем ‘DataSource’, определенным в ресурсе пути к классу [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration $Hikari.class ]: Сбой инициализации компонента; вложенным исключением является org.springframework.beans.factory.Исключение BeanCreationException: ошибка при создании компонента с именем ‘org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker’: не удалось вызвать метод инициализации; вложенным исключением является org.springframework.jdbc.datasource.init.Исключение UncategorizedScriptException: не удалось выполнить скрипт базы данных; вложенным исключением является org.springframework.jdbc.CannotGetJdbcConnectionException: не удалось получить соединение с JDBC; вложенным исключением является org.postgresql.util.Исключение PSQLException: отказано в подключении к localhost: 5433. Убедитесь, что имя хоста и порт указаны правильно и что postmaster принимает соединения TCP / IP.

  • вот Dockerfile для приложения:

    ИЗ maven: 3-jdk-11

    ТОМ / tmp

    РАЗОБЛАЧИТЬ 8095

    ДОБАВИТЬ /target/spring-boot-demo-0.0.1-SNAPSHOT.jar app.jar

    ЗАПУСТИТЕ ls -ls

    ТОЧКА ВХОДА [«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= секретно

  • два других сервиса (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:
  

Комментарии:

1. Вы не можете подключиться к имени контейнера?

2. Единственное, что означает, что я смог подключиться к контейнерному postgresql (как определено выше в yml-файле), было: «docker-compose запустить db bash». А затем: «psql -h db -U admin -d postgres» и «Пароль для администратора пользователя: секретный».

3. из ошибки: Connection; nested exception is org.postgresql.util.PSQLException: Connection to localhost:5433 refused. у вас настроен postgresql на 5433, а из yaml вы запускаете его на 5432

4. Эдвин, ты прав, существует несоответствие между сообщением об ошибке и кодом. Эта ошибка была связана с какой-то странной ошибкой обновления памяти, о которой я сообщил в своем комментарии ниже. Спасибо за ваше острое наблюдение.

Ответ №1:

docker-compose.yml публикует порт 5432 Postgres на компьютере, на котором запущен демон docker.

Таким образом, приложения должны подключаться 127.0.0.1 как к хосту Postgres, так и 5432 к порту Postgres, предполагая, что они запускаются на компьютере.

Комментарии:

1. Таким образом, я могу подключиться с локального хоста: psql -h 127.0.0.1 -p 5432 -U postgres, НО соединение не переходит к приложению в контейнерном postgresql (т.Е. К тому, который определен в yml-файле выше), а вместо этого открывает соединение с локальным неконтейнеризованным postgresql.

2. если вы успешно выполнили docker-compose up команду в папке, в которой docker-compose.yml находится файл, контейнерный Postgres порт 5432 контейнерного Postgres сопоставляется с портом 5432 хоста docker (компьютер, на котором запускается демон docker), и при запуске psql способа, который вы опубликовали, вы подключаетесь к контейнерному Postgres

3. Я могу успешно запустить «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».

4. Если вы используете отдельный PostgreSQL на своем хосте, вам нужно изменить опубликованный ports: ; измените только первое число на какой-то другой порт, например 5433:5432 . Но я ожидаю, что у вас возникнут проблемы с запуском, если возникнет конфликт хост-порта. Вы используете Docker Toolbox или Docker Desktop?

5. Как я могу узнать, использую ли я 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