How to use an entrypoint script to initialize container data at runtime

Article ID: KB000493


How do I initialize/seed data into my container at runtime, before the daemon process starts up in my container?


There's a very common pattern used to initialize stateful data in a container at runtime. Use a shell script as the ENTRYPOINT of a container, and execute the necessary setup steps before passing control to a long-running process.

  1. Create a shell script with the following contents (named in our example):
set -e

if [ "$1" = 'postgres' ]; then
    chown -R postgres "$PGDATA"

    if [ -z "$(ls -A "$PGDATA")" ]; then
        gosu postgres initdb

    exec gosu postgres "$@"

exec "$@"
  1. Your Dockerfile should then call this script. For example, the following Dockerfile is an excerpt from the postgres image:
FROM debian:stretch
COPY /usr/local/bin/
RUN ln -s /usr/local/bin/ / # backwards compat
CMD ["postgres"]

You can see that when the container starts up, the command portion is interprated to be sh -c ' postgres'.

The script is invoked and given the argument postgres. The script checks if the first argument sent to it is equal to the string postgres, and if so, executes a series of instructions to set up a database. Finally, the exec shell construct is invoked, so that the final command given becomes the container's PID 1. $@ is a shell variable that means "all the arguments", so that leaves us with simply exec postgres.

What's Next

See Dockerfile Best Practices