Laravel, with version 8, introduces a very practical wrapper for a docker environment: Laravel Sail. I personally find it way more easy to use than Laravel Homestead, that had the same purpose of proposing a development environment in a virtual machine. Especially when it comes to deployment.
Coming from low level software development, I’ve been used to this incredibly powerful tool that is a debugger. Placing breakpoints into my code, and being able to watch every variable while going through the code step by step is just great. And it helps understand what is really going on, which is, I think, non-negligible for beginners.
Unfortunately, The Laravel Sail environment does not ship with xDebug installed. Which is an issue being discussed quite roughly on the github repository! I won’t go into the argument. I understand both sides, and I wouldn’t know how to settle it. But since the outcome, for now, is to not embed the xDebug option onto Laravel Sail, I will show here how you can very easily add xDebug to your configuration.
Publish Laravel Sail docker files
I assume that you have Docker Desktop installed and running on your computer. I also assume that you have a Laravel 8 project created. If not, just follow the guide.
You need to publish Sail’s Dockerfiles by executing the sail:publish
command:
./vendor/bin/sail artisan sail:publish
A new directory named docker should appear at the root of your project. Inside you will find 2 directories named 7.4 and 8.0. And in both of them you will find a Dockerfile. Open them.
Edit the Dockerfile
We are going to add xDebug to the container as an option. This way it will be present in your development environment if you want it, but not on your deployed version.
Here is what your Dockerfile should look like once edited:
FROM ubuntu:20.04
LABEL maintainer="Taylor Otwell"
ARG WWWGROUP
ARG XDEBUG
WORKDIR /var/www/html
ENV DEBIAN_FRONTEND noninteractive
ENV TZ=UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update \
&& apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python2 \
&& mkdir -p ~/.gnupg \
&& chmod 600 ~/.gnupg \
&& echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf \
&& apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E5267A6C \
&& apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C300EE8C \
&& echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu focal main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \
&& apt-get update \
&& apt-get install -y php8.0-cli php8.0-dev \
php8.0-pgsql php8.0-sqlite3 php8.0-gd \
php8.0-curl php8.0-memcached \
php8.0-imap php8.0-mysql php8.0-mbstring \
php8.0-xml php8.0-zip php8.0-bcmath php8.0-soap \
php8.0-intl php8.0-readline \
php8.0-msgpack php8.0-igbinary php8.0-ldap \
php8.0-redis
RUN if [ ${XDEBUG}] ; then \
apt-get install -y php-xdebug; \
fi;
RUN php -r "readfile('http://getcomposer.org/installer');" | php -- --install-dir=/usr/bin/ --filename=composer \
&& curl -sL https://deb.nodesource.com/setup_15.x | bash - \
&& apt-get install -y nodejs \
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get install -y yarn \
&& apt-get install -y mysql-client \
&& apt-get install -y postgresql-client \
&& apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN pecl channel-update https://pecl.php.net/channel.xml \
&& pecl install swoole
RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.0
RUN groupadd --force -g $WWWGROUP sail
RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail
COPY start-container /usr/local/bin/start-container
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY php.ini /etc/php/8.0/cli/conf.d/99-sail.ini
RUN chmod +x /usr/local/bin/start-container
EXPOSE 8000
ENTRYPOINT ["start-container"]
Line 6
We add an argument named XDEBUG that can be provided when executing this Dockerfile.
Lines 33 to 35
We insert a condition for installing xDebug, depending on the value of the XDEBUG argument. It is important that the insert is made in this spot. Be careful to do exactly as I did when cutting the RUN instruction in half.
Initialize PHP with xdebug
In those same 2 directories named 7.4 and 8.0, you will find a php.ini file. Open them.
We need ton configure xdebug. Just add the following in the php.ini file:
[XDebug]
zend_extension = xdebug.so
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.discover_client_host = true
xdebug.idekey = VSC
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
Notice that the port 9003 is specified for xDebug client. You can choose another but this one is fine.
Propagate the argument through the docker-compose
To be passed over to the Dockerfile, the XDEBUG argument needs to be set in the docker-compose.yml file. This file is located at the root of you project.
To make it dynamic, and allow xDebug to be activated or not depending on whether it’s executing on the production server or on the development environment, tothe XDEBUG argument will be assigned a variable which I’ll name SAIL_XDEBUG, but you are free to name it as you wish. So, locate the laravel.test section of the docker-compose file and add the argument as follow:
laravel.test:
build:
context: ./docker/8.0
dockerfile: Dockerfile
args:
WWWGROUP: "${WWWGROUP}"
XDEBUG: ${SAIL_DEBUG}
image: sail-8.0/app
ports:
- "${APP_PORT:-80}:80"
environment:
WWWUSER: "${WWWUSER}"
LARAVEL_SAIL: 1
volumes:
- ".:/var/www/html"
networks:
- sail
depends_on:
- mysql
- selenium
Activate xDebug from your env file
Now to activate xDebug on your development environment, you just need to add SAIL_DEBUG=true
to your .env file. Each time you change it, you will need to rebuild the docker image of your app. So let’s do it. Back in your console, run:
./vendor/bin/sail build --no-cache
It will take a few minutes…
To make sure XDebug is active, run the command:
./vendor/bin/sail php -v
You should see a mention to PHP XDebug with it’s version.
Start debugging with VSCode
I’ll show you how to configure VSCode to start debugging, but the configuration should be similar for other editors.
Installation of the extension
To install it in VSCode, we need to :
- Click on the “Extensions” icon (or Ctrl + Shift + X),
- then use the search field to find the extension (type xdebug),
- and finally install it (click on the little green “Install” button).


To work, you need PHP installed on your computer. We can check it’s installed by typing the php -version
command in a console. It should output the currently installed version of PHP.


If not, you can download the last version (nonthread safe) on this site.
Configuration of a listener
The PHP Debug extension is able to manage many configurations if we need to listen to many instances of Xdebug. We are going to create only one here, for our container.
For that we need to :
- Click on the “debug” icon on the sidebar (or Ctrl + Shift + D),
- then click on the gear icon titled “Open launch.json” next to the drop-down menu at the top of the left side panel,
- then click on PHP in the list of proposed environments. A hidden folder named .vscode containing a file named launch.json is created in our project root folder.
We can easily deduce that the configuration of our extension is liked to our project, which is convenient because all of our projects don’t necessarily use Docker and will likely have different configurations.
Inside our launch.json file, we notice 2 configurations that we can delete (or not, doesn’t matter). We are gonna create a new one :
{
"name": "Listen for XDebug on Docker App",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html": "${workspaceFolder}"
},
"hostname": "localhost",
"xdebugSettings": {
"max_data": 65535,
"show_hidden": 1,
"max_children": 100,
"max_depth": 5
}
},
Let’s debug
You’re up. Give it a try!
If you want more details on this configuration, have a look at my article on Debug with VSCode, Xdebug, and Docker on Windows.
I hope you enjoyed this article.
Thanks for reading me. Have a nice day!
The addition to the Dockerfile should be be php8.0-xdebug instead of just php-xdebug.
Hi, Thanks for the post. I soptted an error: where you said SAILDEBUG=true, it should be SAIL_DEBUG=true (to match the var name in the docker-compose file. It just couldn’t build with the incorrect name!
Hi, I am getting the following error while running: php -v
PHP Warning: Failed loading Zend extension ‘xdebug.so’ (tried: /usr/lib/php/20200930/xdebug.so (/usr/lib/php/20200930/xdebug.so: cannot open shared object file: No such file or directory), /usr/lib/php/20200930/xdebug.so.so (/usr/lib/php/20200930/xdebug.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
PHP 8.0.8 (cli) (built: Jul 1 2021 15:26:46) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.8, Copyright (c) Zend Technologies
with Zend OPcache v8.0.8, Copyright (c), by Zend Technologies
I have the same issue Dave.
Does anybody have a solution for this?
used
‘pecl install xdebug’
to fix this instead of
‘apt-get install -y php-xdebug;’
to fix this error
Hi all,
I’ve been looking for this.
Unfortunately, I can’t get it to work…
With either of these options:
– pecl install xdebug;
– apt-get install -y php-xdebug;
– apt-get install -y php8.0-xdebug;
I always get this message from “sail php -v” :
“PHP Warning: Failed loading Zend extension ‘xdebug.so’ (tried: /usr/lib/php/20200930/xdebug.so (/usr/lib/php/20200930/xdebug.so: cannot open shared object file: No such file or directory), /usr/lib/php/20200930/xdebug.so.so (/usr/lib/php/20200930/xdebug.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0”
Hello guys !
The last release of Sail now includes xdebug option. This tutorial is now worthless I’m afraid.
Have a nice day !