Docker Deployment
This guide covers containerizing your application using Docker, setting up multi-container environments with Docker Compose, and deploying to production.Overview
The architecture includes a multi-stage Dockerfile for optimized builds and supports deployment with:- SQL Server
- MongoDB
- RabbitMQ
- Your .NET API
Understanding the Dockerfile
The included Dockerfile uses a multi-stage build for optimal image size and security:Template-API/Dockerfile
Dockerfile Stages
Base Stage
Base Stage
Uses the lightweight ASP.NET runtime image. Only includes what’s needed to run the application, reducing image size and attack surface.
Build Stage
Build Stage
Uses the full .NET SDK to compile the application. Restores NuGet packages and builds in Release configuration.
Publish Stage
Publish Stage
Creates the final published output optimized for deployment.
Final Stage
Final Stage
Copies only the published output to the runtime image, resulting in a minimal production image.
Building the Docker Image
Build the Image
From the solution root directory (containing the Dockerfile):Parameters:
-t hybrid-ddd-api:latest- Tag the image with name and version-f Template-API/Dockerfile- Path to Dockerfile.- Build context (solution root)
Run the Container
Run the container with environment variables:Parameters:
-d- Run in detached mode--name- Container name-p 8080:80- Map port 8080 on host to port 80 in container-e- Environment variables
Test the API
Docker Compose Setup
For a complete multi-container setup, create adocker-compose.yml file:
Running with Docker Compose
Access Services
- API: http://localhost:8080
- Swagger: http://localhost:8080/swagger
- RabbitMQ Management: http://localhost:15672 (admin/YourPassword123)
- SQL Server: localhost:1433 (sa/YourStrong@Password123)
- MongoDB: localhost:27017 (admin/YourPassword123)
Environment Configuration
Development Environment
Createdocker-compose.override.yml for development settings:
Production Environment
Createdocker-compose.prod.yml for production:
Production Deployment
Use Environment Variables
Never hardcode secrets. Use environment files:Create Update Important: Add
.env file:docker-compose.yml:.env to .gitignore!Database Migrations in Docker
Apply Migrations on Startup
Modify yourProgram.cs to apply migrations automatically:
Manual Migration with Init Container
Create a separate migration container:Monitoring and Debugging
Container Logs
Execute Commands in Container
Resource Usage
Troubleshooting
Container Exits Immediately
Container Exits Immediately
Check logs:Common causes:
- Missing environment variables
- Database connection failure
- Configuration errors
Cannot Connect to Database
Cannot Connect to Database
Error: Connection timeout or refusedSolutions:
- Ensure database container is running:
docker ps - Use container name as hostname:
Server=sqlservernotlocalhost - Check network configuration
- Wait for database to be ready (use health checks)
- Verify firewall rules
Port Already in Use
Port Already in Use
Error: Bind for 0.0.0.0:8080 failed: port is already allocatedSolution:
Image Build Fails
Image Build Fails
Solutions:
- Ensure you’re building from solution root
- Verify .csproj file paths in Dockerfile
- Check for missing dependencies
- Clear Docker cache:
docker builder prune - Build with verbose output:
docker build --progress=plain ...
Best Practices
Security
Security
- Never commit
.envfiles - Use secrets management for production
- Run containers as non-root user
- Scan images for vulnerabilities:
docker scan hybrid-ddd-api:latest - Keep base images updated
- Use specific image tags, not
latest
Performance
Performance
- Use multi-stage builds to minimize image size
- Leverage build cache with proper COPY ordering
- Set resource limits for containers
- Use volume mounts for development, not production
- Enable connection pooling for databases
Maintainability
Maintainability
- Tag images with version numbers
- Document environment variables
- Use docker-compose for multi-container apps
- Implement health checks
- Centralize logging
- Regular backups of volumes
Next Steps
Database Setup
Learn about migrations and database configuration
Event Handling
Configure RabbitMQ for event-driven architecture