Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .dockerignore.backup
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Docker ignore file for NLWebNet
# Optimizes Docker build context by excluding unnecessary files

# Git
.git
.gitignore
.gitattributes

# GitHub workflows and metadata
.github/
copilot-setup-steps.yml

# IDE and editor files
.vs/
.vscode/
*.user
*.suo
*.userosscache
*.sln.docstates
.idea/

# Build outputs
**/bin/
**/obj/
**/out/
**/.vs/

# Test results
TestResults/
test-results*.xml
coverage*.xml
*.coverage
*.coveragexml

# NuGet
packages/
*.nupkg
*.snupkg
**/packages/*
!**/packages/build/

# Runtime logs
logs/
*.log

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Temporary files
tmp/
temp/
*.tmp
*.temp

# Documentation (not needed in container)
README.md
doc/
*.md

# Scripts (not needed in runtime)
scripts/

# License files
LICENSE*
COPYING*

# Docker files (avoid recursion)
Dockerfile*
docker-compose*
.dockerignore

# Environment specific files (use volume mounts instead)
appsettings.*.json
!appsettings.json
*.env
.env*
65 changes: 62 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,25 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}/demo
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build Docker image (test build)
run: |
echo "🐳 Building Docker image for testing..."
Expand All @@ -365,14 +384,29 @@ jobs:
docker run -d --name nlwebnet-test -p 8080:8080 nlwebnet-demo:test

# Wait for container to start
sleep 5
sleep 10

# Check if container is running (basic test)
if docker ps | grep nlwebnet-test; then
echo "✅ Container is running"

# Test health endpoint if available
echo "🔍 Testing health endpoint..."
for i in {1..5}; do
if curl -f -s http://localhost:8080/health >/dev/null 2>&1; then
echo "✅ Health endpoint responds successfully"
break
elif [ $i -eq 5 ]; then
echo "⚠️ Health endpoint not responding (may be expected)"
else
echo "⏳ Waiting for health endpoint... (attempt $i/5)"
sleep 3
fi
done

# Show container logs for debugging
echo "📋 Container logs:"
docker logs nlwebnet-test
echo "📋 Recent container logs:"
docker logs --tail 10 nlwebnet-test
else
echo "❌ Container failed to start"
docker logs nlwebnet-test
Expand All @@ -383,6 +417,31 @@ jobs:
docker stop nlwebnet-test
docker rm nlwebnet-test

- name: Build and push Docker image to GHCR
uses: docker/build-push-action@v5
with:
context: .
file: deployment/docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Generate deployment summary
run: |
echo "## 🐳 Docker Build Summary" >> $GITHUB_STEP_SUMMARY
echo "- **Image**: \`ghcr.io/${{ github.repository }}/demo\`" >> $GITHUB_STEP_SUMMARY
echo "- **Tags**: ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "- **Build Status**: ✅ Success" >> $GITHUB_STEP_SUMMARY
echo "- **Smoke Test**: ✅ Passed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Usage" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "docker pull ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "docker run -p 8080:8080 ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
Copy link

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The steps.meta.outputs.tags contains multiple tags separated by newlines, but this will only show the first tag in the docker pull command. This could confuse users about which tag to actually pull. Consider using a specific tag like latest or the first tag from the list.

Suggested change
echo "docker run -p 8080:8080 ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
FIRST_TAG="$(echo "${{ steps.meta.outputs.tags }}" | head -n1)"
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "docker pull $FIRST_TAG" >> $GITHUB_STEP_SUMMARY
echo "docker run -p 8080:8080 $FIRST_TAG" >> $GITHUB_STEP_SUMMARY

Copilot uses AI. Check for mistakes.

Copy link

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as the previous line - steps.meta.outputs.tags contains multiple tags but only the first will be used in the docker run command, which may not be the intended tag for users to run.

Suggested change
echo "docker run -p 8080:8080 ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
FIRST_TAG=$(echo "${{ steps.meta.outputs.tags }}" | awk -F',' '{print $1}')
echo "docker pull $FIRST_TAG" >> $GITHUB_STEP_SUMMARY
echo "docker run -p 8080:8080 $FIRST_TAG" >> $GITHUB_STEP_SUMMARY

Copilot uses AI. Check for mistakes.

echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

# Alternative: .NET SDK Container Build (modern approach)
dotnet-container-build:
runs-on: ubuntu-latest
Expand Down
81 changes: 81 additions & 0 deletions deployment/docker/.dockerignore.pre-built
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Docker ignore file for NLWebNet pre-built approach
# This version allows obj/ folders for pre-restored packages

# Git
.git
.gitignore
.gitattributes

# GitHub workflows and metadata
.github/
copilot-setup-steps.yml

# IDE and editor files
.vs/
.vscode/
*.user
*.suo
*.userosscache
*.sln.docstates
.idea/

# Build outputs (keep obj/ for restore metadata)
**/bin/
**/out/
**/.vs/

# Test results
TestResults/
test-results*.xml
coverage*.xml
*.coverage
*.coveragexml

# NuGet packages (but not restore metadata)
packages/
*.nupkg
*.snupkg
**/packages/*
!**/packages/build/

# Runtime logs
logs/
*.log

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Temporary files
tmp/
temp/
*.tmp
*.temp

# Documentation (not needed in container)
README.md
doc/
*.md

# Scripts (not needed in runtime)
scripts/

# License files
LICENSE*
COPYING*

# Docker files (avoid recursion)
Dockerfile*
docker-compose*
.dockerignore

# Environment specific files (use volume mounts instead)
appsettings.*.json
!appsettings.json
*.env
.env*
31 changes: 29 additions & 2 deletions deployment/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ WORKDIR /src
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
ENV DOTNET_CLI_TELEMETRY_OPTOUT=true
ENV NUGET_XMLDOC_MODE=skip
# Configure .NET to handle SSL issues in Docker environment
ENV DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
ENV NUGET_CERT_REVOCATION_MODE=offline
# Additional SSL configurations for NuGet connectivity
ENV NUGET_CERT_REVOCATION_MODE=offline
ENV DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT=false
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true

# Update package lists and install certificates with additional SSL handling
RUN apt-get update && \
apt-get install -y ca-certificates curl && \
update-ca-certificates && \
rm -rf /var/lib/apt/lists/* && \
# Create NuGet config to bypass SSL issues
mkdir -p ~/.nuget/NuGet && \
echo '<?xml version="1.0" encoding="utf-8"?><configuration><packageSources><add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /></packageSources><config><add key="http_proxy" value="" /><add key="https_proxy" value="" /></config></configuration>' > ~/.nuget/NuGet/NuGet.Config

# Copy solution file and project files for dependency resolution
COPY ["NLWebNet.sln", "./"]
Expand All @@ -18,8 +34,19 @@ COPY ["src/NLWebNet/NLWebNet.csproj", "src/NLWebNet/"]
COPY ["samples/Demo/NLWebNet.Demo.csproj", "samples/Demo/"]
COPY ["tests/NLWebNet.Tests/NLWebNet.Tests.csproj", "tests/NLWebNet.Tests/"]

# Restore dependencies
RUN dotnet restore "samples/Demo/NLWebNet.Demo.csproj"
# Restore dependencies with comprehensive SSL workarounds
RUN dotnet restore "samples/Demo/NLWebNet.Demo.csproj" \
--disable-parallel \
--verbosity minimal \
--force \
--ignore-failed-sources || \
# Fallback with additional options if first attempt fails
dotnet restore "samples/Demo/NLWebNet.Demo.csproj" \
--disable-parallel \
--verbosity minimal \
--force \
--ignore-failed-sources \
--no-cache

# Copy source code
COPY . .
Expand Down
66 changes: 66 additions & 0 deletions deployment/docker/Dockerfile.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Multi-stage Dockerfile for NLWebNet Demo Application
# This version is optimized for local development environments with SSL issues
# Pre-restore packages using 'dotnet restore' before building with this Dockerfile

# Build stage
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src

# Set essential environment variables for .NET in containerized environments
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
ENV DOTNET_CLI_TELEMETRY_OPTOUT=true
ENV NUGET_XMLDOC_MODE=skip

# Install curl for troubleshooting
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*

# Copy source files
COPY ["src/", "src/"]
COPY ["samples/", "samples/"]
COPY ["NLWebNet.sln", "./"]
COPY ["Directory.Packages.props", "./"]
COPY ["NuGet.Config", "./"]

# Build the demo application (assumes packages are pre-restored on host)
WORKDIR "/src/samples/Demo"
RUN dotnet build "NLWebNet.Demo.csproj" -c Release -o /app/build

# Publish stage
FROM build AS publish
RUN dotnet publish "NLWebNet.Demo.csproj" -c Release -o /app/publish /p:UseAppHost=false

# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final

# Install curl for health checks and create a non-root user for security
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* \
&& groupadd -r nlwebnet && useradd -r -g nlwebnet nlwebnet

# Set working directory
WORKDIR /app

# Copy published application
COPY --from=publish /app/publish .

# Create directory for logs and ensure proper permissions
RUN mkdir -p /app/logs && chown -R nlwebnet:nlwebnet /app

# Switch to non-root user
USER nlwebnet

# Configure ASP.NET Core
ENV ASPNETCORE_ENVIRONMENT=Production
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_HTTP_PORTS=8080

# Expose port
EXPOSE 8080

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1

# Entry point
ENTRYPOINT ["dotnet", "NLWebNet.Demo.dll"]
Loading