Steps to reproduce:
-
Download and run
postgres:9.6.24
:docker run --name my_container --restart=always -d -p 127.0.0.1:5432:5432 -e POSTGRES_PASSWORD=pgmypass postgres:9.6.24
Here result:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 879883bfc84a postgres:9.6.24 "docker-entrypoint.s…" 26 seconds ago Up 25 seconds 127.0.0.1:5432->5432/tcp my_container
OK.
-
Open file inside container
/var/lib/postgresql/data/pg_hba.conf
docker exec -it my_container bash root@879883bfc84a:/# cat /var/lib/postgresql/data/pg_hba.conf IPv4 local connections: host all all 127.0.0.1/32 trust
-
Replace file
/var/lib/postgresql/data/pg_hba.conf
inside container by my file. Copy and overwrite my file from host to container:tar --overwrite -c pg_hba.conf | docker exec -i my_container /bin/tar -C /var/lib/postgresql/data/ -x
-
Make sure the file has been modified. Go inside container and open changed file
docker exec -it my_container bash root@879883bfc84a:/# cat /var/lib/postgresql/data/pg_hba.conf IPv4 local connections: host all all 0.0.0.0/0 trust
As you can see the content of file was changed.
-
Create new image from container
docker commit my_container
See result:
docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> ee57ad4bc6b4 3 seconds ago 200MB postgres 9.6.24 027ccf656dc1 12 months ago 200MB
Now tag my new image
docker tag ee57ad4bc6b4 my_new_image:1.0.0
See reult:
docker images REPOSITORY TAG IMAGE ID CREATED SIZE my_new_image 1.0.0 ee57ad4bc6b4 About a minute ago 200MB postgres 9.6.24 027ccf656dc1 12 months ago 200MB
OK.
-
Stop and delete old continer:
docker stop my_continer docker rm my_container
See result:
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
As you can see not exit any container. OK.
-
Create new continer from new image
docker run --name my_new_container_test --restart=always -d -p 127.0.0.1:5432:5432 -e POSTGRES_PASSWORD=pg1210 my_new_image:1.0.0
See result:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3a965dbbd991 my_new_image:1.0.0 "docker-entrypoint.s…" 7 seconds ago Up 6 seconds 127.0.0.1:5432->5432/tcp my_new_container
-
Open file inside container
/var/lib/postgresql/data/pg_hba.conf
docker exec -it my_new_container bash root@879883bfc84a:/# cat /var/lib/postgresql/data/pg_hba.conf IPv4 local connections: host all all 127.0.0.1/32 trust
As you can see my change in files are lost. The content of file is original. Not my changes.
P.S. This problem is only with file pg_hba.config. E.g if I created in the container the folder and file: /Downaloads/myfile.txt
then this file not lost in the my container "my_new_container".
2
Answers
Docker Container is a readyonly entity, which means if you will create a file into the container, remove it and re-create it (The container), the file is not supposed to be there.
what you want to do is one of two things,
docker volume usages
Dockerfile Reference
Editing files inside container with
docker exec
, in general, will in fact cause you to lose work. You mentiondocker commit
but that’s almost never a best practice. (If this was successful, but then you discovered PostgreSQL 9.6.24 exactly had some critical bug and you must upgrade, could you recreate the exact some image?)In the case of the
postgres
image, the files in/var/lib/postgresql/data
are always stored in a Docker volume or mount point. In your case you didn’t use adocker run -v
option, but the image is configured to create an anonymous volume in that directory. The volume is not included indocker commit
, which is why you’re not seeing it on the rebuilt container. (Also see docker postgres with initial data is not persisted over commits.)For editing a configuration file, the easiest thing to do is to store the data on the host system. Create a directory to hold it, and extract the configuration file from the image. (Since the data directory is created by the image’s startup script, you need a slightly longer path to get it out.)
Now when you run the container, provide this data directory as a bind mount. That will inject the configuration file, but also cause the database data to persist over container exits.
Note that this sequence doesn’t use
docker exec
or "go inside" containers at all, and you haven’t created an image without corresponding source. Everything is run with commands from the host. If you do need to reset the database data, in this setup, it’s just files, and you canrm -rf pgdata
, maybe saving the modified configuration file along the way.(If I’m reading this configuration change correctly, you’re trying to globally disable passwords and instead allow
trust
authentication for all inbound connections. That’s not usually a good idea, especially since username/password authentication is standard in every database library I’ve encountered. You probably still want the volume to persist data, but I might not make this change topg_hba.conf
.)