Внутренняя ошибка сети Docker: попытка отправить данные на закрытый сокет

Вопрос или проблема

Используя openresty/openresty:latest в Dockerfile:

FROM openresty/openresty:latest

COPY default-prod.conf /etc/nginx/conf.d/default.conf

RUN apt-get update && apt-get install -y luarocks

RUN luarocks install luasocket
RUN luarocks install pgmoon
RUN luarocks install lua-cjson
RUN luarocks install lua-resty-openssl

и networks: в моем docker-compose.yml

  smalljobsdb:
    image: postgres:14
    container_name: smalljobsdb
    env_file:
      - .env.production
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    ports:
      - "5450:5432"
    volumes:
      - ./db-production/postgresql:/var/lib/postgresql/data
    networks:
      - smalljobs

  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile.prod
    container_name: nginx
    restart: always
    # network_mode: host
    networks:
      - smalljobs
    volumes:
      # - ./certbot/www/:/var/www/certbot/:ro
      - ./server/shared:/usr/share/nginx/html
      - ./nginx/cert:/etc/nginx/ssl:ro
      - storefrontbuild:/usr/share/nginx/html/storefront
    ports:
      - 80:80
      - 443:443
    depends_on:
      smalljobsdb:
        condition: service_started
      smalljobsserver:
        condition: service_started
      smalljobsstorefront:
        condition: service_completed_successfully

когда я пытаюсь подключиться к своей базе данных postgres во время рендеринга своего веб-сайта в файле nginx.conf:

location ~ ^/[0-9]+$ {
        default_type text/html;
        resolver 127.0.0.11 valid=30s;
        content_by_lua_block {
            local id = ngx.var.uri:match("^/([0-9]+)$")  -- Извлечение ID из URI

            if id then
                local cjson = require "cjson"
                local pgmoon = require("pgmoon")
                
                -- Настройка соединения с PostgreSQL
                local pg = pgmoon.new({
                    host     = "smalljobsdb",
                    port     = "", << УДАЛЕНО НО ИСПОЛЬЗУЕТСЯ
                    user     = "", << УДАЛЕНО НО ИСПОЛЬЗУЕТСЯ
                    password = "", << УДАЛЕНО НО ИСПОЛЬЗУЕТСЯ
                    database = ""  << УДАЛЕНО НО ИСПОЛЬЗУЕТСЯ
                })

                ngx.log(ngx.ERR, "BEFORE CONNECTION " .. id)
                -- Подключение к базе данных PostgreSQL
                assert(pg:connect())
                ngx.log(ngx.ERR, "AFTER CONNECTION " .. id)
                pg:keepalive()

я получаю ошибку:

nginx                  | 2024/11/08 17:09:27 [error] 7#7: *1 [lua] default.conf:60):17: BEFORE CONNECTION 8, client: 85.193.34.174, server: smalljobs.cz, request: "GET /8 HTTP/1.1", host: "smalljobs.cz"
nginx                  | 2024/11/08 17:09:28 [error] 7#7: *1 [lua] default.conf:60):20: AFTER CONNECTION 8, client: 85.193.34.174, server: smalljobs.cz, request: "GET /8 HTTP/1.1", host: "smalljobs.cz"
nginx                  | 2024/11/08 17:09:28 [error] 7#7: *1 attempt to send data on a closed socket: u:00007F1E11F831F8, c:0000000000000000, ft:0 eof:0, client: 85.193.34.174, server: smalljobs.cz, request: "GET /8 HTTP/1.1", host: "smalljobs.cz"
nginx                  | 2024/11/08 17:09:28 [error] 7#7: *1 attempt to receive data on a closed socket: u:00007F1E11F831F8, c:0000000000000000, ft:0 eof:0, client: 85.193.34.174, server: smalljobs.cz, request: "GET /8 HTTP/1.1", host: "smalljobs.cz"
nginx                  | 2024/11/08 17:09:28 [error] 7#7: *1 lua entry thread aborted: runtime error: content_by_lua(/etc/nginx/conf.d/default.conf:60):24: receive_message: failed to get type: closed
nginx                  | stack traceback:
nginx                  | coroutine 0:
nginx                  |    [C]: in function 'assert'
nginx                  |    content_by_lua(/etc/nginx/conf.d/default.conf:60):24: in main chunk, client: 85.193.34.174, server: smalljobs.cz, request: "GET /8 HTTP/1.1", host: "smalljobs.cz"

ЧТО Я ПРОБОВАЛ:

  • Смена контейнера Nginx на network_mode: host – не удалось в начале:
    upstream smalljobsserver {
    server smalljobsserver:3034; << smalljobsserver не найден
    }
  • Подключение через 127.0.0.1 и резолвер 8.8.8.8 или GOOGLE DNS, или не удалось отправить соединение наружу

ЧТО Я ХОЧУ
Получить данные из базы данных в зависимости от /:id из URL. Как можно безопаснее, чтобы не было подделки

Ответ или решение

Ошибка в Docker: "attempt to send data on a closed socket" при подключении к PostgreSQL из OpenResty

Ошибка "attempt to send data on a closed socket" при работе с Docker и OpenResty является распространенным симптомом, указывающим на проблемы с сетевыми соединениями между контейнерами или с конфигурацией самого подключения. Давайте подробно разберемся с возможными причинами и путями их решения.

Контекст ошибки

Ваша конфигурация Docker предполагает использование двух контейнеров: одного для Postgres и другого для OpenResty. В процессе обработки запроса к вашему приложению вы пытаетесь подключиться к базе данных PostgreSQL. Ошибка возникает после попытки установить соединение, что может свидетельствовать о нескольких проблемах.

Возможные причины

  1. Неверные параметры подключения: Убедитесь, что все параметры подключения к базе данных (хост, порт, пользователь, пароль, имя базы данных) указаны корректно. Проверьте конфигурацию переменных окружения, чтобы гарантировать их доступность и правильность.

  2. Сетевая конфигурация: Обратите внимание на конфигурацию Docker. Оба контейнера должны находиться в одной сети, что, судя по вашему docker-compose.yml, сделано правильно (используется сеть smalljobs). Убедитесь, что вы используете правильные имена контейнеров и что они доступны друг другу.

  3. Проблемы с временем жизни соединения: Метод pg:keepalive() в Lua может не поддерживать долгосрочные соединения должным образом. Убедитесь, что соединение с базой данных установлено и активно во время работы вашего кода. Также стоит проверить, не закрывается ли соединение между запросами.

  4. Файловая система: Если у вас есть файлы на хосте, которые монтируются в контейнере (например, данные базы данных), убедитесь, что права доступа к ним корректны.

  5. Версия зависимостей: Иногда проблемы возникают из-за несовместимости библиотек. Убедитесь, что версии pgmoon и других Lua-библиотек совместимы с используемой версией PostgreSQL.

Рекомендации по устранению проблемы

  1. Проверка параметров подключения:

    local pg = pgmoon.new({
       host     = "smalljobsdb",
       port     = "5432",  -- Убедитесь, что порт указан
       user     = "ваш_пользователь",
       password = "ваш_пароль",
       database = "ваша_база"
    })
  2. Проверка соединения: Добавьте дополнительный лог для проверки успешного подключения:

    local connection_status, err = pg:connect()
    if not connection_status then
       ngx.log(ngx.ERR, "Connection failed: " .. err)
       return ngx.exit(500)  -- Или другая обработка ошибки
    end
  3. Тестирование соединения: Запустите команду из вашего контейнера с OpenResty, чтобы проверить подключение к базе данных:

    docker exec -it nginx_container_name psql -h smalljobsdb -U ваш_пользователь -d ваша_база
  4. Настройка Docker Compose: Убедитесь, что все служебные зависимости правильно настроены и запускаются в нужном порядке. Параметры depends_on могут быть критически важны, но не гарантируют, что служба будет полностью готова к использованию. Рассмотрите использование кастомных проверок готовности.

  5. Логи и отладка: Используйте логи Docker и Nginx для получения информации о возможных ошибках и поведении приложения.

  6. Избегайте network_mode: host, если это не абсолютно необходимо, так как это может повлечь за собой дополнительные проблемы с разделением сетей и маршрутизации.

Заключение

Ошибка "attempt to send data on a closed socket" может иметь несколько источников. Следуя приведенным выше рекомендациям и методам отладки, вы сможете определить и устранить причину проблемы. Хорошая практика — убедиться в правильности конфигурации, четком понимании сетевой архитектуры Docker и аккуратной обработке ошибок при работе с соединениями к базе данных.

Оцените материал
Добавить комментарий

Капча загружается...