Skip to main content

draky-entrypoint

Introduction

draky-entrypoint is an addon that automatically attaches the special entrypoint to selected services. This entrypoint will augment any container with additional functionality that is commonly useful. The original entrypoint will still run, so don't worry about breaking anything.

To use it, download the latest release of the draky-entrypoint from the repository and extract it in the .draky/addons directory in an initialized project.

We will start with the codebase that we ended up with at the end of the Basics tutorial, minus commands — essentially the default template plus a MariaDB definition and variables.

This is our project's structure:

.draky/
commands/
README.txt
env/
dev/
docker-compose.recipe.yml
services/
mariadb/
variables.dk.yml
services.yml
README.md
.gitignore
core.dk.yml
local.dk.yml.example
template.dk.yml
# .draky/env/dev/docker-compose.recipe.yml

services:
database:
extends:
file: ../../services/mariadb/services.yml
service: mariadb
# .draky/services/mariadb/variables.dk.yml

variables:
MARIADB_VERSION: 12
MARIADB_IMAGE: "mariadb:${MARIADB_VERSION}"
MARIADB_DATABASE: main
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_EXPOSED_PORT: 3306
# .draky/services/mariadb/services.yml

services:
mariadb:
image: "mariadb:${MARIADB_VERSION}"
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD}"
MARIADB_DATABASE: "${MARIADB_DATABASE}"
ports:
- "${MARIADB_EXPOSED_PORT}:3306"

Let's build the docker-compose.yml file with the draky env build command. We should get something like this:

# .draky/env/dev/docker-compose.yml

# This file is autogenerated because the environment contains a recipe. To modify the services, modify the recipe.
services:
database:
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: ${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD}
MARIADB_DATABASE: ${MARIADB_DATABASE}
image: ${MARIADB_IMAGE}
ports:
- ${MARIADB_EXPOSED_PORT}:3306

Now let's add the latest release of the draky-entrypoint to our project. We'll download the latest release from the repository and put it in the .draky/addons/draky-entrypoint directory. This gives us the following structure:

.draky/
addons/
draky-entrypoint/
.gitignore
draky-entrypoint.addon.dk.yml
draky-entrypoint.sh
hooks.py
commands/
README.txt
env/
dev/
docker-compose.recipe.yml
services/
mariadb/
variables.dk.yml
services.yml
README.md
.gitignore
core.dk.yml
local.dk.yml.example
template.dk.yml

And finally, we will add the draky-entrypoint addon to our mariadb definition:

# .draky/services/mariadb/services.yml

services:
mariadb:
image: "mariadb:${MARIADB_VERSION}"
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD}"
MARIADB_DATABASE: "${MARIADB_DATABASE}"
ports:
- "${MARIADB_EXPOSED_PORT}:3306"
draky: # <-- added
addons: # <-- added
- draky-entrypoint # <-- added

This is enough to enable the addon for the service. It will work only when using a recipe, as that's part of a recipe's specification, but not the docker-compose.yml one. So, this value will be removed from the generated docker-compose.yml file, but the addon will influence the final result.

Now run draky env build again to see the difference!

# .draky/env/dev/docker-compose.yml

# This file is autogenerated because the environment contains a recipe. To modify the services, modify the recipe.
services:
database:
command: # <-- this has been added
- mariadbd # <-- this has been added
entrypoint: # <-- this has been added
- /draky-entrypoint.sh # <-- this has been added
- docker-entrypoint.sh # <-- this has been added
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: ${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD}
MARIADB_DATABASE: ${MARIADB_DATABASE}
image: ${MARIADB_IMAGE}
ports:
- ${MARIADB_EXPOSED_PORT}:3306
volumes: # <-- this has been added
- ${DRAKY_PROJECT_CONFIG_ROOT}/addons/draky-entrypoint/draky-entrypoint.sh:/draky-entrypoint.sh:cached # <-- this has been added

As you can see, the service definition of our database in the docker-compose.yml has been modified by the draky-entrypoint addon.

It mounted its own entrypoint script, made the service use it, but also made sure that the original entrypoint and command are still there and will be executed. This way no features of the original image will be lost.

The new entrypoint gives the image some neat additional functionality that we will explore next.

Initialization scripts

/draky-entrypoint.resources is a directory inside the container that is supposed to contain all resources used by draky-entrypoint. You should mount it as a volume; for example, like this:

- "./resources:/draky-entrypoint.resources:cached,ro"

Now you can place resources used by draky-entrypoint in this directory. One of them is the init.d directory.

All scripts under /draky-entrypoint.resources/init.d will be executed on container startup. This is useful for initializing databases, for example. We can use this directory to perform all kinds of preparations. The MariaDB image already has such a directory available: /docker-entrypoint-initdb.d, but not all images do, and draky-entrypoint provides a unified way to perform initialization across images.

So, let's mount the resources directory:

# .draky/services/mariadb/services.yml

services:
mariadb:
image: "${MARIADB_IMAGE}"
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD}"
MARIADB_DATABASE: "${MARIADB_DATABASE}"
ports:
- "${MARIADB_EXPOSED_PORT}:3306"
volumes: # <-- this has been added
- "./resources:/draky-entrypoint.resources:cached,ro" # <-- this has been added
draky:
addons:
- draky-entrypoint

Now each script that will be added to the .draky/services/mariadb/resources/init.d directory will run on the container's startup.

Let's add one:

# .draky/services/mariadb/resources/init.d/00-init.sh

#!/usr/bin/env sh
echo "I'm running on startup!"

And remember to make it executable: chmod u+x .draky/services/mariadb/resources/init.d/00-init.sh

Now when we run draky env up, in the container logs we will see something like this:

/draky-entrypoint.sh: Running extra initialization scripts.
2025-08-27T11:25:54.948602241Z /draky-entrypoint.sh: running /draky-entrypoint.resources/init.d/00-init.sh
2025-08-27T11:25:54.949362500Z I'm running on startup!

Overriding files inside containers

The draky-entrypoint addon also allows you to replace files inside containers. This is useful, for example, when you want to override some configuration files before your service starts.

Traditionally you could mount a new file in place of the original one, but with multiple files that would pollute your docker-compose.yml configuration and make it ugly. The draky-entrypoint provides a cleaner way to do this.

Assuming we already have the resources directory mounted (from the previous section), like this:

- "./resources:/draky-entrypoint.resources:cached,ro"

Create the override subdirectory inside it.

This is a special subdirectory. Everything that you put inside will be recursively copied into the container's directory tree on startup.

For example, let's assume that we would like to override the my.cnf file.

It's located at the /etc/mysql/my.cnf inside the container.

To override it, we would need to create the .draky/services/mariadb/resources/override/etc/mysql/my.cnf file. The override would be applied before MariaDB starts.

However, it's better practice to add our own configuration file to the /etc/mysql/mariadb.conf.d/ directory, so let's do that.

# .draky/services/mariadb/resources/override/etc/mysql/mariadb.conf.d/99-customization.cnf

[mysqld]
max_allowed_packet = 1M

Now, let's recreate our mariadb command from the Basics tutorial.

# .draky/services/mariadb/commands/mariadb.database.dk.sh

#!/usr/bin/env sh
mariadb -u root "$@" < /dev/stdin

Then restart the environment, so our override will be applied:

draky env down;draky env up

And check the current value of the max_allowed_packet variable:

$ draky mariadb -e "SHOW VARIABLES LIKE 'max_allowed_packet';"
+--------------------+---------+
| Variable_name | Value |
+--------------------+---------+
| max_allowed_packet | 1048576 |
+--------------------+---------+

We can see that the value has been successfully set.

This is an easy way to override any files inside the container, without a need to produce custom images or multiplying volumes.

Using variables in overridding files

But there is more. We can use variables in the files we use for overriding to make them even more flexible!

Not all variables are available by default, though. Variables available in overridding files are those passed to the container through the environment property, with the DRAKY_OVERRIDE_ prefix. You can still use variables from a draky's configuration file, but to do that you need to explicitly define the DRAKY_OVERRIDE_* variables in the service definition and map variables from a configuration file to them.

Let's make the max_allowed_packet value based on a variable.

# .draky/services/mariadb/resources/override/etc/mysql/mariadb.conf.d/99-customization.cnf

[mysqld]
max_allowed_packet = ${DRAKY_OVERRIDE_MAX_ALLOWED_PACKET}
# .draky/services/mariadb/services.dk.yml

services:
mariadb:
image: "${MARIADB_IMAGE}"
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: "${MARIADB_ALLOW_EMPTY_ROOT_PASSWORD}"
MARIADB_DATABASE: "${MARIADB_DATABASE}"
DRAKY_OVERRIDE_MAX_ALLOWED_PACKET: "${MARIADB_MAX_ALLOWED_PACKET}" # <-- added
ports:
- "${MARIADB_EXPOSED_PORT}:3306"
volumes:
- "./resources:/draky-entrypoint.resources:cached,ro"
draky:
addons:
- draky-entrypoint
# .draky/services/mariadb/variables.dk.yml

variables:
MARIADB_VERSION: 12
MARIADB_IMAGE: "mariadb:${MARIADB_VERSION}"
MARIADB_DATABASE: main
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_EXPOSED_PORT: 3306
MARIADB_MAX_ALLOWED_PACKET: 2M # <-- added

Now let's restart our environment:

draky env down;draky env up

And see the result:

$ draky mariadb -e "SHOW VARIABLES LIKE 'max_allowed_packet';"
+--------------------+---------+
| Variable_name | Value |
+--------------------+---------+
| max_allowed_packet | 2097152 |
+--------------------+---------+

Creating the host user in the container

You can also create the host user inside the container, which can be useful if you want to run some processes or commands as the host user.

It is as simple as adding the DRAKY_ENTRYPOINT_DO_CREATE_HOST_USER: 1 variable to the environment section of the service definition.

Conclusion

draky-entrypoint is a powerful addon that will make your life easier when working with existing images. All up-to-date documentation is kept here.