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= 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