嗨,我在 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 运行良好,我可以连接它们,但是当我运行后端容器时,它会抛出此错误:
[错误]初始化数据库失败,连接失败
:拨号错误(拨号tcp 127.0.0.1:5433:连接:连接被拒绝)host=127.0.0.1 user=postgres database=postgres
在 Dockerfile 中,您结合了 PostgreSQL、Redis 和 Go 应用程序。
但是根据 Docker 的文档建议将它们分开:
最佳实践是通过每个容器使用一项服务来分隔关注区域。
因此,让我们将 Dockerfile 简化为单独的 Go 应用程序:
FROM golang
WORKDIR /app
COPY ./app .
RUN go build -o bin
ENTRYPOINT [ "/app/bin" ]
有趣的事实,您使用的
EXPOSE
指令不会暴露任何内容:
指令实际上并不发布端口。它充当构建镜像的人和运行容器的人之间的一种文档......EXPOSE
由于您是运行容器的人,因此没有必要。仅当我将 Dockerfile 发布到注册表以便其他开发人员或团队可以下载和使用它时,我才会使用它。这就是我删除它的原因。
现在让我们谈谈您遇到的错误。
每个服务都在单独的容器中运行,但您尝试从
backend
连接到 db
,就像它们在单个容器中运行一样。考虑一下在不同机器上运行的进程的服务。这样,您就可以清楚为什么无法在 postgres
的本地主机上访问 backend
。
您为所有容器定义了
network_mode: bridge
。这意味着它们都将连接到默认的桥接网络。这意味着他们可以使用自己的 IP 地址互相访问。但要获取他们的地址很困难。值得庆幸的是,有一个更简单的方法。只需定义一个自定义桥接网络:
networks:
my_network:
这里
my_network
是用户定义的网络,默认为driver: bridge
。与默认桥接网络相反,用户定义的桥接网络允许自动服务发现:
在用户定义的网络上,容器不仅可以通过IP地址进行通信,还可以将容器名称解析为IP地址。这称为自动服务发现。
这意味着,您将能够使用
db:5432
作为数据库的地址。
这是您需要的撰写文件的完整示例:
volumes:
redis_data:
postgres_data:
networks:
my_network:
services:
postgres:
image: postgres
volumes:
- postgres_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
app:
depends_on:
- redis
- postgres
build: .
networks:
- my_network
ports:
- 8089:8089
command: command
container_name: app
restart: always
希望它已经对您有所帮助。
但我会在一天内添加更多解释和完整的工作示例。