Skip to content

Example Docker and Docker Compose configuration for ASP.NET Core 3.1.x and Let's Encrypt

License

Notifications You must be signed in to change notification settings

chrisgate/aspnet-core-docker-ssl

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Usage

Copy files

Copy Dockerfile, docker-compose.yml and .dockerignore to the root of your ASP.NET Core project.

Install packages

dotnet tool install --global dotnet-ef
dotnet tool install --global dotnet-aspnet-codegenerator
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL

Configuration

ASP.NET Core

Add connection strings

You can set up ASP.NET Core so that it uses SQLite during development and PostgreSQL in production. You do this by adding two different connection strings. You only need to add the connection string, leave the rest of the config file as it is.

In appsettings.Development.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Filename=Example.db"
  },
  "Logging": {
    ...
  }
}

In appsettings.json:

{
  "ConnectionStrings": {
    "DefaultConnection": "Host=postgres;Port=5432;Username=postgres;Password=Password1.;Database=postgres;"
  },
  "Logging": {
    ...
  },
  "AllowedHosts": "*"
}

Modify Program.cs

The database initializer should behave different in development vs production, and because of this it needs to know what environment we are in:

var host = CreateHostBuilder(args).Build();

using (var scope = host.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    // Get our database context from the service provider
    var context = services.GetRequiredService<ExampleDbContext>();

    // Get the environment so we can check if this is running in development or otherwise
    var environment = services.GetService<IHostEnvironment>();

    // Initialise the database using the initializer from Data/ExampleDbInitializer.cs
    DbInitializer.Initialize(context, environment.IsDevelopment());
}

host.Run();

Modify Startup.cs

The Startup class needs to be updated so it also receives the environment in its constructor:

// The second parameter has been added so we can get the current environment in ConfigureServices
public Startup(IConfiguration configuration, IHostEnvironment environment)
{
    Configuration = configuration;
    Environment = environment;
}

public IConfiguration Configuration { get; }
public IHostEnvironment Environment { get; }

ConfigureServices() needs to be updated to use the appropriate connection string for each environment:

if (Environment.IsDevelopment()) // Database used during development
{
    // Register the database context as a service. Use the SQLite for this
    services.AddDbContext<ExampleDbContext>(options =>
        options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
}
else // Database used in all other environments (production etc)
{
    // Register the database context as a service. Use PostgreSQL server for this
    services.AddDbContext<ExampleDbContext>(options =>
        options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
}

Add the database initializer

The database initializer will receive the current environment from the change in Program.cs, and decide what to do based on that:

public static class DbInitializer
{
    public static void Initialize(ExampleDbContext context, bool development)
    {
        // Run migrations if we're not in development mode
        if (!development)
        {
            context.Database.Migrate();
            return;
        }

        // If we are in development mode the code below is run.

        // Delete the database before we initialize it.
        // This is common to do during development.
        context.Database.EnsureDeleted();

        // Make sure the database and tables exist
        context.Database.EnsureCreated();

        // You can now add test data here
    }
}

Docker Compose

Create a file called .env in the same directory as docker-compose.yml and set the required environment variables:

# Change these
HOST=example.org,www.example.org
EMAIL=admin@example.org
POSTGRES_PASSWORD=Password1.

Make sure to include both the bare domain and the www sub-domain in HOST as shown above.

Dockerfile

Update the last line of Dockerfile with the name of your ASP.NET Core project. The name is case sensitive.

ENTRYPOINT ["dotnet", "Example.dll"]

Build your application

You should build your application first to make sure everything is working.

docker-compose build

This will pull all the build requirements and build your application.

Start containers

1. PostgreSQL database

I recommend starting PostgreSQL first as the first startup takes a while.

docker-compose up -d postgres

2. Nginx proxy

First start the container:

docker-compose up -d nginx-proxy

Then configure the www-forwarding and restart it:

HOST=example.org # Change this
VOLUME=$(docker volume inspect --format '{{ .Mountpoint }}' $(basename $PWD)_nginx-vhost)
echo "return 301 \$scheme://www.$HOST\$request_uri;" >> $VOLUME/$HOST
docker-compose restart nginx-proxy

3. Start the rest

docker-compose up -d

Checking for errors

You can check the logs to see if everything is working:

docker-compose logs

Press Ctrl+C to close logs.

About

Example Docker and Docker Compose configuration for ASP.NET Core 3.1.x and Let's Encrypt

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Dockerfile 100.0%