如何使用 Docker 运行带有 PostgreSQL DB 和 Redis 的 Golang 后端?

问题描述 投票:0回答:1

嗨,我在 ubonto 中有一个包含 golang redis 和 postgress 数据库的项目 我的 docker 文件是:

我的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 连接到 postgress 数据库 127.0.0.1:5432 并传递 123

2-我无法连接到端口 8089 的容器

我能做什么?

我尝试运行它

docker  run -t mycontiner --network=host

但是一样 我无法连接到它或 ping 它并且无法访问相同的 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:连接:连接被拒绝)

linux docker go redis listen
1个回答
1
投票

在 Dockerfile 中,您结合了 PostgreSQL、Redis 和 Go 应用程序。

但是根据 Docker 的文档建议将它们分开

最佳实践是通过每个容器使用一项服务来分隔关注区域。

因此,让我们将 Dockerfile 简化为单独的 Go 应用程序

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

有趣的事实,您使用的

EXPOSE
指令不会暴露任何内容

EXPOSE
不发布端口。它充当构建映像的人员和运行容器的人员之间的一种文档。

由于您是运行容器的人,因此没有必要。仅当我将 Dockerfile 发布到注册表以便其他人可以下载和使用它时,我才会使用它。这就是我删除它的原因。

可选:以下稍微改进的版本应该允许更快的重建:

FROM golang
WORKDIR /app
COPY go.mod go.sum ./ # ddd
RUN go mod download
COPY *.go ./
RUN go build -o bin
CMD [ "/app/bin" ]

现在我们来谈谈您遇到的错误

每个服务都位于单独的容器中,但您尝试从

backend
连接到
db
,就像它们在单个容器中运行一样。将它们视为在不同的机器上运行。这样,您就可以清楚为什么无法在
db
的本地主机上访问
backend

您为所有容器定义了

network_mode: bridge
。因此它们都将连接到默认的桥接网络。这意味着他们可以通过IP 互相访问。 但获取IP却很棘手。值得庆幸的是,有一个更简单的方法。只需定义一个自定义桥接网络:

networks:
  my_network:

这里

my_network
是用户定义的网络,默认为
driver: bridge
。与默认桥接网络相反,用户定义的桥接网络允许自动服务发现

在用户定义的网络上,容器不仅可以通过IP进行通信,还可以将容器名称解析为IP。这称为自动服务发现。

这意味着,在您的

backend
服务的代码中,您将能够使用
db:5432
访问您的 PostgreSQL 数据库。这里的
db
会自动替换为
db
服务的IP。

但是要从主机访问您的服务,请使用

ports
属性将主机的端口映射到容器的端口。您的
backend
服务地图
8000:8089
。这意味着,
backend
服务可以在主机上以
localhost:8000
的形式访问,但可以从其他服务以
backend:8089
的形式访问。

这是您需要的撰写文件的完整最小示例

networks:
  my_network:
services:
  db:
    image: postgres
    volumes:
      - ./db/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    networks:
      - my_network
    ports:
      - 5433:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: 123
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 1s
      retries: 100
  redis:
    image: redis
    networks:
      - my_network
    ports:
      - 6380:6379
  backend:
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    build: ./backend
    networks:
      - my_network
    ports:
      - 8000:8089

此处,

./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
将数据从主机上的
./postgres/docker-entrypoint-initdb.d
映射到
docker-entrypoint-initdb.d
容器内的
db
。那里的任何 SQL 都会初始化 PostgreSQL DB。

backend.depends_on
db.healthcheck
一起可以确保
backend
db
健康时启动(即 PostgreSQL DB 已准备好接受连接)。

最后,一个完整的工作示例 在这里

© www.soinside.com 2019 - 2024. All rights reserved.