Docker for Local Development
The Dockerizing for nginx page covers the production image. Day-to-day development wants a different shape: fast rebuilds, hot reload, and a database that resets easily — without needing SQL Server or Node installed on the host at all.
.dockerignore — keep the build context small
Without this, every docker build copies bin/, obj/, node_modules/, and .git into the build context first, which is slow and can leak local build artifacts into the image.
**/bin
**/obj
**/node_modules
**/.vs
.git
.env
*.md
Dockerfile*
docker-compose*
docker-compose.override.yml — a dev-only layer
Compose automatically merges docker-compose.yml with docker-compose.override.yml when present. Keep production-shaped config (image tags, restart policies) in the base file, and put dev conveniences — bind-mounted source for hot reload, exposed debug ports, relaxed passwords — in the override, which never ships.
services:
api:
build:
target: build # stop at the SDK stage instead of the slim runtime stage
volumes:
- ./YourApp.API:/src/YourApp.API
- ./YourApp.Application:/src/YourApp.Application
- ./YourApp.Domain:/src/YourApp.Domain
- ./YourApp.Infrastructure:/src/YourApp.Infrastructure
environment:
- ASPNETCORE_ENVIRONMENT=Development
command: dotnet watch --project YourApp.API run --urls http://0.0.0.0:8080
ports:
- "8080:8080"
db:
ports:
- "1433:1433" # exposed on the host so a local GUI client can connect
environment:
- SA_PASSWORD=DevOnlyPassword1!
dotnet watch inside the container plus the bind-mounted source folders means saving a file on the host triggers a rebuild inside the container — no docker build round-trip per change.
Bringing it up
# override file is picked up automatically alongside docker-compose.yml
docker compose up --build
# reset the database to a clean state — drops the volume entirely
docker compose down -v
docker compose up --build
Attaching a debugger
VS Code's Dev Containers extension can attach directly to a running container's process, so breakpoints work the same as running locally — see .devcontainer/devcontainer.json if the project uses one. Without it, the simplest option is running the API on the host (against the containerized database only) during active debugging, and switching to the full compose stack for integration testing.
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost,1433;Database=YourApp;User=sa;Password=DevOnlyPassword1!;TrustServerCertificate=True"
}
}
Keep the override file out of what actually ships:docker-compose.override.ymlshould be in.gitignoreor clearly marked dev-only if committed, and never referenced from the deploy pipeline in CI Pipeline (GitHub Actions) — production always builds from the basedocker-compose.ymland the real Dockerfile target.