我是 docker 和 docker compose 的新手,我只是想更好地理解它。
我在尝试连接两个容器时遇到以下问题,一个容器具有 Postgres DB,另一个容器具有 EF 迁移。
当我尝试使用 5433 映射端口并运行迁移容器时,连接被拒绝。但是,如果我尝试从外部应用程序(例如 DBeaver)连接到 PostgresDB 容器,我就可以毫无顾虑地进行连接。
我看到了这个堆栈溢出问题,并看到同一网络中的两个容器之间的连接不适用于映射端口,我们必须使用主机端口,但不明白为什么它会这样工作,或者它是否有任何解决方法。
这是我的 docker-compose.yml
version: '3.4'
networks:
dev:
driver: bridge
services:
api:
env_file:
- .env
image: avaliacaomestradoapi
container_name: avaliacaomestradoapi-api
depends_on:
- postgresDB
- migrations
ports:
- '${API_PORT}:80'
build:
context: .
dockerfile: Dockerfile
environment:
- ConnectionStrings__DefaultConnection=${CONNECTION_STRING}
- ASPNETCORE_URLS=http://+:80
networks:
- dev
migrations:
env_file:
- .env
image: avaliacaomestrado-migrations
container_name: avaliacaomestradoapi-migrations
depends_on:
- postgresDB
build:
context: .
dockerfile: Dockerfile.migrations
environment:
- ConnectionStrings__DefaultConnection=${CONNECTION_STRING}
networks:
- dev
postgresDB:
env_file:
- .env
image: postgres:latest
container_name: avaliacaomestradoapi-db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
ports:
- '5433:5432'
restart: always
volumes:
- avaliacaomestrado_data:/var/lib/postgresql/data
networks:
- dev
volumes:
avaliacaomestrado_data:
这是连接字符串:
Server=avaliacaomestradoapi-db;User ID=postgres;Password=postgres;Port=5433;Database=avaliacaomestrado;Integrated Security=true;Pooling=true;Maximum Pool Size=1024;Timeout=300
这是日志:
Npgsql.NpgsqlException (0x80004005): Failed to connect to 192.168.64.2:5433
avaliacaomestradoapi-migrations | ---> System.Net.Sockets.SocketException (111): Connection refused
avaliacaomestradoapi-migrations | at Npgsql.Internal.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
avaliacaomestradoapi-migrations | at Npgsql.Internal.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
avaliacaomestradoapi-migrations | at Npgsql.Internal.NpgsqlConnector.RawOpen(SslMode sslMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken, Boolean isFirstAttempt)
avaliacaomestradoapi-migrations | at Npgsql.Internal.NpgsqlConnector.<Open>g__OpenCore|191_1(NpgsqlConnector conn, SslMode sslMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken, Boolean isFirstAttempt)
avaliacaomestradoapi-migrations | at Npgsql.Internal.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
avaliacaomestradoapi-migrations | at Npgsql.UnpooledConnectorSource.Get(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
avaliacaomestradoapi-migrations | at Npgsql.NpgsqlConnection.<Open>g__OpenAsync|45_0(Boolean async, CancellationToken cancellationToken)
avaliacaomestradoapi-migrations | at Npgsql.NpgsqlConnection.Open()
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected)
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternal(Boolean errorsExpected)
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected)
avaliacaomestradoapi-migrations | at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlDatabaseCreator.Exists(Boolean async, CancellationToken cancellationToken)
avaliacaomestradoapi-migrations | at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlDatabaseCreator.Exists(Boolean async, CancellationToken cancellationToken)
avaliacaomestradoapi-migrations | at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.NpgsqlDatabaseCreator.Exists()
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
avaliacaomestradoapi-migrations | at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
avaliacaomestradoapi-migrations | Failed to connect to 192.168.64.2:5433
我尝试使用
在 postgres 容器中设置监听地址command: postgres -c listem_addresses:'*'
在 docker compose 中使用默认网络并尝试使用
公开 5433 映射端口expose:
- 5433
但没有成功。
所以现在我将坚持使用上面提到的解决方案,使用主机端口,但我只是想了解它是如何工作的。
容器之间的连接使用Docker网络;在您的示例中,您将自定义网络命名为
dev
。 ports:
仅适用于来自 Docker 外部的连接。
如果您在 Compose 设置中的容器之间进行连接,则客户端应连接到目标的 Compose 服务名称以及目标服务的“正常”端口号;对于 PostgreSQL,端口 5432。此处不需要
ports:
,并且如果存在,也不会考虑它们。
例如,这样做的结果是,您只需删除数据库的
ports:
块即可对主机和外部网络隐藏数据库。无法从 Docker 外部访问该容器,但您仍然可以使用容器名称和标准端口号进行连接。
(我可能会删除所有
networks:
块以使用 Compose 为您提供的 default
网络。您也不需要手动指定 container_name:
。expose:
是第一代 Docker 网络的产物,几乎什么都不做,如果你碰巧拥有它,可以安全地删除它。)