Как настроить докер и запустить докер для golang+redis+postgres и прослушать порт 8089

привет, у меня есть проект с golang redis и базой данных postgress в ubonto мой файл докера:

мой table.sql таков:

CREATE TABLE users (  username VARCHAR (200) PRIMARY KEY,   pass VARCHAR (50)   );

Alter User postgres WITH PASSWORD '123';

# syntax=docker/dockerfile:1
FROM postgres:latest AS go2
ENV POSTGRES_USER postgress
ENV POSTGRES_PASSWORD ''
ENV POSTGRES_DB postgress
EXPOSE 5432
ADD table.sql /docker-entrypoint-initdb.d/
FROM redis:latest AS go3

FROM golang:latest AS go
LABEL maintainer=”[email protected]”
WORKDIR /app
COPY . .
RUN go build -o bin
ENTRYPOINT [ "/app/bin" ] 


EXPOSE 8089



и я создаю его с помощью этой команды:

docker build . -t mycontiner

и я запускаю его с помощью этой команды:

docker  run -t mycontiner --network=bridge

и это показывает это:

[error] failed to initialize database, got error failed to connect to `host=172.17.0.2 user=postgres database=postgres`: dial error (dial tcp 172.17.0.2:5432: connect: connection refused)
2024/07/29 13:52:27 IP:172.17.0.2
2024/07/29 13:52:27 IP:172.17.0.2
2024/07/29 13:52:27 server listening at 172.17.0.2:8089
2024/07/29 13:52:27 server listening at 172.17.0.2:8089

Моя проблема: 1-я не могу подключиться к базе данных postgress 127.0.0.1:5432 с пользователем postgress и передать 123

2-я не могу подключиться к контейнеру с портом 8089

что я могу сделать?

я пытался запустить его с помощью

docker  run -t mycontiner --network=host

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

Update:

i created a docker compose file 
services:
   db:
    image: postgres:15.7
    restart: always
    network_mode: bridge
    volumes:
    - ./db/table.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
    - '5433:5432'
    environment:
        POSTGRES_DB: postgres
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: 123
    
   redis:
    image: redis:7.0.12
    network_mode: bridge
    ports:
      - '6380:6379'
   
   backend:
   
    build: ./backend
    network_mode: bridge
   
    
    ports:
       - '8000:8089'  
    depends_on:
      - db

  

но мои Redis и Postgres работают хорошо, и я могу их подключить, но когда я запускаю свой внутренний контейнер, он выдает эту ошибку:

[ошибка] не удалось инициализировать базу данных, возникла ошибка: не удалось подключиться к host=127.0.0.1 user=postgres database=postgres: ошибка набора номера (наберите TCP 127.0.0.1:5433: подключение: соединение отклонено)

docker run запускает только один контейнер, а контейнер запускает только один процесс. Возможно, вы ищете такой инструмент, как Docker Compose, который сможет запускать три контейнера параллельно. Показанный вами Dockerfile генерирует только образ, запускающий приложение Go, блоки хранилища данных полностью игнорируются.
David Maze 29.07.2024 17:52

Я создал файл компоновки Docker с тремя службами db, redis, backend go lang, но получил эту ошибку во внутренней службе [error] failed to initialize database, got error failed to connect to host=127.0.0.1 user=postgres data=postgres: dial error (dial tcp 127.0.0.1:5433: connect: connection refused)

Vali 31.07.2024 15:31

Да, в Docker 127.0.0.1 и соответствующее имя хоста localhost почти всегда относятся к текущему контейнеру, а не к одному из других контейнеров или хост-системе. Сеть в Compose в документации Docker описано, как соединяться между контейнерами.

David Maze 01.08.2024 16:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В вашем Dockerfile вы объединяете PostgreSQL, Redis и ваше приложение Go.

Но согласно документации Докера их предлагается разделить:

Лучше всего разделить проблемные области, используя одну службу для каждого контейнера.

Итак, давайте упростим ваш Dockerfile до одного приложения Go:

FROM golang
WORKDIR /app
COPY ./app .
RUN go build -o bin
ENTRYPOINT [ "/app/bin" ]

Интересный факт: использованная вами EXPOSE инструкция ничего не раскрывает:

Инструкция EXPOSE не публикует порт. Он функционирует как своего рода документация между человеком, который создает образ, и человеком, который запускает контейнер...

Поскольку контейнером управляете вы, в этом нет необходимости. Я бы использовал его только в том случае, если опубликую Dockerfile в реестре, чтобы другие могли его загрузить и использовать. Вот почему я удалил его.

Теперь давайте поговорим об ошибке, с которой вы столкнулись.

Каждая служба находится в отдельном контейнере, но вы пытаетесь подключиться от backend к db, как будто они работают в одном контейнере. Думайте о них как о работающих на отдельных машинах. Таким образом, должно быть очевидно, почему вы не можете получить доступ к db на локальном хосте backend.

Вы определили network_mode: bridge для всех контейнеров. Таким образом, все они будут подключены к мостовой сети по умолчанию. Это означает, что они могут получить доступ друг к другу по своим IP-адресам. Но получить IP-адреса сложно. К счастью, есть более простой способ. Просто определите собственную сеть мостов:

networks:
  my_network:

Здесь my_network — определяемая пользователем сеть, по умолчанию она равна driver: bridge. В отличие от мостовой сети по умолчанию, определяемые пользователем мостовые сети позволяют автоматическое обнаружение сервисов:

В определяемых пользователем сетях контейнеры могут не только обмениваться данными по IP-адресам, но также могут преобразовывать имя контейнера в IP-адрес. Это называется автоматическим обнаружением служб.

Это означает, что в коде вашего backend сервиса вы сможете использовать db:5432 для доступа к вашей базе данных PostgreSQL. db здесь будет автоматически заменен IP-адресом службы db.

Итак, подведем итог. Если вы хотите получить доступ к одной службе из другой, вам необходимо определить собственную мостовую сеть и подключить к ней обе службы. Затем используйте имена контейнеров вместо IP-адресов.

Чтобы получить доступ к вашим сервисам с хоста, используйте атрибут ports, чтобы сопоставить порт хоста с портом контейнера. Ваши backend карты услуг 8000:8089. Это означает, что сервис backend доступен на хосте как localhost:8000, а из других сервисов как backend:8089.

Это полный пример файла создания, который вам нужен:

volumes:
  db_data:
  redis_data:
networks:
  my_network:
services:
  db:
    image: postgres
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    networks:
      - my_network
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    container_name: postgres
    restart: always
  redis:
    image: redis
    volumes:
      - redis_data:/data
    networks:
      - my_network
    ports:
      - 6379:6379
    container_name: redis
    restart: always
  backend:
    depends_on:
      - db
      - redis
    build: .
    networks:
      - my_network
    ports:
      - 8000:8089
    container_name: backend
    restart: always

Здесь я определяю пользовательские объемы и прикрепляю их к db и redis. Это делается для того, чтобы их данные оставались постоянными, иначе они будут исчезать каждый раз, когда вы их перезапускаете. Кроме того, лучше переместить конфиденциальную информацию, такую ​​как имя пользователя и пароль, в файл .env, который не хранится в VCS.

Наконец, инструкция ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d сопоставляет данные с ./postgres/docker-entrypoint-initdb.d на хосте docker-entrypoint-initdb.d внутри db контейнера. Любой SQL будет инициализировать базу данных PostgreSQL.

теперь все работает, но когда я хочу получить доступ к серверной части с 8089 с IP-адресом 127.0.0.1, у меня возникает проблема. если я запускаю main.go вручную, он работает, но я не могу получить доступ к внутреннему контейнеру, который я сопоставил с портом 8089:8089.

Vali 01.08.2024 18:52

и для последней ошибки, которую я обнаружил, я должен установить список внутренних портов: 8000, а не 127.0.0.1:8000. Почему? Я не знаю. Но это работает :) спасибо за вашу помощь.

Vali 01.08.2024 19:06

Другие вопросы по теме

Похожие вопросы

Как выглядит индексный файл, созданный Linux «ar», в файле .a?
Как одно общее загруженное ядро ​​процессора может повлиять на общую загрузку процессора openmp?
Как одно общее загруженное ядро ​​процессора может повлиять на общую загрузку процессора openmp?
SAP NetWeaver. Невозможно получить дескриптор iamodell.so: libnsl.so.1: невозможно открыть файл общего объекта: такого файла или каталога нет
Я хочу использовать mod_timer для таймера на 10 миллисекунд, но результат всегда 20 миллисекунд
Команда «sed» возвращает «Нет такого файла или каталога» при запуске с помощью доступного сценария?
Ок. что означает символ «@» перед регулярным выражением
Почему адреса файлов, хранящихся на диске (vbox vm), различаются каждый раз, когда я просматриваю их?
Как я могу вызвать доверенную подпись Azure из ОС Linux?
Функция Azure с проблемой сети речи Azure AI (WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED)