├── Dockerfile ├── LICENSE.md ├── README.md ├── build.cmd └── docker-entrypoint.cmd /Dockerfile: -------------------------------------------------------------------------------- 1 | #### 2 | #### argument for Windows version must be set early 3 | #### 4 | ARG WIN_VER 5 | 6 | #### 7 | #### Download and prepare PostgreSQL for Windows 8 | #### 9 | FROM mcr.microsoft.com/windows/servercore:${WIN_VER} as prepare 10 | 11 | ### Set the variables for EnterpriseDB 12 | ARG EDB_VER 13 | ENV EDB_VER $EDB_VER 14 | ENV EDB_REPO https://get.enterprisedb.com/postgresql 15 | 16 | ##### Use PowerShell for the installation 17 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"] 18 | 19 | ### Download EnterpriseDB and remove cruft 20 | RUN $URL1 = $('{0}/postgresql-{1}-windows-x64-binaries.zip' -f $env:EDB_REPO,$env:EDB_VER) ; \ 21 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; \ 22 | Invoke-WebRequest -Uri $URL1 -OutFile 'C:\\EnterpriseDB.zip' ; \ 23 | Expand-Archive 'C:\\EnterpriseDB.zip' -DestinationPath 'C:\\' ; \ 24 | Remove-Item -Path 'C:\\EnterpriseDB.zip' ; \ 25 | Remove-Item -Recurse -Force –Path 'C:\\pgsql\\doc' ; \ 26 | Remove-Item -Recurse -Force –Path 'C:\\pgsql\\include' ; \ 27 | Remove-Item -Recurse -Force –Path 'C:\\pgsql\\pgAdmin*' ; \ 28 | Remove-Item -Recurse -Force –Path 'C:\\pgsql\\StackBuilder' 29 | 30 | ### Make the sample config easier to munge (and "correct by default") 31 | RUN $SAMPLE_FILE = 'C:\\pgsql\\share\\postgresql.conf.sample' ; \ 32 | $SAMPLE_CONF = Get-Content $SAMPLE_FILE ; \ 33 | $SAMPLE_CONF = $SAMPLE_CONF -Replace '#listen_addresses = ''localhost''','listen_addresses = ''*''' ; \ 34 | $SAMPLE_CONF | Set-Content $SAMPLE_FILE 35 | 36 | ### Install correct Visual C++ Redistributable Package 37 | RUN if (($env:EDB_VER -like '9.*') -or ($env:EDB_VER -like '10.*')) { \ 38 | Write-Host('Visual C++ 2013 Redistributable Package') ; \ 39 | $URL2 = 'https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe' ; \ 40 | } else { \ 41 | Write-Host('Visual C++ 2017 Redistributable Package') ; \ 42 | $URL2 = 'https://download.visualstudio.microsoft.com/download/pr/11100230/15ccb3f02745c7b206ad10373cbca89b/VC_redist.x64.exe' ; \ 43 | } ; \ 44 | Invoke-WebRequest -Uri $URL2 -OutFile 'C:\\vcredist.exe' ; \ 45 | Start-Process 'C:\\vcredist.exe' -Wait \ 46 | -ArgumentList @( \ 47 | '/install', \ 48 | '/passive', \ 49 | '/norestart' \ 50 | ) 51 | 52 | # Determine new files installed by VC Redist 53 | # RUN Get-ChildItem -Path 'C:\\Windows\\System32' | Sort-Object -Property LastWriteTime | Select Name,LastWriteTime -First 25 54 | 55 | # Copy relevant DLLs to PostgreSQL 56 | RUN if (Test-Path 'C:\\windows\\system32\\msvcp120.dll') { \ 57 | Write-Host('Visual C++ 2013 Redistributable Package') ; \ 58 | Copy-Item 'C:\\windows\\system32\\msvcp120.dll' -Destination 'C:\\pgsql\\bin\\msvcp120.dll' ; \ 59 | Copy-Item 'C:\\windows\\system32\\msvcr120.dll' -Destination 'C:\\pgsql\\bin\\msvcr120.dll' ; \ 60 | } else { \ 61 | Write-Host('Visual C++ 2017 Redistributable Package') ; \ 62 | Copy-Item 'C:\\windows\\system32\\vcruntime140.dll' -Destination 'C:\\pgsql\\bin\\vcruntime140.dll' ; \ 63 | } 64 | 65 | #### 66 | #### PostgreSQL on Windows Nano Server 67 | #### 68 | FROM mcr.microsoft.com/windows/nanoserver:${WIN_VER} 69 | 70 | RUN mkdir "C:\\docker-entrypoint-initdb.d" 71 | 72 | #### Copy over PostgreSQL 73 | COPY --from=prepare /pgsql /pgsql 74 | 75 | #### In order to set system PATH, ContainerAdministrator must be used 76 | USER ContainerAdministrator 77 | RUN setx /M PATH "C:\\pgsql\\bin;%PATH%" 78 | USER ContainerUser 79 | ENV PGDATA "C:\\pgsql\\data" 80 | 81 | COPY docker-entrypoint.cmd / 82 | ENTRYPOINT ["C:\\docker-entrypoint.cmd"] 83 | 84 | EXPOSE 5432 85 | CMD ["postgres"] 86 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Stellar Iridescence 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repository is archived! 2 | 3 | I no longer have a need for PostgreSQL as a Windows container so I will not continue to maintain this repository. 4 | 5 | If anyone still has a use case for this kind of container image I recommend to reimplement the refactored upstream entrypoint shell script in PowerShell. Batch script probably cannot be used without a lot of ugly hacks. 6 | 7 | ## Supported tags and `Dockerfile` links 8 | 9 | - [`12.0`, `12`, `latest` (12/Dockerfile)](https://github.com/stellirin/docker-postgres-windows/blob/master/Dockerfile) 10 | - [`11.5`, `11` (11/Dockerfile)](https://github.com/stellirin/docker-postgres-windows/blob/master/Dockerfile) 11 | - [`10.10`, `10` (10/Dockerfile)](https://github.com/stellirin/docker-postgres-windows/blob/master/Dockerfile) 12 | - [`9.6.15`, `9.6` (9.6/Dockerfile)](https://github.com/stellirin/docker-postgres-windows/blob/master/Dockerfile) 13 | - [`9.5.19`, `9.5` (9.5/Dockerfile)](https://github.com/stellirin/docker-postgres-windows/blob/master/Dockerfile) 14 | - [`9.4.24`, `9.4` (9.4/Dockerfile)](https://github.com/stellirin/docker-postgres-windows/blob/master/Dockerfile) 15 | 16 | The above tags are manifest tags that consist of a set builds based on all available `nanoserver` releases, specifically: 17 | 18 | - `nanoserver:1909` 19 | - `nanoserver:1903` 20 | - `nanoserver:1809` 21 | - `nanoserver:1803` (EOL 2019-11-12) 22 | - `nanoserver:1709` (EOL 2019-04-09) 23 | - `nanoserver:sac2016` (EOL 2018-10-09) 24 | 25 | Your Docker client should pull down the correct image. 26 | 27 | ## Quick reference 28 | 29 | - **Where to get help**: 30 | [the Docker Community Forums](https://forums.docker.com/), [the Docker Community Slack](https://blog.docker.com/2016/11/introducing-docker-community-directory-docker-community-slack/), or [Stack Overflow](https://stackoverflow.com/search?tab=newest&q=docker) 31 | 32 | - **Where to file issues**: 33 | [https://github.com/stellirin/docker-postgres-windows/issues](https://github.com/stellirin/docker-postgres-windows/issues) 34 | 35 | - **Maintained by**: 36 | [Stellirin](https://github.com/stellirin) 37 | 38 | - **Supported architectures**: ([more info](https://github.com/docker-library/official-images#architectures-other-than-amd64)) 39 | [`windows-amd64`](https://hub.docker.com/u/winamd64/) 40 | 41 | ## What is PostgreSQL? 42 | 43 | ![logo](https://raw.githubusercontent.com/docker-library/docs/master/postgres/logo.png) 44 | 45 | ## How to use this image 46 | 47 | ```console 48 | $ docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d stellirin/postgres-windows 49 | ``` 50 | 51 | This image includes `EXPOSE 5432` (the postgres port), so standard container linking will make it automatically available to the linked containers. The default `postgres` user and database are created in the entrypoint with `initdb`. 52 | 53 | ### Extended use 54 | 55 | For further details about usage see the [official PostgreSQL container image](https://hub.docker.com/_/postgres/). 56 | 57 | ## About this container image 58 | 59 | A Windows container to run PostgreSQL based on the [EnterpriseDB](https://www.enterprisedb.com/) distribution, which is found on the [PostgeSQL for Windows](https://www.postgresql.org/download/windows/) download page. 60 | 61 | This repository builds a Windows based Docker image that is functionaly similar to the official [Linux based Docker image](https://hub.docker.com/_/postgres/). 62 | 63 | ### Testing 64 | 65 | The resulting image has been (minimally) tested with a proprietary enterprise Java application. This image accepts typical SQL files, it can use TLS certificates in PEM format, and it allows the Java application to connect securely and process data. 66 | 67 | So far, no differences in behaviour have been observed compared to the official Linux based container. 68 | 69 | ### Motivation 70 | 71 | The Linux based Docker image cannot run on Windows as a LCOW container. This is due to differences in functionality between the NTFS and EXT4 file systems. Specifically, Linux commands such as `chown` do not work but the PostgreSQL images rely on them for security. 72 | 73 | ### Entrypoint 74 | 75 | The entrypoint is written as a batch script because the database is run on `windows/nanoserver`, which doesn't have PowerShell. Writing the entrypoint script was challenging due to batch script limitations, but this gives us a base image of less than `450MB` versus nearly `5GB` when `windows/servercore` is used. 76 | 77 | The `Dockerfile` and the `docker-entrypoint.cmd` were strongly inspired by the equivalent files for the official Linux based Docker images. There are some minor deviations, but this is mostly to work around differences in batch script behaviour. 78 | 79 | ### Licence 80 | 81 | The files here are under the MIT licence, the same as the regular [docker-library/postgres](https://github.com/docker-library/postgres) docker files. Just like `docker-library/postgres`, the licence here covers *only* the files in this repository. It doesn't cover the PostgreSQL distribution, which has its own licence. 82 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | SETLOCAL EnableDelayedExpansion 3 | 4 | :: Usage: build.cmd pgValue winValue 5 | :: pgValue: specifies a specific PostgreSQL version. One of: 6 | :: pg94 7 | :: pg95 8 | :: pg96 9 | :: pg10 10 | :: pg11 11 | :: pg12 12 | :: winValue: specifies a specific Windows base image. One of: 13 | :: win1607 14 | :: win1709 15 | :: win1803 16 | :: win1809 17 | :: win1903 18 | :: win1909 19 | :: If no values are specified then all images are built. 20 | 21 | :: Batch file has no concept of a function, only goto 22 | goto :start 23 | 24 | :: CALL :image_build TAGNAME COREVER NANOVER EDBVER 25 | :image_build 26 | set winVer=%~1 27 | set edbVer=%~2 28 | set pgVer=%edbVer:~0,-2% 29 | 30 | :: Modern version numbers: 10, 11, 12 etc. 31 | :: legacy version numbers: 9.4, 9.5, 9.6 32 | for /f "tokens=1,2,3 delims=." %%a in ("%pgVer%") do ( 33 | if [%%c] == [] ( 34 | set tagVer=%%a 35 | ) 36 | if NOT [%%c] == [] ( 37 | set tagVer=%%a.%%b 38 | ) 39 | ) 40 | 41 | docker build ^ 42 | --build-arg WIN_VER=%winVer% ^ 43 | --build-arg EDB_VER=%edbVer% ^ 44 | --tag %repoName%:%pgVer%-%winVer% ^ 45 | --tag %repoName%:%tagVer%-%winVer% ^ 46 | . 47 | docker push %repoName%:%pgVer%-%winVer% 48 | docker push %repoName%:%tagVer%-%winVer% 49 | EXIT /B 0 50 | 51 | :: CALL :postgres_build EDBVER 52 | :postgres_build 53 | set edbVer=%~1 54 | 55 | if [%win1809%] == [true] ( 56 | call :image_build 1809 %edbVer% 57 | ) 58 | if [%win1903%] == [true] ( 59 | call :image_build 1903 %edbVer% 60 | ) 61 | if [%win1909%] == [true] ( 62 | call :image_build 1909 %edbVer% 63 | ) 64 | EXIT /B 0 65 | 66 | :: call :manifest_build MANVER 67 | :manifest_build 68 | set manVer=%~1 69 | docker manifest create --amend ^ 70 | %repoName%:%manVer% ^ 71 | %repoName%:%manVer%-1809 ^ 72 | %repoName%:%manVer%-1903 ^ 73 | %repoName%:%manVer%-1909 74 | docker manifest push %repoName%:%manVer% 75 | EXIT /B 0 76 | 77 | :: ------------------------------------------------------------ 78 | :: ------------------------------------------------------------ 79 | :: ------------------------------------------------------------ 80 | 81 | :start 82 | 83 | set repoName=stellirin/postgres-windows 84 | 85 | :: Build versions of PostgreSQL supported by EnterpriseDB 86 | set pgValue=%~1 87 | if [%pgValue%] == [] ( 88 | echo Building all PostgreSQL versions 89 | set pg94=true 90 | set pg95=true 91 | set pg96=true 92 | set pg10=true 93 | set pg11=true 94 | set pg12=true 95 | ) 96 | if NOT [%pgValue%] == [] ( 97 | set %pgValue%=true 98 | ) 99 | 100 | :: Build versions based on various Windows 10 base images 101 | set winValue=%~2 102 | if [%winValue%] == [] ( 103 | set win1809=true 104 | set win1903=true 105 | set win1909=true 106 | ) 107 | if NOT [%winValue%] == [] ( 108 | set %winValue%=true 109 | ) 110 | 111 | docker pull mcr.microsoft.com/windows/servercore:1809 112 | docker pull mcr.microsoft.com/windows/servercore:1903 113 | docker pull mcr.microsoft.com/windows/servercore:1909 114 | 115 | docker pull mcr.microsoft.com/windows/nanoserver:1809 116 | docker pull mcr.microsoft.com/windows/nanoserver:1903 117 | docker pull mcr.microsoft.com/windows/nanoserver:1909 118 | 119 | :: ------------------------------------------------------------ 120 | :: ------------------------------------------------------------ 121 | :: ------------------------------------------------------------ 122 | 123 | :: PostgreSQL 9.4 124 | if [%pg94%] == [true] ( 125 | call :postgres_build "9.4.24-2" 126 | if [%winValue%] == [] ( 127 | call :manifest_build "9.4" 128 | call :manifest_build "9.4.24" 129 | ) 130 | ) 131 | 132 | :: PostgreSQL 9.5 133 | if [%pg95%] == [true] ( 134 | call :postgres_build "9.15.19-2" 135 | if [%winValue%] == [] ( 136 | call :manifest_build "9.5" 137 | call :manifest_build "9.5.19" 138 | ) 139 | ) 140 | 141 | :: PostgreSQL 9.6 142 | if [%pg96%] == [true] ( 143 | call :postgres_build "9.6.15-2" 144 | if [%winValue%] == [] ( 145 | call :manifest_build "9.6" 146 | call :manifest_build "9.6.15" 147 | ) 148 | ) 149 | 150 | :: PostgreSQL 10 151 | if [%pg10%] == [true] ( 152 | call :postgres_build "10.10-2" 153 | if [%winValue%] == [] ( 154 | call :manifest_build "10" 155 | call :manifest_build "10.10" 156 | ) 157 | ) 158 | 159 | :: PostgreSQL 11 160 | if [%pg11%] == [true] ( 161 | call :postgres_build "11.5-2" 162 | if [%winValue%] == [] ( 163 | call :manifest_build "11" 164 | call :manifest_build "11.5" 165 | ) 166 | ) 167 | 168 | :: PostgreSQL 12 169 | if [%pg12%] == [true] ( 170 | call :postgres_build "12.0-1" 171 | if [%winValue%] == [] ( 172 | call :manifest_build "12" 173 | call :manifest_build "12.0" 174 | ) 175 | ) 176 | -------------------------------------------------------------------------------- /docker-entrypoint.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | SETLOCAL EnableDelayedExpansion 3 | 4 | :: Batch file has no concept of a function, only goto 5 | goto :start 6 | 7 | :: usage: CALL :file_env VARIABLE [DEFAULT] 8 | :: ie: CALL :file_env 'XYZ_DB_PASSWORD' 'example' 9 | :: (will allow for "%XYZ_DB_PASSWORD_FILE%" to fill in the value of 10 | :: "%XYZ_DB_PASSWORD%" from a file, especially for Docker's secrets feature) 11 | :file_env 12 | :: Reset all values 13 | set cmdVar= 14 | set fileVar= 15 | set default= 16 | set value= 17 | :: Start the 'function' 18 | set cmdVar=%~1 19 | set fileVar=%cmdVar%_FILE 20 | set default=%~2 21 | :: No concept of AND in batch scripts 22 | :: Instead we use nested if 23 | if NOT [!%cmdVar%!] == [] ( 24 | if NOT [!%fileVar%!] == [] ( 25 | :: Instead of exiting, just use the environment value 26 | echo Warning: both %cmdVar% and %fileVar% are set, %fileVar% will be ignored 27 | ) 28 | ) 29 | :: set as the default value 30 | set value=%default% 31 | if NOT [!%cmdVar%!] == [] ( 32 | :: override with the environment value 33 | set value=!%cmdVar%! 34 | ) 35 | :: No concept of ELIF in batch scripts 36 | :: we use nested if with opposite test 37 | if [!%cmdVar%!] == [] ( 38 | if NOT [!%fileVar%!] == [] ( 39 | :: override with the file value 40 | set /p value= NUL 59 | 60 | :: look specifically for PG_VERSION, as it is expected in the DB dir 61 | if NOT exist "%PGDATA%\PG_VERSION" ( 62 | 63 | call :file_env POSTGRES_USER, postgres 64 | call :file_env POSTGRES_PASSWORD 65 | call :file_env POSTGRES_INITDB_ARGS 66 | 67 | if NOT [!POSTGRES_PASSWORD!] == [] ( 68 | echo !POSTGRES_PASSWORD!> "%TEMP%\pgpass.tmp" 69 | set POSTGRES_INITDB_ARGS=!POSTGRES_INITDB_ARGS! --pwfile="%TEMP%\pgpass.tmp" 70 | ) 71 | 72 | if NOT [%POSTGRES_INITDB_WALDIR%] == [] ( 73 | set POSTGRES_INITDB_ARGS=!POSTGRES_INITDB_ARGS! --waldir %POSTGRES_INITDB_WALDIR% 74 | ) 75 | 76 | call initdb -U "!POSTGRES_USER!" -E UTF8 --no-locale -D "%PGDATA%" !POSTGRES_INITDB_ARGS! 77 | if exist "%TEMP%\pgpass.tmp" ( 78 | call del "%TEMP%\pgpass.tmp" 79 | ) 80 | 81 | if NOT [!POSTGRES_PASSWORD!] == [] ( 82 | set authMethod=md5 83 | echo authMethod: !authMethod! 84 | ) else ( 85 | echo **************************************************** 86 | echo WARNING: No password has been set for the database. 87 | echo This will allow anyone with access to the 88 | echo Postgres port to access your database. In 89 | echo Docker's default configuration, this is 90 | echo effectively any other container on the same 91 | echo system. 92 | echo Use "-e POSTGRES_PASSWORD=password" to set 93 | echo it in "docker run". 94 | echo **************************************************** 95 | set authMethod=trust 96 | echo authMethod: !authMethod! 97 | ) 98 | echo.>> "%PGDATA%\pg_hba.conf" 99 | echo host all all all !authMethod!>> "%PGDATA%\pg_hba.conf" 100 | 101 | :: internal start of server in order to allow set-up using psql-client 102 | :: does not listen on external TCP/IP and waits until start finishes 103 | call pg_ctl -U "!POSTGRES_USER!" -D "%PGDATA%" -w start 104 | 105 | call :file_env POSTGRES_DB !POSTGRES_USER! 106 | 107 | set psqlParam=^-v ON_ERROR_STOP=1 --username "!POSTGRES_USER!" --no-password 108 | 109 | :: Create a database with its name as the user name, override %PGDATABASE% 110 | if NOT [!POSTGRES_DB!] == [postgres] ( 111 | echo CREATE DATABASE :"db"; | call psql !psqlParam! --dbname postgres --set db="!POSTGRES_DB!" 112 | ) 113 | set psqlParam=^-v ON_ERROR_STOP=1 --username "!POSTGRES_USER!" --no-password --dbname "!POSTGRES_DB!" 114 | 115 | :: Execute any batch scripts for this new DB 116 | for %%f in (C:\docker-entrypoint-initdb.d\*.cmd) do ( 117 | echo cmd: running %%f 118 | call "%%f" 119 | ) 120 | :: Execute any SQL scripts for this new DB 121 | for %%f in (C:\docker-entrypoint-initdb.d\*.sql) do ( 122 | echo psql: running %%f 123 | call psql !psqlParam! -f "%%f" 124 | ) 125 | 126 | pg_ctl -U "!POSTGRES_USER!" -D "%PGDATA%" -m fast -w stop 127 | 128 | echo PostgreSQL init process complete; ready for start up. 129 | ) 130 | 131 | :: start the database 132 | call %* 133 | --------------------------------------------------------------------------------