Using Peachpie with Docker to Run PHP on .NET Core

It has been a while since our last article, as we have been working on integrating the ASP.NET Core pipeline into Peachpie compiler. This opens up a whole host of new possibilities, which we would like to demonstrate in this blog post.

Putting the pieces together

Up until now, we always had to focus on individual platforms or constructs and we were forced to demonstrate the usage of Peachpie compiler on the command line. With the latest advances in the development of the project, we can now put the pieces of the puzzle together and use multiple major technologies to show the benefits of Peachpie for everyone to try easily: Docker, .NET Core, ASP.NET Core, VS Code and Peachpie compiler, which is built on top of the Roslyn compiler platform.

In this article, our objective is to show:

  1. How dotnet automatically compiles PHP code into a .NET Core library
  2. That dotnet re-compiles your code when you change it
  3. How to use a Docker image with Peachpie
  4. That Peachpie compiler is now fully compatible with .NET Core

What is ASP.NET Core?

Believe it or not, it has been 14 years since Microsoft introduced ASP.NET 1.0 for developers to run web applications. On June 27, 2016, after significant beta testing, the .NET tooling team has finally officially published ASP.NET Core 1.0. So what is the difference?

Essentially, it is a trimmed down, lean and modular version of ASP.NET, with the key advantage of being optimized for cloud and cross-platform. ASP.NET Core is open-source and designed to build modern applications to run on Windows, Linux and Macs, as well as any device. Given that the framework no longer requires System.Web.dll and a majority of features are implemented as NuGet packages, Microsoft successfully managed to create a lean and modular platform to optimize apps to the highest degree. Some of the main benefits of ASP.NET Core are:

  • Building and running cross-platform apps on Windows, Mac and Linux
  • Simple and quick web development
  • Cloud-optimized and environment-based configuration
  • Ability to host on IIS or in your own process
  • Built on .NET Core, therefore side-by-side app versioning is supported

Source: Jeffrey T. Fritz,

Docker – a virtualization revolution

We are all familiar with VMWare, but Docker is a relatively new entrant to the market with the potential to disrupt it entirely. With Docker, you can wrap a piece of software into a so-called container, which is a complete filesystem that contains everything from the code itself, the runtime, system tools, to the system libraries. The key difference between containers and virtual machines is that their unique architectural approach allows containers to be much more efficient and portable. They include the application and all of its dependencies, but share the kernel with other containers, running as isolated processes on the host operating system.

Docker containers are independent of particular infrastructures, which means they run on any computer, infrastructure and on any cloud. Virtual machines, on the other hand, require a hypervisor on top of the host operating system, where the apps and the required binaries and libraries are run on top of guest operating systems. This additional architectural layer requires a rather significant amount of memory usage.


Docker is incredibly easy to set up, as you will be able to see in our demonstration.


  1. Temporary Peachpie SDK via a Docker image.
  2. Extending project.json with the ability to compile PHP.
  3. Showing a sample application including the .NET Core Kestrel Web Server, .php request delegate and automatic re-compilation when the source file changes.
  4. Utilizing the Docker image with ASP.NET Core and a PHP website compiled to .NET Core.

DisclaimerPeachpie compiler is still a work in progress and therefore not fully compatible with all PHP constructs. The Docker image presented in this article is for demonstration and experimentation purposes only. Please refer to our Roadmap for an up-to-date list of implemented features.

Video Tutorial

For a quick video tutorial, please click the image below:

Peachpie SDK

For now, we prepared a Docker image with the latest build of Peachpie compiler and runtime (iolevel/dotnet-compile-php). The image contains binaries of Peachpie compiler and runtime, making them available to users.

In the future, Peachpie compiler and the related tools will be available as NuGet packages.


Currently, the project.json file is a definition taken by the ‘dotnet’ utility, describing what dependencies and sources have to be compiled and executed.

project.json for PHP dotnet project

In order to infiltrate the dotnet build with PHP, you have to add a ”compilerName” option with the “PHP” parameter, as shown in the screenshot above (see for further reference).

Once we define “compilerName” in project.json, dotnet looks up the command on your system called “dotnet-compile-{compilerName}”, i.e. ”dotnet-compile-php” in our case. Our ‘iolevel/dotnet-compile-php’ Docker image comes with this command, making a call to Peachpie compiler itself.


‘Dotnet’ provides all the necessary arguments to our compiler, like the output path or references. This includes NuGet packages and other project references – stay tuned for future posts on this incredibly useful functionality. The command above restores NuGet packages, builds dependencies and produces the `website.dll` file with compiled PHP scripts.

Compiling a website

By extending the ‘dotnet’ build with the ‘PHP’ language as described above, the .php files are compiled into a DLL file, which is portable and thus fully .NET Core compatible. Note how project.json automatically compiles all the PHP code into .NET without any additional action required.

The resulting DLL file contains .NET representations of PHP classes and functions. In addition, each source PHP script is compiled into a .NET class named <Root>.{FILENAME} containing the `Main` method representing the script’s global code (see Peachpie Architecture WiKi). This is used by the Peachpie runtime to determine the contained scripts so they can be invoked as requested.

Sample application

For this demonstration, we have prepared an ordinary ASP.NET Core console project running the Kestrel Web Server (an opensource web server built in .NET Core).

A part of the solution is a website project containing PHP files and project.json as described above.

ASP.NET Core RequestDelegate that invokes a compiled PHP script from referenced website.dll.

The configuration of the sample web server adds a RequestDelegate ( that handles requests to .php files by invoking scripts in the compiled website. See our GitHub repo for implementation details.

Sample web server project.json with Kestrel and Watcher

The `project.json` above shows the dependency to the Kestrel web server and our `website` project.

Additionally, we make use of Microsoft.DotNet.Watcher.Tools (, which seamlessly adds the ability to re-compile and re-run our application when the source files have changed. This, in a way, simulates the behavior of PHP, where you can change source files while the server is running.

Running the Docker image with the sample application

We prepared a Docker image with the sample app (iolevel/peachpie-aspnetcore). This is just for demonstration purposes and you can change the app as needed or build your own app on top of it. The sample app watches for file changes, and thus any alternations of the PHP files cause `dotnet` to build and restart the web server.

If you do not already have Docker installed, please visit and try the following:

docker run -p 5004:5004 iolevel/peachpie-aspnetcore


The code above downloads the Docker image (if not yet installed) and instantiates the Docker container running our sample application. The parameter -p specifies that we are exposing port 5004 to the host system so you can invoke the compiled PHP script in your browser by entering http://localhost:5004/index.php.

Compiled PHP

Running the compiled script in the browser

The screenshot above shows our sample PHP website compiled to .NET. Feel free to try this out yourself and to build your app on top of our sample. However, please beware that Peachpie currently does not support all constructs just yet.

Make sure you follow the progress of this project on Facebook and Twitter and join the community chat on Gitter.

Posted on August 30, 2016, in category Announcement, Information, News, Tutorial, tags: , , , , , ,