Skip to main content

PHP

Dagger can be used to perform common CI tasks - testing, containerizing, publishing and more - for any PHP application, by encapsulating these CI tasks as Dagger Functions in a Dagger module.

How it works

To Daggerize a PHP project using a Dagger module, you must:

  • Create a new Dagger module in your PHP project
  • Implement your CI pipeline as one or more Dagger Function(s)
  • Test your Dagger Function(s) locally and then transfer them to your CI environment

Prerequisites

None

Example

The following example demonstrates how CI tasks can be encapsulated as Dagger Functions in a Dagger module. It assumes:

  • A PHP 8.2.x Web application with Composer for package management and PHPUnit for application testing. This example uses the Slim Framework skeleton application.
  • Credentials to publish the containerized application image to a registry like Docker Hub.

Clone the application repository:

git clone https://github.com/slimphp/Slim-Skeleton.git
cd Slim-Skeleton

Bootstrap a new module:

dagger init --name=my-module --sdk=go --source=./dagger

Update the generated dagger/main.go file with the following code:

package main

import (
"context"
"fmt"

"dagger/my-module/internal/dagger"
)

type MyModule struct{}

// return container image with application source code and dependencies
func (m *MyModule) Build(source *dagger.Directory) *dagger.Container {
return dag.Container().
From("php:8.2").
WithExec([]string{"apt-get", "update"}).
WithExec([]string{"apt-get", "install", "--yes", "git-core", "zip", "curl"}).
WithExec([]string{"sh", "-c", "curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer"}).
WithDirectory("/var/www", source.WithoutDirectory("dagger")).
WithWorkdir("/var/www").
WithExec([]string{"chmod", "-R", "775", "/var/www"}).
WithEnvVariable("PATH", "./vendor/bin:$PATH", dagger.ContainerWithEnvVariableOpts{
Expand: true,
}).
WithExec([]string{"composer", "install"})
}

// return result of unit tests
func (m *MyModule) Test(ctx context.Context, source *dagger.Directory) (string, error) {
return m.Build(source).
WithExec([]string{"phpunit"}).
Stdout(ctx)
}

// return address of published container image
func (m *MyModule) Publish(ctx context.Context, source *dagger.Directory, version string, registryAddress string, registryUsername string, registryPassword *dagger.Secret, imageName string) (string, error) {
return m.Build(source).
WithLabel("org.opencontainers.image.title", "PHP with Dagger").
WithLabel("org.opencontainers.image.version", version).
WithEntrypoint([]string{"php", "-S", "0.0.0.0:8080", "-t", "public"}).
WithExposedPort(8080).
WithRegistryAuth(registryAddress, registryUsername, registryPassword).
Publish(ctx, fmt.Sprintf("%s/%s/%s", registryAddress, registryUsername, imageName))
}

Here is an example of calling the Dagger Function to run the application's unit tests:

dagger call test --source=.

Here is an example of calling the Dagger Function to publish the application image to Docker Hub. Replace the DOCKER-HUB-USERNAME and DOCKER-HUB-PASSWORD placeholders with your Docker Hub credentials.

export REGISTRY_PASSWORD=DOCKER-HUB-PASSWORD
dagger call publish \
--source=. \
--version=0.1 \
--registry-address=docker.io \
--registry-username=DOCKER-HUB-USERNAME \
--registry-password=env:REGISTRY_PASSWORD \
--image-name=my-php-app
note

If you prefer to write your Dagger module in PHP instead of the above languages, an experimental PHP SDK is also available for PHP developers. This SDK is currently under development and therefore not yet documented. Interested early adopters can learn more by reviewing the source code or visiting our PHP channel.

Resources

If you have any questions about additional ways to use PHP with Dagger, join our Discord and ask your questions in our PHP channel.

About PHP

PHP is an interpreted, server-side scripting language.