11

I'm currently trying to run PostgreSQL 10.6.1 in a docker container (Base-Image is mcr.microsoft.com/windows/servercore:ltsc2016) that should be run on Windows Server 2016 Datacenter (Version 1607, Build 14393.2759).

Everything runs fine, including PostgreSQL's initdb and running PostgreSQL afterwards - as long as PostgreSQL's data directory is not a volume on the docker host.

If I try to run it having the PostgreSQL's data directory placed on either a named or bind volume, PostgreSQL is able to do its initdb but fails to start afterwards.

I suspect that the error is due to the fact that mounted volumes are visible as symlink within containers depending on mcr.microsoft.com/windows/servercore:ltsc2016, causing PostgreSQL to fail. On mcr.microsoft.com/windows/servercore:1809, this behaviour changed - mounted volumes look like 'normal' directories and PostgreSQL is able to start.

As there is no useful error message at all and running a database having no persistent storage outside of a container sounds like a really useless thing, any help is appreciated.

The Dockerfile I'm using looks like this:

FROM mcr.microsoft.com/windows/servercore:ltsc2016
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
ARG version=10.6-1

RUN [Net.ServicePointManager]::SecurityProtocol = 'Tls12, Tls11, Tls' ; \
    Invoke-WebRequest $('https://get.enterprisedb.com/postgresql/postgresql-{0}-windows-x64-binaries.zip' -f $env:version) -OutFile 'postgres.zip' -UseBasicParsing ; \
    Expand-Archive postgres.zip -DestinationPath C:\ ; \
    Remove-Item postgres.zip ; \
    Remove-Item 'C:\pgsql\pgAdmin 4' -Recurse ; \
    Remove-Item 'C:\pgsql\StackBuilder' -Recurse ; \
    Remove-Item 'C:\pgsql\doc' -Recurse
RUN [Net.ServicePointManager]::SecurityProtocol = 'Tls12, Tls11, Tls' ; \
    Invoke-WebRequest 'http://download.microsoft.com/download/0/5/6/056DCDA9-D667-4E27-8001-8A0C6971D6B1/vcredist_x64.exe' -OutFile vcredist_x64.exe ; \
    Start-Process vcredist_x64.exe -ArgumentList '/install', '/passive', '/norestart' -NoNewWindow -Wait ; \
    Remove-Item vcredist_x64.exe

SHELL ["cmd", "/S", "/C"]
RUN setx /M PATH "C:\pgsql\bin;%PATH%"
RUN MD data
RUN setx /M PGDATA "C:\data"

ENV PGUSER postgres
ENV PGPASSWORD postgres

COPY docker-entrypoint.cmd /
COPY start.cmd /

EXPOSE 5432

ENTRYPOINT ["docker-entrypoint.cmd"]
CMD [ "start.cmd"]

The referenced docker-entrypoint.cmd looks like this:

@ECHO %PGPASSWORD% > pw.txt

@ECHO OFF
IF NOT EXIST %PGDATA%/PG_VERSION (
    initdb.exe --encoding=UTF8 --username=%PGUSER% --pwfile=pw.txt
    @echo host all all 0.0.0.0/0 trust > %PGDATA%/pg_hba.conf
    @echo host all all ::0/0 trust >> %PGDATA%/pg_hba.conf
)

%*

The referenced start.cmd looks like this:

@echo off

pg_ctl start -o "-h * -c max_prepared_transactions=100 -c max_connections=1000"

REM logic to keep container alive
:ENDLESS
CALL :sleep 100000
goto ENDLESS
exit

REM https://superuser.com/questions/48231/how-do-i-make-a-batch-file-wait-sleep-for-some-seconds
:sleep
ping 127.0.0.1 -n %1 -w 1000 > NUL
Kalle Richter
  • 8,008
  • 26
  • 77
  • 177
sven
  • 4,161
  • 32
  • 33
  • 1
    I believe you already figured it out... if that's the case, there's no point on having a DBMS inside a container if you can persist the data files to a real file system. Sorry, I'm not sure what your question is... – sebagomez Feb 19 '19 at 18:42
  • @sebagomez the problem is that if you use a named/bind volume for persisting the data, `postgres` doesn't start (while `initdb` can initialize the data directory on the volume). – Kalle Richter Feb 21 '19 at 06:49
  • what version of PowerShell you work ? – Soleil Feb 25 '19 at 21:18
  • you can check this link https://docs.docker.com/install/windows/docker-ee/ – Soleil Feb 25 '19 at 21:22
  • How are you defining your volumes? Using the `docker run` command or via `docker-compose` ? – Manish Dash Feb 26 '19 at 07:20

0 Answers0