docker-library / postgres

Docker Official Image packaging for Postgres
http://www.postgresql.org
MIT License
2.16k stars 1.13k forks source link

Proposal for initdb-script ran every time #1094

Closed claudiomerli closed 9 months ago

claudiomerli commented 1 year ago

In a project we have to handle our database and user and roles by an SH script. These DB can change very often and we made a script put in /docker-entrypoint-initdb.d that is executed on first initialisation. Can be useful to have a second directory such as (/docker-entrypoint-startdb.d) with scripts that are executed every time the DB is launched, also if the initialisation is already done.

tianon commented 1 year ago

See https://github.com/docker-library/postgres/issues/173, https://github.com/docker-library/postgres/issues/821, https://github.com/docker-library/postgres/issues/191, https://github.com/docker-library/postgres/issues/929 for some other issues that have some good thoughts / suggestions (one of/many of which this is probably a solid duplicate of).

Gruummy commented 1 year ago

In my project i do such things already for pgadmin4 container (i know this is pgadmin and not postgres .... only as example)

# Use non fixed patch version to be able to autorefresh
# Version 7.5 referenced at 27.07.2023
# --> https://hub.docker.com/r/dpage/pgadmin4/tags
#
FROM WhatEverRegistry/dpage/pgadmin4:7.5

USER root

# Add all local parts of source 1 to 1 into the container
# Info: All files here were checked. They are not existing before
#       in the container. So this is only an addition of additional
#       files to the container image.
# Attention: The content of the src directory must be 1 to 1 the
#            file layout inside the container image. All content
#            is directly added to the root of the container as base
#
ADD src /

# Add possibility to include automatically additional scripts to
# "/custom-entrypoint.d/" inside the docker container, if this image is
# used in a docker "FROM" style. (It is a docker BUILD trigger)
#
ONBUILD COPY /src/custom-entrypoint.d/* /custom-entrypoint.d/

# Add ENV variable to container pointing to /etc/profile to force
# the ash shell to start preparing the environment with the contained
# logic when an interactive (login) shell will be requested.
# --> google: how-to-get-etc-profile-to-run-automatically-in-alpine-docker
#
ENV ENV="/etc/profile"

# Extend source image (based on alpine) with special things for special reasons
# To avoid creation of multipe docker layers, all the modifications are done
# here in one big collection of RUN commands during docker build.
#
    # 1. Make all .sh scripts of custom extensions executable inside the container
    #    (for directories which are copied from "/src" folder to "/" inside the image)
RUN find /build/ -type f -iname "*.sh" -exec chmod +x {} \; && \
    find /custom-entrypoint.d/ -type f -iname "*.sh" -exec chmod +x {} \; && \
    chmod +x /custom-entrypoint.sh && \
    #
    # 2. Patch permissions of files inside the container which needs at startup
    #    time to be changeable by *entypoint.sh scripts / startup user.
    /build/docker/FilesToBePatchable.sh && \
    #
    # 3. Remove all only for the build time related contents from the image
    rm -rf /build && \
    #
    # 4. Add empty wpad.dat to root of web to avoid http 404 errors in case
    #    that you run the container locally and Windows tries to scan this file
    touch /pgadmin4/pgadmin/wpad.dat && \
    #
    # 5. home of pgadmin is missing by default, so build of container fails if you
    #    use for example "VSCode" as local developer / test software
    mkdir -p /home/pgadmin && \
    chmod 775 /home/pgadmin && \
    chown -R pgadmin /home/pgadmin && \
    #
    # 6. Add bash for usage in later support actions
    apk --no-cache add --upgrade bash && \
    #
    # 7. Add run-parts in full version (busybox version is to limited)
    apk --no-cache add --upgrade run-parts && \
    #
    # 8. Add tz in to fullfill requirement of TZ="Europe/Berlin"
    apk --no-cache add --upgrade tzdata && \
    #
    # 9. Remove special set capabilities from orignal dockerfile of pgadmin.
    #    Container hardening in AWS EKS removes all capabilities and as a
    #    consequence python can not longer be started
    #
    #    !!! This needs to be revisited when you go to newer pgadmin image !!!
    find /usr/bin/ -type f -iname "python*" -exec setcap -r {} \;

# Now there is no longer a need to be root. We can savely switch to pgadmin user
USER pgadmin

# Go to unpriviledged port to not struggle with kubernetes securityContext.capabilities
EXPOSE 5050

# Now run our custom entrypoint script as a wrapper for the official one
# from the original upstream source
#
ENTRYPOINT ["/custom-entrypoint.sh"]

This give the possibility that at startup any files in a row can be executed however the files are injected / mounted to to container

Here the content of the script which is executed as custom entrypoint

#!/bin/sh
# Alpine does not contain bash as default shell, so do everything in "sh" style

# Custom entrypoint script wrapper. Inspired by:
# https://www.camptocamp.com/en/news-events/flexible-docker-entrypoints-scripts
#
DIR=/custom-entrypoint.d
if [[ -d "$DIR" ]]; then
  /bin/run-parts --verbose --regex '^[a-zA-Z0-9\._-]+$' "$DIR"
fi

# Call the original entrypoint of the base image with trailing "$@" to transfer pid 1
# to the upstream entrypoint so that signals get handeled correctly.
#
exec /entrypoint.sh "$@"

If someone finds this inspiring ... please do not implement "/custom-entrypoint.d" as default in a container image ... choose another namespace ... 'custom*' namespace should be reserved for usage by "custom" extentions ;-)

... please excuse the big amount of the comments there ... but i am a comment ... lover ...

i think all the time when i implement things for the situation ... what i would think if i need to fix / patch things which had been done years ago by other colleagues which i can not ask why it was done this way ...