in PhpStorm Correctly
Anyone who runs PHP inside a Docker container also wants PhpStorm to work with that same PHP version, for autocompletion, navigation, tests and debugging. The Docker interpreter in PhpStorm connects the IDE and the container without requiring PHP to be installed locally. This article shows how to configure it correctly.
Table of Contents
- 1. Why a Docker interpreter instead of a local PHP installation
- 2. Setting up the Docker connection in PhpStorm
- 3. Configuring a PHP interpreter from a Docker container
- 4. Using Composer via the Docker interpreter
- 5. Running PHPUnit tests inside the Docker container
- 6. Configuring XDebug with the Docker interpreter
- 7. Understanding and setting path mappings correctly
- 8. Common errors and their solutions
- 9. Summary
- 10. FAQ
1. Why a Docker interpreter instead of a local PHP installation
The classic approach, installing PHP locally and configuring it as a PhpStorm interpreter, works, but it has structural downsides: the local PHP version quickly drifts from the production PHP version. Local PHP extensions don't match the container's extensions. Developers on different operating systems end up with different PHP versions. And if three projects need three different PHP versions, local version management quickly becomes complex.
The Docker interpreter in PhpStorm solves these problems: PhpStorm communicates with the PHP process inside the Docker container as if it were a local interpreter. Autocompletion, type inference and navigation features use the PHP version and extensions from the container, identical to the production environment. Tests run inside the container, XDebug debugs the container's PHP process, and Composer installs packages using the container's PHP version.
For Magento projects on the Mark Shust stack this is the right choice: PHP 8.4 runs inside the container, and PhpStorm should use exactly that version for all IDE features. Without a Docker interpreter, PhpStorm might use a local PHP 8.2 or an entirely different version, which would cause autocompletion to suggest incorrect types and inspections to raise incorrect warnings.
2. Setting up the Docker connection in PhpStorm
Before a Docker interpreter can be configured, PhpStorm needs a connection to the Docker daemon. This connection is configured under "Settings > Build, Execution, Deployment > Docker". PhpStorm supports three connection types: Unix socket (for macOS and Linux), TCP socket, and Docker for Windows. On macOS and Linux, PhpStorm automatically detects the Unix socket /var/run/docker.sock.
After adding the Docker connection, a green checkmark appears once the connection succeeds, and PhpStorm lists the available containers and images in the "Services" panel (View > Tool Windows > Services). From there, containers can be started, stopped, and their logs inspected, directly from the IDE, without opening a terminal.
An important note for the Mark Shust stack: the stack uses Docker Compose with multiple services. PhpStorm must know the correct docker-compose.yml and use the correct service (phpfpm) as the basis for the interpreter. Multiple compose files (e.g. compose.yaml + compose.dev.yaml) can be given to PhpStorm as an override file, exactly like docker compose -f compose.yaml -f compose.dev.yaml on the command line.
# Verifying Docker connection for PhpStorm interpreter setup
# Run from project root to confirm service is accessible:
# Check running services
docker compose ps
# Expected output for Mark Shust stack:
# NAME IMAGE COMMAND SERVICE PORTS
# nginx nginx:1.25 ... nginx 0.0.0.0:80->80/tcp
# phpfpm php:8.4-fpm ... phpfpm 9000/tcp
# db mariadb:11.x ... db 3306/tcp
# Verify PHP version in container (must match PhpStorm interpreter target)
docker compose exec phpfpm php -v
# PHP 8.4.x (cli) (built: ...)
# with XDebug 3.x
# Check available extensions
docker compose exec phpfpm php -m
# Should show: bcmath, gd, intl, mbstring, pdo_mysql, soap, xsl, zip, Xdebug
3. Configuring a PHP interpreter from a Docker container
The actual interpreter configuration happens under "Settings > PHP > CLI Interpreter > + (Add) > From Docker, Vagrant, VM, WSL, Remote". In the dialog, choose "Docker Compose", select the compose file (or several) and the service (phpfpm). PhpStorm then runs a docker compose run in the background, reads the PHP version and available extensions, and shows them in the configuration dialog.
Once configured, the Docker interpreter appears in the interpreter list along with the container image and PHP version. This interpreter can then be set as the default PHP CLI interpreter, at which point it applies to all PHP operations in PhpStorm: running scratches, calling external tools, Composer commands, and more.
Under "Settings > PHP" the Docker interpreter can also be set as the interpreter for the PHP language level, which is the setting that determines which PHP features and functions PhpStorm treats as available. If PHP 8.4 runs inside the container, this should be set to "PHP 8.4" so PhpStorm correctly analyzes PHP 8.4 features such as property hooks and doesn't show incorrect "unsupported syntax" warnings.
<?php
// PhpStorm Docker Interpreter: what PhpStorm can now do:
// 1. Type inference with container's PHP 8.4 and extensions
declare(strict_types=1);
class ProductRepository
{
public function __construct(
private readonly \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
private readonly \Psr\Log\LoggerInterface $logger,
) {}
// PhpStorm: knows \Magento\... classes from vendor/ in container
// Ctrl+Click navigates to actual vendor files mounted in container
public function findBySkus(string ...$skus): array
{
$collection = $this->collectionFactory->create();
$collection->addAttributeToFilter('sku', ['in' => $skus]);
// PhpStorm: autocomplete shows actual Magento Collection methods
// because Docker interpreter reads vendor from container
return $collection->getItems();
}
}
// 2. PHP 8.4 features recognized (PHP version from container)
// Property hooks, asymmetric visibility, etc. (no false warnings)
4. Using Composer via the Docker interpreter
With a configured Docker interpreter set as the default CLI interpreter, PhpStorm also runs Composer through the container. Under "Settings > PHP > Composer", select the Docker interpreter as the interpreter. If Composer lives in the container at /usr/local/bin/composer (the default for official PHP images and the Mark Shust stack), PhpStorm finds it automatically.
Composer operations from the "Tools > Composer" menu (adding/removing packages, composer update, validation) are then executed via docker compose exec phpfpm composer .... This is exactly the same as the manual bin/composer wrapper in the Mark Shust stack. PhpStorm shows the output in the Run panel and automatically refreshes its indexing afterward, so newly installed packages are instantly navigable.
A practical tip: PhpStorm can be configured to check on every project open whether composer.json and vendor/ are in sync. This happens via "Settings > PHP > Composer > Synchronize IDE settings with composer.json: On". If the project is opened after a git pull and someone has added new packages, PhpStorm automatically reminds you to run composer install.
5. Running PHPUnit tests inside the Docker container
Running PHPUnit tests inside Docker requires a run configuration that uses the Docker interpreter. Under "Run > Edit Configurations > Add > PHPUnit", select the Docker interpreter in the "Interpreter" field. PhpStorm automatically adds the necessary volume mounts (to make the local project folder accessible inside the container) and runs PHPUnit using the container's PHP version.
In the "PHPUnit" configuration form there are two options for the configuration file: "Use configuration file" (points at phpunit.xml in the project) or "Use alternative configuration" for specific scenarios. The working directory must point to the project root, PhpStorm maps this automatically into the container. Test results appear in the Test Runner panel with red/green status indicators, stack traces, and direct navigation to the failing code.
For Magento-specific tests (integration tests that require a database), the database connection must be available inside the container. That means: the db service must be running, and the test configuration (dev/tests/integration/etc/install-config-mysql.php) must use the container's internal service names (e.g. db as the hostname, not localhost). PhpStorm runs the tests inside the container network, where these service names are resolvable.
<?php
// phpunit.xml, configured for Docker interpreter execution
// PhpStorm Run Configuration picks this up automatically
// src/dev/tests/unit/phpunit.xml
/*
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.0/phpunit.xsd"
bootstrap="../../../app/bootstrap.php"
colors="true"
stderr="true">
<testsuites>
<testsuite name="Mironsoft Unit Tests">
<directory>../../../app/code/Mironsoft</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">../../../app/code/Mironsoft</directory>
</include>
</coverage>
</phpunit>
*/
// Example unit test, runs in Docker container via PhpStorm
namespace Mironsoft\Catalog\Test\Unit\Model;
use Mironsoft\Catalog\Model\PriceCalculator;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
class PriceCalculatorTest extends TestCase
{
private PriceCalculator $calculator;
protected function setUp(): void
{
$this->calculator = new PriceCalculator();
}
#[DataProvider('priceDataProvider')]
public function testRoundingIsConsistent(float $input, float $expected): void
{
self::assertSame($expected, $this->calculator->round($input));
}
public static function priceDataProvider(): array
{
return [
'standard rounding' => [10.555, 10.56],
'no rounding needed' => [10.50, 10.50],
'zero price' => [0.0, 0.0],
];
}
}
6. Configuring XDebug with the Docker interpreter
Using XDebug with the Docker interpreter in PhpStorm requires correct configuration on both sides: XDebug must be installed and configured inside the container, and the debug port and server configuration must be set correctly in PhpStorm. The most common mistake is a faulty path mapping, PhpStorm can't match the breakpoint to the correct file inside the container.
XDebug configuration inside the container (in conf.d/xdebug.ini or php.ini): zend_extension=xdebug, xdebug.mode=debug, xdebug.client_host=host.docker.internal (on Linux: the gateway IP or host-gateway from extra_hosts), xdebug.client_port=9003, xdebug.start_with_request=yes (or trigger for selective debugging).
In PhpStorm: "Settings > PHP > Debug > Xdebug: Debug port: 9003". Under "Settings > PHP > Servers" create a server with the name set in PHP_IDE_CONFIG=serverName=.... Path mapping: local workspace path -> container path (/var/www/html). Then enable "Run > Start Listening for PHP Debug Connections", PhpStorm waits for XDebug connections. On the next page load (with an XDebug trigger or start_with_request=yes), PhpStorm pauses at the first breakpoint.
7. Understanding and setting path mappings correctly
Path mappings are the bridge between the host's filesystem (where PhpStorm works) and the container's filesystem (where PHP runs). Without correct path mappings, PhpStorm can't match XDebug breakpoints to the right files, and test error messages point to container paths that don't exist locally.
In the Mark Shust stack, the mapping is typically: local path /home/mir/development/mironsoft/src maps to container path /var/www/html. This setting is configured in "Settings > PHP > Servers" on the relevant server entry. The server name must exactly match the PHP_IDE_CONFIG value inside the container.
A common mistake: the local path points to the repository root, while the container path points to a subdirectory (or vice versa). If Magento's src/ directory is mounted inside the container at /var/www/html, the path mapping must be src/ -> /var/www/html, not . -> /var/www/html. PhpStorm shows in the debug console when a mapping is missing and interactively suggests one, which can be used as a starting point for the manual fix.
8. Common errors and their solutions
| Symptom | Cause | Solution |
|---|---|---|
| "Cannot connect to Docker" | Docker daemon unreachable or wrong socket | Settings > Docker: check Unix socket /var/run/docker.sock |
| Autocompletion shows wrong PHP level | Wrong interpreter or language level | Settings > PHP: set interpreter and language level to 8.4 |
| XDebug doesn't connect | client_host or port wrong, firewall blocking | Enable xdebug.log, check host.docker.internal |
| Breakpoint is ignored | Path mapping missing or wrong | Settings > PHP > Servers: path mapping host -> container |
| PHPUnit can't find Composer | Composer path inside container not configured | Settings > PHP > Test Frameworks: specify autoloader path |
Mironsoft
Docker setups, Magento 2 and PhpStorm configuration
Need a Docker interpreter set up for your PHP team?
We set up Docker interpreters in PhpStorm for Magento and PHP projects, including Composer, PHPUnit, XDebug and correct path mappings for your Docker stack.
Interpreter setup
Configure the Docker interpreter correctly, for PHP, Composer and all quality tools
XDebug configuration
Set up XDebug inside the container with correct path mappings and host connection
PHPUnit integration
Test runner inside the Docker container for Magento unit and integration tests
9. Summary
The Docker interpreter in PhpStorm connects the IDE to the PHP process inside the container, without a local PHP installation and without version inconsistencies. The setup happens in four steps: establish the Docker connection under "Settings > Build, Execution, Deployment > Docker", derive the PHP interpreter under "Settings > PHP > CLI Interpreter" from the Docker Compose service, configure Composer to use the same interpreter, and set the XDebug port and path mappings under "Settings > PHP > Debug" and "PHP > Servers".
Path mappings are the critical point in every Docker-based interpreter configuration: PhpStorm needs to know which local directory path corresponds to which container path. Without correct mappings, XDebug breakpoints simply don't work. With correct mappings, the Docker interpreter is functionally identical to a local interpreter, with the decisive advantage that it uses the exact PHP version and extensions of the production container.
Docker Interpreter in PhpStorm: The Essentials at a Glance
Docker connection
Settings > Build, Execution, Deployment > Docker: Unix socket /var/run/docker.sock. PhpStorm detects it automatically on macOS/Linux.
Interpreter configuration
Settings > PHP > CLI Interpreter > Add > Docker Compose: service phpfpm, PHP path detected automatically. Set the language level to the PHP version inside the container.
XDebug setup
client_host=host.docker.internal (Linux: extra_hosts), port 9003. Settings > PHP > Servers: server name = PHP_IDE_CONFIG serverName. Path mapping host -> container.
PHPUnit inside the container
Run Configuration > PHPUnit: select the Docker interpreter. PhpStorm adds volume mounts automatically. Test results are navigable in the Test Runner panel.