Pictures from the network, if violated your rights, please contact me.
preface
Xdebug should be familiar to many people, debugging and installation is a bit cumbersome, but it is very easy to use.
Docker and Swoole are also popular in recent years, but they are not easy to debug. Many people’s first reaction to the headline is “Isn’t Swoole not compatible with Xdebug?” Yes, Swoole’s official documentation clearly states that Swoole is not compatible with Xdebug.
However, the strong community gave us the answer: SDEBUG
Sdebug is a tool forked from Xdebug 2.7 that can be used for breakpoints and debugging in Swoole environments.
Runtime environment
software | version |
---|---|
Windows 10 Professional | 1909 |
PHPStorm | 2020.1 |
Docker Desktop | 2.2.0.5 (43884). |
Docker | 19.03.8 |
Hyper-V | latest |
Hyperf (PHP Framework) | 1.1.25 (hyperf – skeleton create) |
Sdebug | 2.7 |
PHP | 7.3.12 |
Start the installation
Docker && Docker Desktop
Docker can be downloaded from the official website for Windows, but note the following restrictions.
- 64-bit operating system
- More than 4G RAM
- Enable virtualization in the BIOS
- Windows Professional and above
- Open the Hyper – V
I’m not going to go into the introduction here because there are too many articles like this, so make sure Docker is installed.
When the installation is complete, a little static Docker icon will appear on your desktop taskbar. Notice, I want to emphasize that static static means Docker is running, dynamic means Docker is in a medium not running state. Then right click, select Settings, we need to open two options.
- 1. Enable the TCP connection
- 2. Set up the domestic Docker Hub image
{
"registry-mirrors": [
"http://hub-mirror.c.163.com"]."insecure-registries": []."debug": true."experimental": false
}
Copy the code
Now, select Apply & Restart in the lower right corner and wait for the Docker to Restart. If the Docker does not Restart, you can manually click Restart in the Docker icon in the taskbar. After the Restart is complete, execute the command to check.
$docker info Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Registry Mirrors: http://hub-mirror.c.163.com/ Live Restore Enabled: false Product License: Community EngineCopy the code
You should now be able to see the mirror address of NetEase.
Let’s start
Check the connection
The important factor for debugging is whether the Docker container can communicate with the host. Otherwise, the following is nonsense.
Use PowersShell or Cmder
$cat C: / Windows/System32 / drivers/etc/hosts | findstr searches the host. The docker. Internal 192.168.3.22 host. The docker. InternalCopy the code
After executing, you should see an IP 192.168.x.x output mapped to host.docker.internal. Please remember this IP. Now run the following command, run a Alpine Linux container, and run a ping, but you won’t see the output here.
- Further reading
Networking features in Docker Desktop for Windows | Docker Documentation
$ docker run -di alpine:latest
a8369f4e057e161c2079281e4bfbc31dc509f802e3ce0c2f09708cd8613459ae
Copy the code
We then execute the following command to obtain the container ID, which we already obtained after the previous execution.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a8369f4e057e alpine:latest "/bin/sh" About a minute ago Up About a minute pensive_lehmann
Copy the code
Use Docker Exec to open the command line that can interact with the container.
$ docker exec -it a8369f4e057e sh
Copy the code
Docker exec it
/bin/bash docker exec it
/bin/bash docker exec it
/bin/bash After entering the terminal, we re-execute the ping command.
/ # ping 192.168.3.22 (192.168.3.22): 56 data bytes 64 bytes from 192.168.3.22: Seq =0 TTL =37 time=1.003 ms 64 bytes from 192.168.3.22: seq=1 TTL =37 time=0.937 ms 64 bytes from 192.168.3.22: seq=1 TTL =37 time=0.937 ms 64 bytes from 192.168.3.22: Seq =2 TTL =37 time=1.026 ms 64 bytes from 192.168.3.22: Seq =3 TTL =37 time= 1.341 ms ^C -- 192.168.3.22 Ping statistics -- 3 packets transmitted, 4 packets transmitted, 0% packet loss round-trip min/ AVG/Max = 0.937/1.026/1.141msCopy the code
If a normal ping message can be output, it means that our docker container can communicate with the host. If not, try ping 192.168.56.1. If these two commands can’t ping, I think you don’t need to see 😨, because the basic is to do the Docker container internal communication with the host machine, to use Xdebug, if you just want to build a development environment, then you can continue to see.
Next, I will show you how to build your own Docker PHP development environment using Dockerfile.
Docker
Installing PHP
Most of the time, I use the latest VERSION of PHP for development, unless the project calls for an older version, which is the case here. Because Sdebug is based on Xdebug 2.7, which does not support the latest PHP 7.4, So we had to go to the Docker Hub PHP Library and select a newer PHP tag :7.3.17- CLI-alpine3.11. Create a new php.dockerfile file and install the necessary extensions and Composer.
FROM php:7.3.17-cli-alpine3.11
Now we need to configure something.
# compile parameter, used to specify the Swoole version
ARG swoole_ver
# save to environment variable, if not passed to default value
ENV SWOOLE_VER=${swoole_ver:-"v4.4.15"}
# APk is a package manager for Alpine
# set-ex is to stop the script in case of an error
RUN set -ex \
Do all this in a temporary directory
&& cd /tmp \
# change the default apK source to the Aliyun image
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
Update package list
&& apk update \
# Add so many extensions because we'll need them later to compile Swoole and sdebug
&& apk add vim git autoconf openssl-dev build-base zlib-dev re2c libpng-dev oniguruma-dev
# install composer
RUN cd /tmp \
# Download Composer from Aliyun
&& wget https://mirrors.aliyun.com/composer/composer.phar \
&& chmod u+x composer.phar \
&& mv composer.phar /usr/local/bin/composer \
# Set aliyun image for Composer
&& composer config -g repo.packagist composer https://mirrors.aliyun.com/composer \
Add the composer global command to PATH to make sure we use it later
&& echo 'export PATH="$PATH:$HOME/.composer/vendor/bin"' >> ~/.bashrc
# php ext
RUN php -m \
# docker-php-ext-install # docker-php-ext-install is a PHP directive that allows us to install some default PHP extensions
You can enable the necessary extensions here
&& docker-php-ext-install gd pdo_mysql mysqli sockets pcntl \
Now you can check the extensions that PHP already has installed
&& php -m
Copy the code
So our image is ready to run PHP, but next we need to install Swoole.
Install Swoole
If you have used PECL, you may know that Swoole and PhpRedis can be installed directly with PECL, but PECL installation is slow to download, so we use Swoole’s official warehouse in China.
# install swoole
RUN cd /tmp \
# from mirrors
&& git clone https://gitee.com/swoole/swoole swoole \
&& cd swoole \
# Switch to the specified version of the tag
&& git checkout ${SWOOLE_VER} \
&& phpize \
Run configure
&& ./configure --enable-openssl --enable-sockets --enable-http2 --enable-mysqlnd \
&& make \
&& make install \
# enable the extension via docker-php-ext-enable, which is also provided by PHP.
&& docker-php-ext-enable swoole \
Check PHP modules already installed
&& php -m \
Check whether swoole is installed correctly
&& php --ri swoole
Copy the code
Install Sdebug
Sdebug source code is hosted on Github. As we all know, Github download speed is slow due to some reasons, so we need to use the domestic mirror, but it seems that Sdebug does not have a mirror in China, so we need to do it ourselves, go to the code cloud, register an account, Then select the new project to import from Github so that we can create a mirror of the repository. I have already created a Sdebug, you can create one yourself if you mind, the method is above. The procedure for installing Sdebug is almost exactly the same as Swoole, but there are a few points to note, which I’ll comment in detail in Dockerfile next
# install sdebug
Change the directory to/TMP before running clone
RUN cd /tmp \
# from mirrors
&& git clone https://gitee.com/vyi/sdebug sdebug \
Go to the clone directory
&& cd sdebug \
Switch to the sdebug_2_7 branch, this must be the switch branch, because the master branch is the source of Xdebug
&& git checkout sdebug_2_7 \
&& phpize \
&& ./configure --enable-xdebug \
&& make \
&& make install \
# here is the value xdebug executed after the installation is complete
&& docker-php-ext-enable xdebug \
&& php -m \
Sdebug = sdebug
&& php --ri sdebug
Copy the code
Now that everything is installed, we need to do some simple configuration for Swoole and sdebug, and just like before, Here is using Dockerfile commands/usr/local/etc/PHP/conf. D, this position is the default PHP ini loading directory will scan, we can execute PHP – ini command to check
/mnt/d/htdocs/tom # php --ini
Configuration File (php.ini) Path: /usr/local/etc/php
Loaded Configuration File: (none)
Scan for additional .ini files in: /usr/local/etc/php/conf.d
Additional .ini files parsed: /usr/local/etc/php/conf.d/99-xdebug-enable.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
/usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pcntl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-redis.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sockets.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
/usr/local/etc/php/conf.d/docker-php-ext-swoole.ini,
/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
Copy the code
You can see the following, which means he will scan the configuration file here
Scan for additional .ini files in: /usr/local/etc/php/conf.d
# config php
RUN cd /usr/local/etc/php/conf.d \
# swoole config
# Turn off swoole short name, use Hyperf this is required
&& echo "swoole.use_shortname = off" >> 99-off-swoole-shortname.ini \
# config xdebug&& {\# Add an Xdebug node
echo "[Xdebug]"; \
# Enable remote connection
echo "xdebug.remote_enable = 1"; \
# This is a multi-user debugging, but now some difficulties, temporarily do not start
echo "; xdebug.remote_connect_back = On"; \
Start remote debugging automatically
echo "xdebug.remote_autostart = true"; \
Host. Docker. Internal.
echo "xdebug.remote_host = host.docker.internal"; \
The port is fixed to 19000. Of course, other ports can be filled in to ensure that they are not occupied
echo "xdebug.remote_port = 19000"; \
# Here is fixed
echo "xdebug.idekey=PHPSTORM"; \
Save the result to 99-xdebug-enable.ini
} | tee 99-xdebug-enable.ini
Copy the code
Host. Docker. Internal and 19000 are necessary, the host points to the host, the port is the port on which PHP Storm listens, docker needs to send requests to it, so it needs to make sure it is not occupied.
- Further reading
Networking features in Docker Desktop for Windows | Docker Documentation
Install PhpRedis
Use this extension because your project needs to connect to Redis, which is just a connection library, not Redis.
# install phpredis
RUN cd /tmp \
# from mirrors
&& git clone https://gitee.com/mirrors/phpredis phpredis \
&& cd phpredis \
&& phpize \
&& ./configure \
&& make \
&& make install \
&& docker-php-ext-enable redis \
&& php -m \
&& php --ri redis
Copy the code
Miscellaneous configuration
# check
Check PHP version information and installed modules
RUN cd /tmp \
Check the PHP version
&& php -v \
Check the installed modules
&& php -m \
&& echo -e "Build Completed!"
Expose port 9501
EXPOSE 9501
The default login directory does not exist.
# We need to map our external Windows file directory to the Docker container during run
WORKDIR /mnt/d/htdocs
Copy the code
Dockerfile
Our Dockerfile should now look like this
FROM php:7.3.17-cli-alpine3.11
Now we need to configure something.
# compile parameter, used to specify the Swoole version
ARG swoole_ver
# save to environment variable, if not passed to default value
ENV SWOOLE_VER=${swoole_ver:-"v4.4.15"}
# APk is a package manager for Alpine
# set-ex is to stop the script in case of an error
RUN set -ex \
Do all this in a temporary directory
&& cd /tmp \
# change the default apK source to the Aliyun image
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
Update package list
&& apk update \
# Add so many extensions because we'll need them later to compile Swoole and sdebug
&& apk add vim git autoconf openssl-dev build-base zlib-dev re2c libpng-dev oniguruma-dev
# install composer
RUN cd /tmp \
# Download Composer from Aliyun
&& wget https://mirrors.aliyun.com/composer/composer.phar \
&& chmod u+x composer.phar \
&& mv composer.phar /usr/local/bin/composer \
# Set aliyun image for Composer
&& composer config -g repo.packagist composer https://mirrors.aliyun.com/composer \
Add the composer global command to PATH to make sure we use it later
&& echo 'export PATH="$PATH:$HOME/.composer/vendor/bin"' >> ~/.bashrc
# php ext
RUN php -m \
# docker-php-ext-install # docker-php-ext-install is a PHP directive that allows us to install some default PHP extensions
You can enable the necessary extensions here
&& docker-php-ext-install gd pdo_mysql mysqli sockets pcntl \
Now you can check the extensions that PHP already has installed
&& php -m
# install swoole
RUN cd /tmp \
# from mirrors
&& git clone https://gitee.com/swoole/swoole swoole \
&& cd swoole \
# Switch to the specified version of the tag
&& git checkout ${SWOOLE_VER} \
&& phpize \
Run configure
&& ./configure --enable-openssl --enable-sockets --enable-http2 --enable-mysqlnd \
&& make \
&& make install \
# enable the extension via docker-php-ext-enable, which is also provided by PHP.
&& docker-php-ext-enable swoole \
Check PHP modules already installed
&& php -m \
Check whether swoole is installed correctly
&& php --ri swoole
# install sdebug
Change the directory to/TMP before running clone
RUN cd /tmp \
# from mirrors
&& git clone https://gitee.com/vyi/sdebug sdebug \
Go to the clone directory
&& cd sdebug \
Switch to the sdebug_2_7 branch, this must be the switch branch, because the master branch is the source of Xdebug
&& git checkout sdebug_2_7 \
&& phpize \
&& ./configure --enable-xdebug \
&& make \
&& make install \
# here is the value xdebug executed after the installation is complete
&& docker-php-ext-enable xdebug \
&& php -m \
Sdebug = sdebug
&& php --ri sdebug
# config php
RUN cd /usr/local/etc/php/conf.d \
# swoole config
# Turn off swoole short name, use Hyperf this is required
&& echo "swoole.use_shortname = off" >> 99-off-swoole-shortname.ini \
# config xdebug&& {\# Add an Xdebug node
echo "[Xdebug]"; \
# Enable remote connection
echo "xdebug.remote_enable = 1"; \
# This is a multi-user debugging, but now some difficulties, temporarily do not start
echo "; xdebug.remote_connect_back = On"; \
Start remote debugging automatically
echo "xdebug.remote_autostart = true"; \
Host. Docker. Internal.
echo "xdebug.remote_host = host.docker.internal"; \
The port is fixed to 19000. Of course, other ports can be filled in to ensure that they are not occupied
echo "xdebug.remote_port = 19000"; \
# Here is fixed
echo "xdebug.idekey=PHPSTORM"; \
Save the result to 99-xdebug-enable.ini
} | tee 99-xdebug-enable.ini
# install phpredis
RUN cd /tmp \
# from mirrors
&& git clone https://gitee.com/mirrors/phpredis phpredis \
&& cd phpredis \
&& phpize \
&& ./configure \
&& make \
&& make install \
&& docker-php-ext-enable redis \
&& php -m \
&& php --ri redis
# check
Check PHP version information and installed modules
RUN cd /tmp \
Check the PHP version
&& php -v \
Check the installed modules
&& php -m \
&& echo -e "Build Completed!"
Expose port 9501
EXPOSE 9501
The default login directory does not exist.
# We need to map our external Windows file directory to the Docker container during run
WORKDIR /mnt/d/htdocs
Copy the code
That’s our complete Dockerfile, now we’re going to generate the image file
Docker build -f php.dockerfile -t faqqcn/php-swoole-sdebug:1.0.Copy the code
- -f means we want to use the dockerfile file
- -t indicates a name format for our image
<domain>/<name>:<tag>
- . The final
.
Represents the current directory
Successfully built 9c5c20556cf2 Successfully tagged faqqcn/php-swoole-sdebug:1.0 SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.Copy the code
The output above shows that the image was successfully created. Now take a look.
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
faqqcn/php-swoole-sdebug 1.0 9c5c20556cf2 About a minute ago 526MB
Copy the code
Now let’s run it
$ docker run -di -p 8080:9501 -v D:/2vy-cc/htdocs:/mnt/d/htdocs --name php-swoole-sdebug faqqcn/php-swoole-sdebug:1.0
19db6032c9fe9cd2228844e4c029c980f14172991a4f113480ee5facd1763c2e
Copy the code
- Parameter interpretation
parameter | instructions |
---|---|
-di | This is short for the -d and -i parameters, d for background operation and I for interactive operation |
-p | Enable a port mapping that maps 8080 on the host to 9501 in the container |
-v | Enable a directory mapping that maps the host’s D:/2vy-cc/htdocs directory to the container’s/MNT/D /htdocs |
–name | Give the container a name for next startup, deactivation, deletion, and logging |
See the Docker run command for more parameters
And then the name of our image, and then the Docker will print out the container ID
Now go into the container.
docker exec -it php-swoole-sdebug sh
Copy the code
-it means to create an interactive operation and create a terminal, followed by the name above, and finally a startup shell. Alpine defaults to sh after entering the terminal, check PHP information and create a project
# PHP -v PHP 7.3.17 (cli) Copyright (c) 1997-2018 The PHP Group Zend Engine V3.3.17, Copyright (c) 1998-2018 Zend Technologies with Sdebug V2.7.3-dev, Copyright (c) 2002-2019, by Derick Rethans # php [PHP Modules] Core ctype curl date dom fileinfo filter ftp gd hash iconv json libxml mbstring mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql pdo_sqlite Phar posix readline redis Reflection sdebug session SimpleXML sockets sodium SPL sqlite3 standard swoole tokenizer xml xmlreader xmlwriter zlib [Zend Modules] Sdebug # composer ... / ____ _____ _____ _____ _____ _____ _____ _____ / / / / / (` __ \ / __ / __ \ / ___ / _ \ / ___ / / / ___ / / __ / / / / / / / / _ / / / _ (__) __ / / there comes \ \ _____ / _ _ /. / / / _ ___ / / ____ ____ / / ___ / __ / / _ / Composer version 1.10.5 2020-04-10 11:44:22Copy the code
You can see that swoole, Redis, Sdebug, Composer are installed, and next we will create a Hyperf project
Create a project
# composer create-project hyperf/hyperf-skeleton
Copy the code
There will be a boot during the installation, where you can either press Enter by default or select your own components as needed. Now enter the project and start it.
cd hyperf-skeleton
php bin/hyperf.php start
Copy the code
You will see all the errors pop up, but don’t worry, if you look closely, you will see that this is a Redis error, we will fix it later. For the sake of our pleasant development, if we have to execute the above command every time we modify the file, we will now install a tool to automatically restart the file after modification.
# curl -o watch https://gitee.com/liangguifeng/hyperf-watch/raw/master/watch
# ls -alF | grep watch
-rwxr-xr-x 1 root root 3921 May 4 07:40 watch*
Copy the code
If there’s no x in the watch permission here, let’s add it manually
chmod +x watch
Copy the code
Now let’s execute PHP Watch. Then open PHPStorm in the host, start writing code in PHPStorm, and configure Sdebug.
PHPStorm
Open the file
- Config /autoload/async_queue.php
'processes' => 1,
为'processes' => 0,
Note, here refers to turn off the asynchronous queue, and thus to solve the Redis error in the console, if you need to use the asynchronous queue, please bring here remains the same, and to the config/autoload/Redis. The PHP configuration Redis link information correctly.
We have mapped 8080 on the host to port 9501 on the host, so we will directly access port 8080 on the host.
OK, now that we have access to the project deployed in Docker, configure debugging. Open the PHPStorm set into the Languages & Frameworks | PHP, looks like this.
Click here…
Select + and select From Docker…
If successful is not successful, you did not enable TCP connections in the first step
Select mirror image here.
Ok after checking and confirming
Now go in here and re-select the container and the native mapping relationship to help us find the corresponding file during debugging, otherwise debugging will fail.
Delete an existing mapping and select the default mapping
Then click “Mapping” on the previous line to add
Now add the directory mapping
Now, in the open Languages and Frameworks is set | | PHP Debug
Create a service and fill in the corresponding information, remembering the Name XDEBUG_02
Create a new debug
Adding a Configuration
Now click on the phone in the upper right corner to change it to this state.
Start debugging!
Switch to the container window, terminate the previous command, now we run PHP watch, you will find that it is stuck!! What the hell is this? This means Xdebug is working and if you go to PHPStorm, you’ll notice that the skip button on the left is green and the breakpoint button is green. Now if we go from the new point to the Debugger column, you’ll notice that there is an error. And there are no effects in the IDE. Because it’s not really done yet.
Now let’s fix it. According to the error message, we can simply learn that it is necessary to use the environment variable called PHP_IDE_CONFIG, and click more info… Go to the PHPStorm documentation page, search PHP_IDE_CONFIG, and find that we need to configure a parameter called serverName, which is the Server created earlier, to map local files.
Since we are debugging the CLI inside the container, we go to the terminal of the container and type the following
export PHP_IDE_CONFIG=serverName=XDEBUG_02
Copy the code
Then execute PHP Watch. Now you’ll see, when we’re on watch, the break point starts working.
Now if you debug, you will notice that the following debug bar sometimes has several hyperf.php cuts back and forth, which is very disturbing. This is because the project is configured to use multiple workers by default. You can change it to 1 here.
Business debugging
Now try debugging your business code! Go to the default controller, next breakpoint.
Open the browser refresh and you will see that nothing has changed and that the breakpoint has not been caught.
You just add XDEBUG_SESSION_START=PHPSTORM to the URl and the URl becomes http://localhost:8080/? XDEBUG_SESSION_START=233 Now we can see that PHPStorm has successfully loaded the breakpoint.
If this is too much trouble, you can install a Chrome extension called Xdebuge Helper. After installation, right-click on the plugin bar and select options, select PHPSTORM in the IDE Key and save, return to the page, left-click on the bug in the plugin bar and select Debug. Now refresh the page and PHPSTORM will automatically capture Debug.
Debug in POSTMAN
We can debug GET requests directly in the browser, but sometimes when we need to send headers or posts, we will use tools like POSTMAN to request. In this case, we just need to add XDEBUG_SESSION_START=PHPSTORM to the request parameter. We can also add XDEBUG_SESSION=PHPSTORM to the Cookie to trigger debugging.
The end.
The whole thing is a bit more complicated than the previous article, but I’ve tried to say as much as I can with as little as possible.
If you have other ideas or good suggestions can contact me directly, if you find the content of the article is wrong, welcome to point out.
If you’re still interested in remote debugging, check out my other article on XDEBUG remote debugging. Xdebug remote debugging, can you use it?
Refer to the content
- Networking features in Docker Desktop for Windows | Docker Documentation
- Debug a PHP CLI script – Help | PhpStorm
- hyperf-watch
- Install – Hyperf
- Mabu233 / sDEBUG: Xdebug – Step Debugger and Debugging Aid for PHP