diff --git a/Dockerfile-windows.template b/Dockerfile-windows.template
new file mode 100644
index 0000000000..1478ed030e
--- /dev/null
+++ b/Dockerfile-windows.template
@@ -0,0 +1,66 @@
+####
+#### Download and prepare PostgreSQL for Windows
+####
+FROM mcr.microsoft.com/windows/servercore:1809 as prepare
+
+##### Use PowerShell for the installation
+SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
+
+### Download EnterpriseDB and remove cruft
+RUN $URL1 = '%%EDB_REPOSITORY%%/postgresql-%%EDB_VERSION%%-windows-x64-binaries.zip' ; \
+    Invoke-WebRequest -Uri $URL1 -OutFile 'C:\\EnterpriseDB.zip' ; \
+    Expand-Archive 'C:\\EnterpriseDB.zip' -DestinationPath 'C:\\' ; \
+    Remove-Item -Path 'C:\\EnterpriseDB.zip' ; \
+    Remove-Item -Recurse -Force –Path 'C:\\pgsql\\doc' ; \
+    Remove-Item -Recurse -Force –Path 'C:\\pgsql\\include' ; \
+    Remove-Item -Recurse -Force –Path 'C:\\pgsql\\pgAdmin*' ; \
+    Remove-Item -Recurse -Force –Path 'C:\\pgsql\\StackBuilder'
+
+### Make the sample config easier to munge (and "correct by default")
+RUN $SAMPLE_FILE = 'C:\\pgsql\\share\\postgresql.conf.sample' ; \
+    $SAMPLE_CONF = Get-Content $SAMPLE_FILE ; \
+    $SAMPLE_CONF = $SAMPLE_CONF -Replace '#listen_addresses = ''localhost''','listen_addresses = ''*''' ; \
+    $SAMPLE_CONF | Set-Content $SAMPLE_FILE
+
+# Install Visual C++ Redistributable Package
+RUN $URL2 = '%%EDB_VCREDIST%%' ; \
+    Invoke-WebRequest -Uri $URL2 -OutFile 'C:\\vcredist.exe' ; \
+    Start-Process 'C:\\vcredist.exe' -Wait \
+        -ArgumentList @( \
+            '/install', \
+            '/passive', \
+            '/norestart' \
+        )
+
+# Copy relevant DLLs to PostgreSQL
+RUN if (Test-Path 'C:\\windows\\system32\\msvcp120.dll') { \
+        Write-Host('Visual C++ 2013 Redistributable Package') ; \
+        Copy-Item 'C:\\windows\\system32\\msvcp120.dll' -Destination 'C:\\pgsql\\bin\\msvcp120.dll' ; \
+        Copy-Item 'C:\\windows\\system32\\msvcr120.dll' -Destination 'C:\\pgsql\\bin\\msvcr120.dll' ; \
+    } else { \
+        Write-Host('Visual C++ 2017 Redistributable Package') ; \
+        Copy-Item 'C:\\windows\\system32\\vcruntime140.dll' -Destination 'C:\\pgsql\\bin\\vcruntime140.dll' ; \
+    }
+
+####
+#### PostgreSQL on Windows Nano Server
+####
+FROM mcr.microsoft.com/windows/nanoserver:1809
+
+RUN mkdir "C:\\docker-entrypoint-initdb.d"
+
+#### Copy over PostgreSQL
+COPY --from=prepare "C:\\pgsql" "C:\\pgsql"
+
+#### In order to set system PATH, ContainerAdministrator must be used
+USER ContainerAdministrator
+RUN setx /M PATH "C:\\pgsql\\bin;%PATH%"
+USER ContainerUser
+ENV PGDATA "C:\\pgsql\\data"
+RUN mkdir "%PGDATA%"
+
+COPY docker-entrypoint.cmd "C:\\"
+ENTRYPOINT ["C:\\docker-entrypoint.cmd"]
+
+EXPOSE 5432
+CMD ["postgres"]
diff --git a/docker-entrypoint.cmd b/docker-entrypoint.cmd
new file mode 100644
index 0000000000..dad0302a60
--- /dev/null
+++ b/docker-entrypoint.cmd
@@ -0,0 +1,132 @@
+@echo off
+SETLOCAL EnableDelayedExpansion
+
+:: Batch file has no concept of a function, only goto
+goto :start
+
+:: usage: CALL :file_env VARIABLE [DEFAULT]
+::    ie: CALL :file_env 'XYZ_DB_PASSWORD' 'example'
+::       (will allow for "%XYZ_DB_PASSWORD_FILE%" to fill in the value of
+::       "%XYZ_DB_PASSWORD%" from a file, especially for Docker's secrets feature)
+:file_env
+:: Reset all values
+set cmdVar=
+set fileVar=
+set default=
+set value=
+:: Start the 'function'
+set cmdVar=%~1
+set fileVar=%cmdVar%_FILE
+set default=%~2
+:: No concept of AND in batch scripts
+:: Instead we use nested if
+if NOT [!%cmdVar%!] == [] (
+    if NOT [!%fileVar%!] == [] (
+        :: Instead of exiting, just use the environment value
+        echo Warning: both %cmdVar% and %fileVar% are set, %fileVar% will be ignored
+    )
+)
+:: set as the default value
+set value=%default%
+if NOT [!%cmdVar%!] == [] (
+    :: override with the environment value
+    set value=!%cmdVar%!
+)
+:: No concept of ELIF in batch scripts
+:: we use nested if with opposite test
+if [!%cmdVar%!] == [] (
+    if NOT [!%fileVar%!] == [] (
+        :: override with the file value
+        set /p value=<!%fileVar%!
+    )
+)
+set %cmdVar%=%value%
+EXIT /B 0
+
+:: ------------------------------------------------------------
+:: ------------------------------------------------------------
+:: ------------------------------------------------------------
+
+:start
+
+:: Ensure the data directory exists
+if NOT exist %PGDATA% (
+    mkdir %PGDATA%
+)
+
+:: Ensure the directories have correct permissions
+call icacls "%PGDATA%" /grant "%USERNAME%":(OI)(CI)F > NUL
+
+:: look specifically for PG_VERSION, as it is expected in the DB dir
+if NOT exist "%PGDATA%\PG_VERSION" (
+
+    call :file_env POSTGRES_USER, postgres
+    call :file_env POSTGRES_PASSWORD
+    call :file_env POSTGRES_INITDB_ARGS
+
+    if NOT [!POSTGRES_PASSWORD!] == [] (
+        echo !POSTGRES_PASSWORD!> "C:\.pgpass"
+        set POSTGRES_INITDB_ARGS=!POSTGRES_INITDB_ARGS! --pwfile="C:\.pgpass"
+    )
+
+    if NOT [%POSTGRES_INITDB_WALDIR%] == [] (
+        set POSTGRES_INITDB_ARGS=!POSTGRES_INITDB_ARGS! --waldir %POSTGRES_INITDB_WALDIR%
+    )
+
+    call initdb -U "!POSTGRES_USER!" -E UTF8 --no-locale -D "%PGDATA%" !POSTGRES_INITDB_ARGS!
+    if exist "C:\.pgpass" (
+        call del "C:\.pgpass"
+    )
+
+    if NOT [!POSTGRES_PASSWORD!] == [] (
+        set authMethod=md5
+        echo authMethod: !authMethod!
+    ) else (
+        echo ****************************************************
+        echo WARNING: No password has been set for the database.
+        echo          This will allow anyone with access to the
+        echo          Postgres port to access your database. In
+        echo          Docker's default configuration, this is
+        echo          effectively any other container on the same
+        echo          system.
+        echo          Use "-e POSTGRES_PASSWORD=password" to set
+        echo          it in "docker run".
+        echo ****************************************************
+        set authMethod=trust
+        echo authMethod: !authMethod!
+    )
+    echo.>> "%PGDATA%\pg_hba.conf"
+    echo host all all all !authMethod!>> "%PGDATA%\pg_hba.conf"
+
+    :: internal start of server in order to allow set-up using psql-client
+    :: does not listen on external TCP/IP and waits until start finishes
+	call pg_ctl -U "!POSTGRES_USER!" -D "%PGDATA%" -w start
+
+    call :file_env POSTGRES_DB !POSTGRES_USER!
+
+    set psqlParam=^-v ON_ERROR_STOP=1 --username "!POSTGRES_USER!" --no-password
+
+    :: Create a database with its name as the user name, override %PGDATABASE%
+    if NOT [!POSTGRES_DB!] == [postgres] (
+        echo CREATE DATABASE :"db"; | call psql !psqlParam! --dbname postgres --set db="!POSTGRES_DB!"
+    )
+    set psqlParam=^-v ON_ERROR_STOP=1 --username "!POSTGRES_USER!" --no-password --dbname "!POSTGRES_DB!"
+
+    :: Execute any batch scripts for this new DB
+    for %%f in (C:\docker-entrypoint-initdb.d\*.cmd) do (
+        echo cmd: running %%f
+        call "%%f"
+    )
+    :: Execute any SQL scripts for this new DB
+    for %%f in (C:\docker-entrypoint-initdb.d\*.sql) do (
+        echo psql: running %%f
+        call psql !psqlParam! -f "%%f"
+    )
+
+    pg_ctl -U "!POSTGRES_USER!" -D "%PGDATA%" -m fast -w stop
+
+    echo PostgreSQL init process complete; ready for start up.
+)
+
+:: start the database
+call %*
diff --git a/update.sh b/update.sh
index 8664ff1fef..adb7db8c00 100755
--- a/update.sh
+++ b/update.sh
@@ -99,6 +99,49 @@ for version in "${versions[@]}"; do
 		travisEnv="\n  - VERSION=$version VARIANT=$variant$travisEnv"
 	done
 
+	for variant in windows; do
+		if [ ! -d "$version/$variant" ]; then
+			continue
+		fi
+
+		edbRepository='https://get.enterprisedb.com/postgresql'
+
+		cp docker-entrypoint.cmd "$version/$variant/docker-entrypoint.cmd"
+		cp Dockerfile-windows.template "$version/$variant/Dockerfile"
+
+		case "$version" in
+			9.4)
+				edbVersion='9.4.22-1'
+				# Visual C++ 2013 Redistributable Package
+				edbVCRedist='https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe'
+				;;
+			9.5)
+				edbVersion='9.5.17-1'
+				# Visual C++ 2013 Redistributable Package
+				edbVCRedist='https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe'
+				;;
+			9.6)
+				edbVersion='9.6.13-1'
+				# Visual C++ 2013 Redistributable Package
+				edbVCRedist='https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe'
+				;;
+			10)
+				edbVersion='10.8-1'
+				# Visual C++ 2013 Redistributable Package
+				edbVCRedist='https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe'
+				;;
+			11)
+				edbVersion='11.3-1'
+				# Visual C++ 2017 Redistributable Package
+				edbVCRedist='https://download.visualstudio.microsoft.com/download/pr/11100230/15ccb3f02745c7b206ad10373cbca89b/VC_redist.x64.exe'
+				;;
+		esac
+		sed -e 's|%%EDB_VERSION%%|'"$edbVersion"'|g' \
+			-e 's|%%EDB_REPOSITORY%%|'"$edbRepository"'|g' \
+			-e 's|%%EDB_VCREDIST%%|'"$edbVCRedist"'|g' \
+			"Dockerfile-$variant.template" > "$version/$variant/Dockerfile"
+	done
+
 	travisEnv="\n  - VERSION=$version FORCE_DEB_BUILD=1$travisEnv"
 	travisEnv="\n  - VERSION=$version$travisEnv"
 done