为什么在 docker compose 中不能使用映射端口连接两个容器?

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

我是 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

但没有成功。

所以现在我将坚持使用上面提到的解决方案,使用主机端口,但我只是想了解它是如何工作的。

.net docker networking docker-compose npgsql
1个回答
0
投票

容器之间的连接使用Docker网络;在您的示例中,您将自定义网络命名为

dev
ports:
仅适用于来自 Docker 外部的连接。

如果您在 Compose 设置中的容器之间进行连接,则客户端应连接到目标的 Compose 服务名称以及目标服务的“正常”端口号;对于 PostgreSQL,端口 5432。此处不需要

ports:
,并且如果存在,也不会考虑它们。

例如,这样做的结果是,您只需删除数据库的

ports:
块即可对主机和外部网络隐藏数据库。无法从 Docker 外部访问该容器,但您仍然可以使用容器名称和标准端口号进行连接。

(我可能会删除所有

networks:
块以使用 Compose 为您提供的
default
网络。您也不需要手动指定
container_name:
expose:
是第一代 Docker 网络的产物,几乎什么都不做,如果你碰巧拥有它,可以安全地删除它。)

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