A Sturman
A Sturman

Reputation: 29

Can't connect to Postgres when running .Net 5 API in Docker container

I'm trying connect a .Net 5 API running in a Docker container with a Postgres db running in a separate container. The connection works when running the API locally without a container, however when I run the API in a container I get the error

An error occurred using the connection to database 'databasename' on server 'tcp://localhost:5432'.

I think this is because the docker container is not running on localhost. I have attempted to change the host in the docker-compose file and tried manually changing the connection string in startup.cs. This changes the connection the API uses when run locally, however does not change the connection within the container, or the error I am getting. Any help would be appreciated.

Startup.cs

//var connectionString = Configuration.GetSection(nameof(PostgresSettings)).Get<PostgresSettings>().ConnectionString;
var connectionString = $"Host=tryingtochangehost;Port=5432;Database=databasename;Username=username;Password=password";
services.AddDbContext<DataContext>(options => options.UseNpgsql(connectionString));
services.AddScoped<IDataContext>(provider => provider.GetService<DataContext>());

docker-compose.yml

version: "3.4"

services:
  web:
    build: .
    ports:
      - "8080:80"
    environment:
      - JWTCONFIG:SECRET=secret
      - POSTGRESSETTINGS:PASSWORD=password
      - POSTGRESSETTINGS:HOST=postgresql_database
    depends_on:
      - "postgresql_database"
    networks:
      - mynetwork

  postgresql_database:
    image: postgres:latest
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=databasename
    ports:
      - "5432:5432"
    restart: always
    volumes:
      - database-data:/var/lib/postgresql/data/
    networks:
      - mynetwork

  pgadmin:
    image: dpage/pgadmin4
    environment:
      - [email protected]
      - PGADMIN_DEFAULT_PASSWORD=password
    ports:
      - "5050:80"
    restart: always
    volumes:
      - pgadmin:/root/.pgadmin
    networks:
      - mynetwork

volumes:
  database-data:
  pgadmin:

networks:
  mynetwork:
    driver: bridge

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0-focal AS build
WORKDIR /src
COPY ["Server.csproj", "./"]
RUN dotnet restore "Server.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "Server.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Server.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Server.dll"]

appsettings.json

{
  "PostgresSettings": {
    "Host": "localhost",
    "Port": "5432",
    "Database": "databasename",
    "Username": "admin"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "JwtConfig": {},
  "AllowedHosts": "*"
}

Upvotes: 1

Views: 3044

Answers (2)

A Sturman
A Sturman

Reputation: 29

Turns out my configuration was fine, however I needed to run docker-compose build before docker-compose up so the changes actually had effect.

Upvotes: 0

Hans Kilian
Hans Kilian

Reputation: 25189

When you try to connect to localhost:5432, you're trying to connect to the same container as your web container.

Docker compose creates a virtual network where each container can be reached by it's service name. So you need to change the database server name from localhost to postgresql_database like this in your appsettings:

{
  "PostgresSettings": {
    "Host": "postgresql_database",
    "Port": "5432",
    "Database": "databasename",
    "Username": "admin"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "JwtConfig": {},
  "AllowedHosts": "*"
}

Your connection string code should be

var connectionString = $"Host=postgresql_database;Port=5432;Database=databasename;Username=username;Password=password";

Upvotes: 1

Related Questions