Featured image of post Dockerfile for containerizing Classic ASP

Dockerfile for containerizing Classic ASP

I needed a Windows container image that could run a Classic ASP application without a lot of manual IIS setup. This Dockerfile starts from mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019 and layers in the IIS features, dependencies, and configuration the app needs.

Breakdown of the Dockerfile

Base Image and Shell Configuration

1
2
3
4
ARG LOGMONITOR_VERSION=2.0
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
ARG LOGMONITOR_VERSION

We start with a Windows Server Core image that already includes ASP.NET 4.8, then switch the default shell to PowerShell for the rest of the build.

Installing Windows Features

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
RUN Install-WindowsFeature Web-ASP; `
    Install-WindowsFeature Web-CGI; `
    Install-WindowsFeature Web-ISAPI-Ext; `
    Install-WindowsFeature Web-ISAPI-Filter; `
    Install-WindowsFeature Web-Includes; `
    Install-WindowsFeature Web-HTTP-Errors; `
    Install-WindowsFeature Web-Common-HTTP; `
    Install-WindowsFeature Web-Performance; `
    Install-WindowsFeature WAS; `
    Import-module IISAdministration;

This section installs the IIS features the application depends on, including Classic ASP, CGI, and ISAPI support.

Enabling IIS Features

1
2
RUN Enable-WindowsOptionalFeature -Online -FeatureName IIS-DefaultDocument; `
    Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpErrors;

Here we enable a couple of IIS features that older applications often expect: default documents and HTTP errors.

Installing Dependencies

1
2
RUN Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://vcredist.com/install.ps1'));
RUN md c:/msi;

We install the C++ 2017 redistributable and create a directory for MSI files.

Installing IIS Rewrite Module and SQL ODBC Driver

1
2
3
4
5
RUN Invoke-WebRequest 'https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi' -OutFile c:/msi/rewrite_amd64_en-US.msi; `
    Start-Process 'c:/msi/rewrite_amd64_en-US.msi' '/qn' -PassThru | Wait-Process;

RUN Invoke-WebRequest 'https://download.microsoft.com/download/c/5/4/c54c2bf1-87d0-4f6f-b837-b78d34d4d28a/en-US/18.2.1.1/x64/msodbcsql.msi' -OutFile c:/msi/msodbcsql.msi; `
    Start-Process 'c:/msi/msodbcsql.msi' 'IACCEPTMSODBCSQLLICENSETERMS=YES' -PassThru | Wait-Process;

These commands download and install the IIS Rewrite Module and the SQL ODBC driver.

Downloading Log Monitor

1
2
RUN Invoke-WebRequest -Uri "https://github.com/microsoft/windows-container-tools/releases/download/v$($env:LOGMONITOR_VERSION)/LogMonitor.exe" -OutFile C:\LogMonitor.exe;
RUN Invoke-WebRequest -Uri "https://github.com/microsoft/windows-container-tools/releases/download/v$($env:LOGMONITOR_VERSION)/LogMonitor.exe" -OutFile C:\LogMonitor.exe;

This command downloads the Log Monitor tool from the specified GitHub release URL and saves it to the container’s file system. Log Monitor makes it much easier to surface logs from a Windows container in a usable way.

Unlocking IIS Configuration Sections

1
2
3
4
5
6
7
8
9
RUN & c:\windows\system32\inetsrv\appcmd.exe `
      unlock config `
      /section:system.webServer/asp; `
    & c:\windows\system32\inetsrv\appcmd.exe `
      unlock config `
      /section:system.webServer/handlers; `
    & c:\windows\system32\inetsrv\appcmd.exe `
      unlock config `
      /section:system.webServer/modules;

This section unlocks the IIS configuration sections we need to change later.

In IIS (Internet Information Services), certain configuration sections are locked by default to prevent unauthorized changes that could affect the stability and security of the server. Unlocking these sections is necessary when you need to customize the behavior of your web server beyond the default settings.

  • system.webServer/asp: Unlocking this section allows you to modify settings related to ASP (Active Server Pages), such as enabling or disabling ASP, configuring script timeouts, and setting debugging options.
  • system.webServer/handlers: This section controls the handlers that process requests for specific file types or URL patterns. Unlocking it allows you to add, remove, or modify handlers to customize how requests are processed.
  • system.webServer/modules: Modules are components that handle various stages of request processing in IIS. Unlocking this section allows you to enable, disable, or configure modules to extend the functionality of your web server.

By unlocking these sections, you gain the flexibility to tailor the IIS configuration to meet the specific needs of your applications.

Configuring Default Application Pool and Web Site

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
RUN Import-Module WebAdministration; `
    $pool = Get-Item IIS:\\AppPools\\DefaultAppPool; `
    $pool.ManagedPipelineMode       = 'Integrated'; `
    $pool.ManagedRuntimeVersion     = 'v4.0'; `
    $pool.Enable32BitAppOnWin64     = $false; `
    $pool.AutoStart                 = $true; `
    $pool | Set-Item;

RUN Import-Module WebAdministration; `
    Set-WebConfigurationProperty -Location 'Default Web Site' -Filter "system.webServer/asp" -Name "enableParentPaths" -Value 'True';`
    Set-WebConfigurationProperty -Location 'Default Web Site' -Filter "system.webServer/asp/limits" -Name "maxRequestEntityAllowed" -Value 2000000000;

We configure the default application pool and set properties for the default web site.

Enabling Fusion Logs

1
2
3
4
5
RUN Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name ForceLog         -Value 1               -Type DWord; `
    Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name LogFailures      -Value 1               -Type DWord; `
    Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name LogResourceBinds -Value 1               -Type DWord; `
    Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name LogPath          -Value 'C:\FusionLog\' -Type String; `
    mkdir C:/FusionLog -Force;

This section enables Fusion logs for troubleshooting .NET assembly binding issues.

Setting Up the Working Directory and Copying Files

1
2
3
4
WORKDIR /inetpub/wwwroot
COPY src/ .

COPY cfg/ c:/

We set the working directory to the IIS web root and copy the application source and configuration files.

Setting the Entry Point

1
ENTRYPOINT ["C:\\LogMonitor.exe", "C:\\ServiceMonitor.exe", "w3svc"]

Finally, we set the entry point to start the Log Monitor and Service Monitor for IIS.

This Dockerfile sets up the pieces needed to run a Classic ASP application in a container, with the IIS features, dependencies, and runtime configuration handled in the image.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# escape=`

ARG LOGMONITOR_VERSION=2.0
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
ARG LOGMONITOR_VERSION

# Install Windows Features
RUN Install-WindowsFeature Web-ASP; `
    Install-WindowsFeature Web-CGI; `
    Install-WindowsFeature Web-ISAPI-Ext; `
    Install-WindowsFeature Web-ISAPI-Filter; `
    Install-WindowsFeature Web-Includes; `
    Install-WindowsFeature Web-HTTP-Errors; `
    Install-WindowsFeature Web-Common-HTTP; `
    Install-WindowsFeature Web-Performance; `
    Install-WindowsFeature WAS; `
    Import-module IISAdministration;

# Enable IIS Features
RUN Enable-WindowsOptionalFeature -Online -FeatureName IIS-DefaultDocument; `
    Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpErrors;

# Install C++ 2017 distributions
RUN Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://vcredist.com/install.ps1'));

RUN md c:/msi;

# Install IIS Rewrite Module
RUN Invoke-WebRequest 'https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi' -OutFile c:/msi/rewrite_amd64_en-US.msi; `
    Start-Process 'c:/msi/rewrite_amd64_en-US.msi' '/qn' -PassThru | Wait-Process;

# Install SQL ODBC Driver
RUN Invoke-WebRequest 'https://download.microsoft.com/download/c/5/4/c54c2bf1-87d0-4f6f-b837-b78d34d4d28a/en-US/18.2.1.1/x64/msodbcsql.msi' -OutFile c:/msi/msodbcsql.msi; `
    Start-Process 'c:/msi/msodbcsql.msi' 'IACCEPTMSODBCSQLLICENSETERMS=YES' -PassThru | Wait-Process;

# Download Log Monitor
RUN Invoke-WebRequest -Uri "https://github.com/microsoft/windows-container-tools/releases/download/v$($env:LOGMONITOR_VERSION)/LogMonitor.exe" -OutFile C:\LogMonitor.exe;

# Unlock IIS Configuration Sections
RUN & c:\windows\system32\inetsrv\appcmd.exe `
      unlock config `
      /section:system.webServer/asp; `
    & c:\windows\system32\inetsrv\appcmd.exe `
      unlock config `
      /section:system.webServer/handlers; `
    & c:\windows\system32\inetsrv\appcmd.exe `
      unlock config `
      /section:system.webServer/modules;

# Configure Default Application Pool
RUN Import-Module WebAdministration; `
    $pool = Get-Item IIS:\\AppPools\\DefaultAppPool; `
    $pool.ManagedPipelineMode       = 'Integrated'; `
    $pool.ManagedRuntimeVersion     = 'v4.0'; `
    $pool.Enable32BitAppOnWin64     = $false; `
    $pool.AutoStart                 = $true; `
    $pool | Set-Item;

# Configure Default Web Site
RUN Import-Module WebAdministration; `
    Set-WebConfigurationProperty -Location 'Default Web Site' -Filter "system.webServer/asp" -Name "enableParentPaths" -Value 'True';`
    Set-WebConfigurationProperty -Location 'Default Web Site' -Filter "system.webServer/asp/limits" -Name "maxRequestEntityAllowed" -Value 2000000000;

# Enable Fusion Logs
# https://stackoverflow.com/a/33013110
RUN Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name ForceLog         -Value 1               -Type DWord; `
    Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name LogFailures      -Value 1               -Type DWord; `
    Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name LogResourceBinds -Value 1               -Type DWord; `
    Set-ItemProperty -Path HKLM:\\Software\\Microsoft\\Fusion -Name LogPath          -Value 'C:\FusionLog\' -Type String; `
    mkdir C:/FusionLog -Force;

WORKDIR /inetpub/wwwroot
COPY src/ .

COPY cfg/ c:/

ENTRYPOINT ["C:\\LogMonitor.exe", "C:\\ServiceMonitor.exe", "w3svc"]
Built with Hugo
Theme Stack designed by Jimmy