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 (1)

Collapse
 
arhimede profile image
arhimede

Why ??
Why Podman inside WSL2 inside Windows ?

WSL2 only container inside Win is not enough ?