---
head.title: 'Adding your own start up scripts - Docker PHP - Server Side Up'
description: 'Learn how to use our entrypoint.d directory to customize your container start up experience.'
layout: docs
---

# Adding your own start up scripts
::lead-p
We provide a few [default scripts](/docs/getting-started/default-configurations#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
::note
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](/docs/getting-started/default-configurations#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.

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

## 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.

First, let's take a look at our project structure:

::code-panel
---
label: "Project Structure"
---
```txt
.
├── Dockerfile
├── docker-compose.yml
├── entrypoint.d
│   └── 99-my-script.sh
└── public
    └── index.php
```
::
Let's take a look at the script that we want to run. We can keep this simple for now.

::code-panel
---
label: "99-my-script.sh"
---
```bash
#!/bin/sh
echo "👋 Hello, world!"
```
::

Now, let's take a look at our `Dockerfile`:

::code-panel
---
label: "Dockerfile"
---
```dockerfile
FROM serversideup/php:8.3-unit

COPY --chmod=755 ./entrypoint.d/ /etc/entrypoint.d/
```
::

In the above file, we're 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.

Finally, let's take a look at our `docker-compose.yml` file:

::code-panel
---
label: "docker-compose.yml"
---
```yaml
version: '3'
services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 80:8080
    volumes:
      - .:/var/www/html
```
::

In the above file, we're building our image using the `Dockerfile` in the current directory. We're also mounting our current directory to `/var/www/html` in the container.

## Running our example
When we run `docker compose up`, we should see the following output:

::code-panel
---
label: "Output of \"docker compose up\""
---
```txt
example-project  | init-unit: Stopping Unit daemon after initial configuration...
example-project  | 2023/12/05 19:52:37 [notice] 29#29 process 33 exited with code 0
example-project  | init-unit: Waiting for control socket to be removed...
example-project  | 2023/12/05 19:52:37 [notice] 29#29 process 34 exited with code 0
example-project  | 
example-project  | init-unit: Unit initial configuration complete; ready for start up...
example-project  | 
example-project  | 👋 Hello, world!
example-project  | 2023/12/05 19:52:38 [info] 1#1 unit 1.31.1 started
example-project  | 2023/12/05 19:52:38 [info] 65#65 discovery started
example-project  | 2023/12/05 19:52:38 [notice] 65#65 module: php 8.3.0 "/usr/lib/unit/modules/php.unit.so"
example-project  | 2023/12/05 19:52:38 [info] 1#1 controller started
example-project  | 2023/12/05 19:52:38 [notice] 1#1 process 65 exited with code 0
example-project  | 2023/12/05 19:52:38 [info] 67#67 router started
example-project  | 2023/12/05 19:52:38 [info] 67#67 OpenSSL 3.0.11 19 Sep 2023, 300000b0
```
::

You can see our `👋 Hello, world!` is executing *after* the initialization of `10-init-unit.sh`.

## Additional Steps For FPM-Apache & FPM-NGINX (S6 Overlay based images)
If the image you're working with is using S6 Overlay (`fpm-nginx` and `fpm-apache`), you'll need to take additional steps to get your scripts to execute.

### Background
S6 Overlay uses a set of directories to execute scripts at different stages of the container's life cycle. You can read more about it in [S6 Overlay's documentation](https://github.com/just-containers/s6-overlay).

### Our Solution
Instead of reading through the complexities of S6 Overlay, we wrote a script called `docker-php-serversideup-s6-init` that will automatically configure your script located in `/etc/entrypoint.d` to execute correctly with S6 Overlay.

### `docker-php-serversideup-s6-init` Usage
The only thing you need to do is call `docker-php-serversideup-s6-init` after your script is copied. Here's an example:

::note
Depending on your usecase, you may want to set `S6_CMD_WAIT_FOR_SERVICES` to `1` in your environment variables. This will make sure your script doesn't execute until all the services are ready. Learn more about this in [S6 Overlay's documentation](https://github.com/just-containers/s6-overlay).
::

::code-panel
---
label: "Dockerfile"
---
```dockerfile
FROM serversideup/php:8.3-fpm-nginx

ENV S6_CMD_WAIT_FOR_SERVICES=1

COPY --chmod=755 ./entrypoint.d/ /etc/entrypoint.d/

# Change to root, so we can do root things
USER root

# As root, run the docker-php-serversideup-s6-init script
RUN docker-php-serversideup-s6-init

# Change back to the www-data user
USER www-data
```
::

The above `Dockerfile` will copy scripts from our `entrypoint.d` directory to `/etc/entrypoint.d/` and then run `docker-php-serversideup-s6-init`, which will then take any scripts in `/etc/entrypoint.d/` and configure them to execute correctly with S6 Overlay.