0

In our company we are trying to migrate an application to Docker with Windows Containers. The application uses a PostgreSQL database. We are able to get the application running inside the Container. However, whenever we stop the container and start a new one with the same image all the changes made into the database are gone. How can we achieve persistence with data volumes on Windows Containers?

We've read multiple articles that persistence can be accomplished with data volumes. We've followed this guide and we able to achieve persistence without any problem on Linux Containers https://elanderson.net/2018/02/setup-postgresql-on-windows-with-docker/

However on Windows Containers something is missing to get us where we need.

The Dockerfile we are using for creating an image with postgres on Windows Containers is:

-----START-----

FROM  microsoft/aspnet:4.7.2-windowsservercore-1709

EXPOSE 5432

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN [Net.ServicePointManager]::SecurityProtocol = 'Tls12, Tls11, Tls' ; \
    Invoke-WebRequest -UseBasicParsing -Uri 'https://get.enterprisedb.com/postgresql/postgresql-9.6.10-2-windows-x64.exe' -OutFile 'postgresql-installer.exe' ; \
    Start-Process postgresql-installer.exe -ArgumentList '--mode unattended --superpassword password' -Wait ; \
    Remove-Item postgresql-installer.exe -Force

SHELL ["cmd", "/S", "/C"]

RUN setx /M PATH "C:\\Program Files\\PostgreSQL\\9.6\\bin;%PATH%" && \
    setx /M DATA_DIR "C:\\Program Files\\PostgreSQL\\9.6\\data" && \
    setx /M PGPASSWORD "password"

RUN powershell -Command "Do { pg_isready -q } Until ($?)" && \
    echo listen_addresses = '*' >> "%DATA_DIR%\\postgresql.conf" && \
    echo host  all  all  0.0.0.0/0  trust >> "%DATA_DIR%\\pg_hba.conf" && \
    echo host  all  all  ::0/0      trust >> "%DATA_DIR%\\pg_hba.conf" && \
    net stop postgresql-x64-9.6

----END----

The commands we are using to build the image and running the container are.

docker build -t psql1709 .

docker run -d -it -p 8701:5432 --name postgresv1 -v "posgresData:c:\Program Files\PostgreSQL\9.6\data" psql1709
Jin Lee
  • 3,194
  • 12
  • 46
  • 86

1 Answers1

0

The problem likely is that the DATA_DIR is not set when running the container, and as a result, the database is written to a different path than the path where your volume is mounted.

Each RUN instruction in a Dockerfile is executed in a new container, and the resulting filesystem changes of the step is committed to a new layer.

However, memory state is not persisted, so when you run;

setx /M DATA_DIR "C:\\Program Files\\PostgreSQL\\9.6\\data"

That environment variable is only known during that run instruction, but not after.

To set an environment variable that's persisted as part of the image that you build (and will be set for following RUN instructions, and when running the image/container), use the ENV dockerfile instruction;

ENV DATA_DIR "C:\\Program Files\\PostgreSQL\\9.6\\data"

(I'm not using Windows, so double check if the quoting/escaping works as expected)

Note: I see you're setting PGPASSWORD in an environment variable; be aware that (when using ENV), environment variables can be seen by anyone that has access to the container or image (docker inspect will show this information). In this case, the password seems to be a "default" password, so likely not a concern.

thaJeztah
  • 27,738
  • 9
  • 73
  • 92
  • Thanks thatJeztah for the reply. But should I remove setx /M DATA_DIR "C:\\Program Files\\PostgreSQL\\9.6\\data" and add ENV DATA_DIR "C:\\Program Files\\PostgreSQL\\9.6\\data". Or just add ENV DATA_DIR "C:\\Program Files\\PostgreSQL\\9.6\\data"? – Antonio Maciel Jun 14 '19 at 12:43
  • I think you can remove that, yes – thaJeztah Jun 16 '19 at 16:19