DEV Community

Peter Saktor
Peter Saktor

Posted on

Modern PHP on Windows 11: VS Code, Podman, and MariaDB

Developing PHP applications on Windows used to be painful, often relying on legacy tools like XAMPP. Today, we have a clean, modern, and high-performance solution using Podman (a daemonless container engine compatible with Docker), WSL2 (Windows Subsystem for Linux), and VS Code.

This article will guide you through setting up a powerful development environment that runs PHP 8.4 in a container while connecting seamlessly to your host Windows MariaDB instance for persistence.

1. Prerequisites: Tools You Need

Before we start coding, ensure you have the necessary components installed:

  1. Windows Subsystem for Linux (WSL2): Required to run a Linux distribution (e.g., Ubuntu) efficiently.
  2. Podman: Installed inside your WSL distribution. This is your container engine.
  3. Podman Compose: The equivalent of docker-compose, installed inside WSL (e.g., via sudo apt install podman-compose).
  4. VS Code: Your main editor on the Windows host.
  5. MariaDB/MySQL: Installed and running directly on your Windows 11 host.
  6. VS Code Extensions:
    • PHP Intelephense (For code completion)
    • Docker (Useful for managing containers, even Podman, once configured)

Replacing Docker with Podman on Windows

2. Project Structure and Configuration

We'll start by defining the project structure and the two core container files: Dockerfile and docker-compose.yml.

my-php-app/
├── src/
│   └── index.php           # Our main application file
├── Dockerfile              # Defines the PHP container image (PHP 8.4)
├── docker-compose.yml      # Defines how to run the container (Podman Compose)
└── xdebug.ini              # Configuration for PHP debugging
Enter fullscreen mode Exit fullscreen mode

2.1. Defining the PHP 8.4 Container (Dockerfile)

This file installs PHP 8.4 with the PDO MySQL extension (required to connect to MariaDB) and sets up Xdebug for debugging in VS Code.

# Use the official PHP image with Apache (httpd)
FROM php:8.4-apache

# Set the working directory in the container
WORKDIR /var/www/html

# Install Xdebug
RUN pecl install xdebug \
    && docker-php-ext-enable xdebug

# Copy Xdebug configuration
COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

# Copy application files to the working directory in the container
COPY src/ /var/www/html/

# If you need PDO (for databases)
# RUN docker-php-ext-install pdo pdo_mysql
Enter fullscreen mode Exit fullscreen mode

2.3. Discover the Windows Host IP from WSL (CRITICAL STEP)

The Windows Host IP, as seen from the WSL/Podman network, can change after a reboot. You must determine this address and use it for the database connection and Xdebug.

  1. Open your WSL terminal (e.g., Ubuntu).

  2. Run the following command to find the Windows host's IP address (it's typically the default gateway of the WSL network):

    ip route | grep default | awk '{print $3}'
    
  3. Note the returned IP address (e.g., 172.20.96.1 or 192.168.x.x). You will use this exact IP in the next step. If you reboot Windows, you may need to run this command again.

2.2. Setting up Xdebug (xdebug.ini)

To enable debugging, Xdebug needs to know how to connect back to your VS Code (on the Windows host).

; Enable Xdebug extension
zend_extension=xdebug

; xdebug.ini
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_host = 172.20.96.1
xdebug.client_port = 9003
xdebug.idekey = VSCODE
xdebug.log = /tmp/xdebug.log
xdebug.log_level = 7
Enter fullscreen mode Exit fullscreen mode

3. Connecting to Windows MariaDB and VS Code (The Networking Challenge)

Since Podman runs in WSL2, your container needs a special IP address to reach the Windows host machine for both the database connection and the Xdebug connection.

A. Configure MariaDB for Remote Access (Windows)

  1. Locate your MariaDB configuration file (my.ini or my.cnf) on Windows.
  2. Change the binding address to allow external connections:

    bind-address = 0.0.0.0
    
  3. Restart the MariaDB service on Windows and ensure your Windows Firewall allows incoming TCP connections on port 3306.

B. Defining Services and Networking (docker-compose.yml)

Use the IP address found in Step B for your database connection (DB_HOST).

version: '3.8'

services:
  app:
    build: .
    ports:
      - "8080:80"  # Maps port 8080 on your computer to port 80 in the container
    volumes:
      # Mount the 'src' directory from your PC to the Apache directory
      - ./src:/var/www/html/
    environment:
      # Set the Xdebug client host dynamically
      - XDEBUG_CONFIG=client_host=172.20.96.1 client_port=9003
    extra_hosts:
      - "host.docker.internal:host-gateway"
Enter fullscreen mode Exit fullscreen mode

4. Launching the Environment

Navigate to your project root in the WSL terminal and execute the Podman Compose commands. Since you modified the Dockerfile, you must use the --build flag.

  1. Build and Run:

    podman-compose down  # Stop and remove old containers
    podman-compose up --build -d # Build new image and start services
    
  2. Verify PHP Version: Open your browser and go to http://localhost:8080. Your index.php should now confirm PHP 8.4 is running and successfully connecting to MariaDB on your Windows host.

5. Seamless VS Code Development

Thanks to the volume mounting (./src:/var/www/html/), the code editing is simple: you edit files in VS Code on Windows, and the changes appear instantly in the running container.

Debugging with VS Code

The key for debugging is that the xdebug.ini file uses the same IP address (172.20.96.1 in our example) to send the debug signal back to your Windows machine.

  1. In VS Code, go to the Run and Debug tab.
  2. Set a breakpoint in your PHP code.
  3. Click the green play button for the "Listen for Xdebug" configuration (port 9003).
  4. Load your application in the browser. VS Code should automatically halt execution at the breakpoint.

There is a potential issue. The Windows Firewall might be blocking inbound connections to VS Code, preventing XDebug from connecting.

<?php
// Your PHP code
echo "<h1>Hello, world! Running in Podman container with PHP " . phpversion() . "</h1>";

// Debugging test
$message = "Debug test: Xdebug should stop here";
echo "<p>" . $message . "</p>";

// Show some variables for debugging
$numbers = [1, 2, 3, 4, 5];
foreach ($numbers as $number) {
    echo "<p>Number: " . $number . "</p>";
}

// Show Xdebug info
if (extension_loaded('xdebug')) {
    echo "<p style='color: green;'>✅ Xdebug is loaded!</p>";
    echo "<p>Xdebug version: " . phpversion('xdebug') . "</p>";
} else {
    echo "<p style='color: red;'>❌ Xdebug is NOT loaded!</p>";
}
?>
Enter fullscreen mode Exit fullscreen mode

By mastering the networking between the Windows host and the WSL/Podman container, you have created a robust, high-performance, and entirely containerized PHP development environment on Windows 11.

Top comments (5)

Collapse
 
arhimede profile image
arhimede

Why ??
Why Podman inside WSL2 inside Windows ?

WSL2 only container inside Win is not enough ?

Collapse
 
petersaktor profile image
Peter Saktor

WSL2 provides the operating system that the container engine (like Podman or Docker) needs to work. Podman Desktop for Windows creates a WSL2 virtual machine where Podman is running. You can find more here podman-desktop.io/docs/installatio...

Collapse
 
xwero profile image
david duymelinck • Edited

The idea behind container engines, and virtual machines (which I think is closer to what WSL is), is that it allows you to run the code like it is running on a server. For most programming languages this means running a linux/unix distribution.
Which means a WSL distribution is good enough separation from Windows to use it as a development environment. I use Debian instead of Ubuntu because that is what I encounter on servers the most.

The main reason people opt for a container engine is that it allows to add the config to the project. When you are in the situation that you have to handle several different server setups, this is a good thing.
If you are running code on a single server setup, WSL setup documentation is enough to get new people up and running fast.

So like everything in IT, it depends on the situation you are in to use a certain solution. Don't use something because other people use it.

The biggest problem I have with Docker is that is slow on Windows even if large directories are excluded or using a solution like Mutagen. I don't know if Podman solves that problem?

Thread Thread
 
petersaktor profile image
Peter Saktor

I can't tell if Podman on Windows is significantly faster than Docker. However, Docker Desktop requires a paid subscription for commercial use, which is why I switched to Podman Desktop, an open-source alternative.

Thread Thread
 
xwero profile image
david duymelinck

Sure that is a something to consider, but @arhimede question was not about Podman.

That is why I provided more background to using Docker/Podman when there is already a Linux container system in Windows.