Customization

Adding Start Up Scripts

We provide a few default entrypoint scripts to get you going, but sometimes you want to just add your own. We've made it easy to do that with our entrypoint.d directory.

Entrypoint Script Requirements

Before you write your entry point script, be aware of the following requirements. Your script should:
  • Be executable (755 permissions)
  • Located in the /etc/entrypoint.d directory
  • Have the file extension ending in .sh
We recommend writing your script in /bin/sh for the best compatibility between Alpine and Debian. If you choose to use /bin/bash, your script will only be able to run on Debian-based images.

Choose your execution order

Since we provide default entrypoint scripts, you may want to choose the order in which your scripts are executed. We've made it easy to do that by prefixing your script with a number. The lower the number, the earlier it will be executed.

If you want to disable our entrypoint scripts, you can set DISABLE_DEFAULT_CONFIG to true in your environment variables.

Long running services

Don't use entrypoint scripts for long-running services. You want your services to be monitored and restarted if they crash.

Anything in the /etc/entrypoint.d directory are scripts that are intended to run quickly and then move on. If you run a service as an entrypoint script, that service may crash and not be restarted.

Instead, learn about using S6 overlay so your services can be properly initialized and monitored. See the S6 Overylay project for more details on how to write your own S6 service.

Example: Create a custom entrypoint script

In this example, let's create a 99-my-script.sh so it executes after all the other default scripts.

Dockerfile
FROM serversideup/php:8.4-fpm-nginx

# Copy our scripts as executable
COPY --chmod=755 ./entrypoint.d/ /etc/entrypoint.d/

In the example above, you can see in the Dockerfile we are copying our entrypoint.d directory to /etc/entrypoint.d/ in the container. We're also setting the permissions to 755 so our scripts are executable.

Running our example

When we run docker compose up, we can confirm our script is executing by checking the logs:

php-1  | πŸ‘‰ [NOTICE]: Improve PHP performance by setting PHP_OPCACHE_ENABLE=1 (recommended for production).
php-1  | (init-webserver-config): Processing /etc/nginx/nginx.conf.template β†’ /etc/nginx/nginx.conf...
php-1  | (init-webserver-config): Processing /etc/nginx/site-opts.d/http.conf.template β†’ /etc/nginx/site-opts.d/http.conf...
php-1  | (init-webserver-config): Processing /etc/nginx/site-opts.d/https.conf.template β†’ /etc/nginx/site-opts.d/https.conf...
php-1  | ℹ️ NOTICE (init-webserver-config): Enabling NGINX site with SSL "off"...
php-1  | πŸ‘‹ Hello, world!
php-1  | [03-Nov-2025 19:35:29] NOTICE: fpm is running, pid 93
php-1  | [03-Nov-2025 19:35:29] NOTICE: ready to handle connections
php-1  | HTTP Status Code: 200
php-1  | βœ… NGINX + PHP-FPM is running correctly.

You can see our πŸ‘‹ Hello, world! is executing after the initialization of 10-init-unit.sh.

Running Custom Artisan Commands

If you need to run a custom artisan command at start up, you could update your entrypoint.d/99-my-script.sh file to look like this:

entrypoint.d/99-my-script.sh
#!/bin/sh
# Check if the artisan file exists
if [ -f "$APP_BASE_DIR/artisan" ]; then
  # Run the custom artisan command
  php "$APP_BASE_DIR/artisan" my:custom-command
else
  # If the artisan file is not found, stop the container
  echo "❌ Artisan file not found in $APP_BASE_DIR"
  exit 1
fi

# Exit with a success code
exit 0

Best practices for running custom artisan commands

  • Use /bin/sh for the best compatibility between Alpine and Debian. If you choose to use /bin/bash, your script will only be able to run on Debian-based images.
  • Check to see if the artisan file exists before running the command
  • Exit with a success code
  • Name your file appropriately, so it executes in logic order with the other scripts (see our default configurations)

You can change the name of your file to whatever you want, but we recommend using a number prefix to ensure it executes in the correct order. For example, if you want to run a command after the default scripts, you could name your file 99-my-command.sh. If you want to run a command before the default scripts, you could name your file 1-my-command.sh.

Advanced Scenarios: S6 Overlay dependencies

If you want to customize an image that uses S6 Overlay (fpm-nginx or fpm-apache), you may have an advanced scenario where you have a custom S6 service that needs to be executed after one of our entrypoint scripts. In order to do this, you'll need to move all our scripts from the /etc/entrypoint.d directory to the /etc/s6-overlay/scripts directory. This would be a very time consuming scenario if you did this manually, but thankfully you can use our docker-php-serversideup-s6-init script to do this for you.

Dockerfile
FROM serversideup/php:8.4-fpm-nginx

# Set the user to root for our build steps
USER root

# If you have your own one-shot scripts, copy them to the entrypoint.d directory
COPY --chmod=755 ./entrypoint.d/ /etc/entrypoint.d/

# Copy our entrypoint scripts into the S6 Overlay scripts directory
RUN docker-php-serversideup-s6-init

# If you have your own long running services, copy them to the s6 directory
COPY --chmod=755 ./my-s6-service/ /etc/s6-overlay/s6-rc.d/my-s6-service/

# Drop back to the non-root user
USER www-data

In the above file, we're copying our "one-shot" scripts to the /etc/entrypoint.d directory and our long running services to the /etc/s6-overlay directory. One-shot scripts are scripts that are intended to run quickly and then move on. Long running services are services that are intended to run for a long time and need to be monitored and restarted if they crash.

The magic happens when we run docker-php-serversideup-s6-init. This script will move all our scripts from the /etc/entrypoint.d directory to the /etc/s6-overlay/scripts directory and set the correct dependencies for our S6 services.

You can now reference our script names as dependencies in your own S6 service.

Learn more about S6 Overlay