i try to understand why, by executing this command :
docker run --rm -it postgres bash
container starts well, gives me a bash prompt, without intializing a postgres server.
In fact, when i only execute this :
docker run --rm -it postgres
container tries to intialize a postgres server and failed because a non provided '-e POSTGRES_PASSWORD' sequence which is absolutly normal.
But the question is : what is the mechanism in 'docker' or 'in the official postgres image' that tell container to :
- not initialize a postgres server when an argument is provided at the end of 'docker run --rm -it postgres' sequence (like bash or psql..)
- DO initialize a postgres server when NO argument is provided (docker run --rm -it postgres)
Thanks by advance.
CodePudding user response:
The postgres
image Dockerfile is set up as
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]
When an image has both an ENTRYPOINT
and a CMD
, the command part is passed as additional parameters to the entrypoint. If you docker run postgres bash
, the bash
command overrides the command part but leaves the entrypoint intact.
This entrypoint wrapper script setup is a common and useful technique. The script can do anything it needs to do to make the container ready to use, and then end with the shell command exec "$@"
to run the command it got passed as arguments. Typical uses for this include dynamically setting environment variables, populating mounted volumes, and (for application containers more than database containers) waiting for a database or other container dependency to be ready.
In the particular case of the postgres
image, its entrypoint script does (simplified):
if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then
docker_setup_env
docker_create_db_directories
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
docker_init_database_dir
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/*
fi
fi
exec "$@"
Since the entrypoint script is just a shell script and it does have the command as positional parameters, it can make decisions based on what the command actually is. In this case, if [ "$1" = 'postgres' ]
– if the main container command is to run the PostgreSQL server – then do the first-time initialization, otherwise don't.