{"id":1925,"date":"2017-05-27T12:47:31","date_gmt":"2017-05-27T07:17:31","guid":{"rendered":"http:\/\/ramkulkarni.com\/blog\/?p=1925"},"modified":"2017-05-27T12:47:31","modified_gmt":"2017-05-27T07:17:31","slug":"setting-up-and-debugging-php7-in-docker","status":"publish","type":"post","link":"http:\/\/ramkulkarni.com\/blog\/setting-up-and-debugging-php7-in-docker\/","title":{"rendered":"Setting up and Debugging PHP7 in Docker"},"content":{"rendered":"<p>Before developing applications in any new language\/platform I make sure that the debugger works in the set up. I had been working on some projects in Python and PHP recently and I have already shared my notes on <a href=\"http:\/\/ramkulkarni.com\/blog\/docker-project-for-python3-djaongo-and-apache2-setup\/\" target=\"_blank\" rel=\"noopener noreferrer\">setting up<\/a> and <a href=\"http:\/\/ramkulkarni.com\/blog\/debugging-django-project-in-docker\/\" target=\"_blank\" rel=\"noopener noreferrer\">debugging Python (Django) application in Docker<\/a> and how to debug the application.<\/p>\n<p>In this post I will describe how to setup PHP7 in Docker and debug the application. You can checkout\u00a0the project from <a href=\"https:\/\/github.com\/ramkulkarni1\/php7-apache2-docker\" target=\"_blank\" rel=\"noopener noreferrer\">this Github repo<\/a>.<\/p>\n<p>Here is the Docker file for this setup &#8211;<\/p>\n<pre style=\"color: #000020; background: #f6f8ff;\"><span style=\"color: #005fd2;\">FROM<\/span> <span style=\"color: #1060b6;\">php:7.0.17-apache<\/span>\r\n\r\n<span style=\"color: #005fd2;\">RUN<\/span> <span style=\"color: #1060b6;\">apt-get<\/span> <span style=\"color: #1060b6;\">update<\/span>\r\n<span style=\"color: #005fd2;\">RUN<\/span> <span style=\"color: #1060b6;\">apt-get<\/span> <span style=\"color: #1060b6;\">install<\/span> <span style=\"color: #074726;\">-y<\/span> <span style=\"color: #1060b6;\">apt-utils<\/span> <span style=\"color: #1060b6;\">vim<\/span> <span style=\"color: #1060b6;\">curl<\/span> <span style=\"color: #1060b6;\">sqlite3<\/span>\r\n<span style=\"color: #005fd2;\">RUN<\/span> <span style=\"color: #1060b6;\">pecl<\/span> <span style=\"color: #1060b6;\">install<\/span> <span style=\"color: #1060b6;\">xdebug<\/span>\r\n<span style=\"color: #595979;\"># copy test db file<\/span>\r\n<span style=\"color: #005fd2;\">ADD<\/span> <span style=\"color: #1060b6;\">.\/db\/employee.db<\/span> <span style=\"color: #1060b6;\">\/employee.db<\/span>\r\n<span style=\"color: #595979;\"># The base image does not have php.ini. <\/span>\r\n<span style=\"color: #595979;\"># Copy our own, with xdebug settings<\/span>\r\n<span style=\"color: #005fd2;\">ADD<\/span> <span style=\"color: #1060b6;\">.\/php.ini<\/span> <span style=\"color: #1060b6;\">\/usr\/local\/etc\/php\/<\/span>\r\n\r\n<span style=\"color: #005fd2;\">EXPOSE<\/span> <span style=\"color: #008c00;\">80<\/span>\r\n<\/pre>\n<p>The container is based on<a href=\"https:\/\/hub.docker.com\/_\/php\/\" target=\"_blank\" rel=\"noopener noreferrer\"> php image from docker hub<\/a>. The version number is <a href=\"https:\/\/github.com\/docker-library\/php\/blob\/76a1c5ca161f1ed6aafb2c2d26f83ec17360bc68\/7.0\/apache\/Dockerfile\" target=\"_blank\" rel=\"noopener noreferrer\">7.0.17-apache<\/a>. This example uses Sqlite3 database, so the package is installed.<\/p>\n<p>To debug PHP applications, you need to install xdebug. In the docker file it is installed using <a href=\"https:\/\/pecl.php.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">pecl<\/a>. Then employee.db (Sqlite3 DB) is copied from the project folder to the root of docker container.<\/p>\n<p><!--more-->The PHP base image does not create php.ini. But we need to create one to set a few XDebug parameters. So we copy php.ini from the project folder to \/usr\/local\/etc\/php in the container.<\/p>\n<p>Here is the content of php.ini &#8211;<\/p>\n<pre style=\"color: #000020; background: #f6f8ff;\"><span style=\"color: #0057a6;\">[<\/span><span style=\"color: #333385;\">xdebug<\/span><span style=\"color: #0057a6;\">]<\/span>\r\n<span style=\"color: #474796;\">zend_extension<\/span><span style=\"color: #308080;\">=<\/span><span style=\"color: #308080;\">\/<\/span>usr<span style=\"color: #308080;\">\/<\/span>local<span style=\"color: #308080;\">\/<\/span>lib<span style=\"color: #308080;\">\/<\/span>php<span style=\"color: #308080;\">\/<\/span>extensions<span style=\"color: #308080;\">\/<\/span>no<span style=\"color: #308080;\">-<\/span>debug<span style=\"color: #308080;\">-<\/span>non<span style=\"color: #308080;\">-<\/span>zts<span style=\"color: #308080;\">-<\/span><span style=\"color: #008c00;\">20151012<\/span><span style=\"color: #308080;\">\/<\/span>xdebug<span style=\"color: #308080;\">.<\/span>so\r\n<span style=\"color: #474796;\">xdebug.remote_enable<\/span><span style=\"color: #308080;\">=<\/span><span style=\"color: #008c00;\">1<\/span>\r\n<span style=\"color: #474796;\">xdebug.remote_autostart<\/span><span style=\"color: #308080;\">=<\/span><span style=\"color: #008c00;\">1<\/span>\r\n<span style=\"color: #474796;\">xdebug.remote_host<\/span><span style=\"color: #308080;\">=<\/span>&lt;ip<span style=\"color: #308080;\">-<\/span>of<span style=\"color: #308080;\">-<\/span>debug<span style=\"color: #308080;\">-<\/span>client<span style=\"color: #308080;\">-<\/span>machine&gt;\r\n<span style=\"color: #474796;\">xdebug.remote_port<\/span><span style=\"color: #308080;\">=<\/span><span style=\"color: #008c00;\">9000<\/span>\r\n<\/pre>\n<p>zend_extension is set to path of xdebug.so file. Ad of current version, pecl installs xdebug at the path specified above. You can check if the above path is valid in your docker container by executing &#8216;find&#8217; command (you need to run bash command in the container and execute &#8216;docker exec -it php7-apache2 bash&#8217;)<\/p>\n<pre style=\"color: #000020; background: #f6f8ff;\">$ <span style=\"color: #1060b6;\">find<\/span> <span style=\"color: #1060b6;\">\/<\/span> <span style=\"color: #074726;\">-name<\/span> <span style=\"color: #1060b6;\">xdebug.so<\/span>\r\n<\/pre>\n<p>If you find that path of xdebug.so is different in you set up, you will have to rebuild the image by executing &#8216;docker-compose build&#8217;.<\/p>\n<p>Coming back to php.ini, you need to set value of xdebug.remote_host to IP of your host machine, from where you would remote debug the application. Set xdebug.remote_port to any port that is not already taken in the host machine. In this example, the port is set to 9000.<\/p>\n<p>docker-compose.yml contains some simple settings &#8211;<\/p>\n<pre style=\"color: #000020; background: #f6f8ff;\"><span style=\"color: #e34adc;\">version:<\/span> <span style=\"color: #800000;\">\"<\/span><span style=\"color: #1060b6;\">2<\/span><span style=\"color: #800000;\">\"<\/span>\r\n\r\n<span style=\"color: #e34adc;\">services:<\/span> \r\n  php7<span style=\"color: #308080;\">-<\/span>apache2<span style=\"color: #406080;\">:<\/span>\r\n<span style=\"color: #e34adc;\">\u00a0\u00a0\u00a0\u00a0build:<\/span> <span style=\"color: #308080;\">.<\/span>\r\n<span style=\"color: #e34adc;\">\u00a0\u00a0\u00a0\u00a0container_name:<\/span> php7<span style=\"color: #308080;\">-<\/span>apache2\r\n<span style=\"color: #e34adc;\">\u00a0\u00a0\u00a0\u00a0ports:<\/span>\r\n      <span style=\"color: #308080;\">-<\/span> <span style=\"color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;\">'8002:80'<\/span>\r\n<span style=\"color: #e34adc;\">\u00a0\u00a0\u00a0\u00a0volumes:<\/span> \r\n      <span style=\"color: #308080;\">-<\/span> $PWD<span style=\"color: #308080;\">\/<\/span>htdocs<span style=\"color: #406080;\">:<\/span><span style=\"color: #308080;\">\/<\/span>var<span style=\"color: #308080;\">\/<\/span>www<span style=\"color: #308080;\">\/<\/span>html\r\n<\/pre>\n<p>It maps port 80 from the container to 8002 to the host machine. So you can access Apache2 running in the container from host machine using url http:\/\/localhost:8002. Using volumes setting, it maps htdocs folder in the project to \/var\/www\/html folder in the container.\u00a0\/var\/www\/html is the doc root for Apache2 server in the container. So any file you create in htdocs folder in the project in host machine can be served by Apache2 in the container.<\/p>\n<p>To enable PHP debugging in Visual Studio Code, you need to install PHP Debug extension. In Visual Studio Code, select menu View | Command Pallet and type Install Extension in the filter text box. Select that option and then search for extension and install it.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1926\" data-permalink=\"http:\/\/ramkulkarni.com\/blog\/setting-up-and-debugging-php7-in-docker\/vs-code-install-php-debug-extension\/\" data-orig-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?fit=1348%2C688\" data-orig-size=\"1348,688\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"vs-code-install-php-debug-extension\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?fit=300%2C153\" data-large-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?fit=525%2C268\" class=\"alignnone wp-image-1926 size-large\" src=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension-1024x523.png?resize=525%2C268\" alt=\"\" width=\"525\" height=\"268\" srcset=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?resize=1024%2C523 1024w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?resize=300%2C153 300w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?resize=768%2C392 768w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-install-php-debug-extension.png?w=1348 1348w\" sizes=\"(max-width: 525px) 100vw, 525px\" data-recalc-dims=\"1\" \/><\/p>\n<p>Next step is to add lunch configuration. Click on Debug icon in the left bar and then click on the drop down list to select configuration. Initially the list only displays &#8216;No Configuration&#8217; and &#8216;Add Configuration&#8217;. Select &#8216;Add \u00a0Configuration&#8217; and select PHP configuration.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1927\" data-permalink=\"http:\/\/ramkulkarni.com\/blog\/setting-up-and-debugging-php7-in-docker\/vs-code-add-php-launch-configuration\/\" data-orig-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?fit=1382%2C692\" data-orig-size=\"1382,692\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"vs-code-add-php-launch-configuration\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?fit=300%2C150\" data-large-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?fit=525%2C263\" class=\"alignnone wp-image-1927 size-large\" src=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?resize=525%2C263\" alt=\"\" width=\"525\" height=\"263\" srcset=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?resize=1024%2C513 1024w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?resize=300%2C150 300w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?resize=768%2C385 768w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-add-php-launch-configuration.png?w=1382 1382w\" sizes=\"(max-width: 525px) 100vw, 525px\" data-recalc-dims=\"1\" \/><\/p>\n<p>Two PHP configurations are added to launch.json file &#8211;\u00a0&#8220;Listen for XDebug&#8221; and\u00a0&#8220;Launch currently open script&#8221;. We are interested in the first configuration. We need to add local to remote mapping path to this configuration &#8211;<\/p>\n<pre style=\"color: #000020; background: #f6f8ff;\"><span style=\"color: #595979;\">{<\/span>\r\n<span style=\"color: #595979;\">\u00a0\u00a0\u00a0\u00a0\"name\": \"Listen for XDebug\",<\/span>\r\n<span style=\"color: #595979;\">\u00a0\u00a0\u00a0\u00a0\"type\": \"php\",<\/span>\r\n<span style=\"color: #595979;\">\u00a0\u00a0\u00a0\u00a0\"request\": \"launch\",<\/span>\r\n<span style=\"color: #595979;\">\u00a0\u00a0\u00a0\u00a0\"serverSourceRoot\": \"\/var\/www\/html\",<\/span>\r\n<span style=\"color: #595979;\">\u00a0\u00a0\u00a0\u00a0\"localSourceRoot\": \"${workspaceRoot}<\/span><span style=\"color: #308080;\">\/<\/span>htdocs\"<span style=\"color: #308080;\">,<\/span>\r\n    \"port\"<span style=\"color: #308080;\">:<\/span> <span style=\"color: #008c00;\">9000<\/span>\r\n}<span style=\"color: #308080;\">,<\/span>\r\n<\/pre>\n<p>Local folder in project, htdocs, is mapped to \/var\/www\/html in the container.<\/p>\n<p>Start the container by executing command &#8211;<\/p>\n<pre style=\"color: #000020; background: #f6f8ff;\">$ docker<span style=\"color: #308080;\">-<\/span>compose up\r\n<\/pre>\n<p>Then set breakpoint in index.php (say line #2) and open http:\/\/localhost:8002 in the browser.\u00a0In VS Code you should see that breakpoint is hit at the same line.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1928\" data-permalink=\"http:\/\/ramkulkarni.com\/blog\/setting-up-and-debugging-php7-in-docker\/vs-code-debug-php\/\" data-orig-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?fit=1628%2C912\" data-orig-size=\"1628,912\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"vs-code-debug-php\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?fit=300%2C168\" data-large-file=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?fit=525%2C294\" class=\"alignnone wp-image-1928 size-large\" src=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?resize=525%2C294\" alt=\"\" width=\"525\" height=\"294\" srcset=\"https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?resize=1024%2C574 1024w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?resize=300%2C168 300w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?resize=768%2C430 768w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?w=1628 1628w, https:\/\/i0.wp.com\/ramkulkarni.com\/blog\/wp-content\/uploads\/2017\/05\/vs-code-debug-php.png?w=1575 1575w\" sizes=\"(max-width: 525px) 100vw, 525px\" data-recalc-dims=\"1\" \/><\/p>\n<p>Watch this video to see how all this works &#8211;<\/p>\n<p><span class=\"embed-youtube\" style=\"text-align:center; display: block;\"><iframe loading=\"lazy\" class=\"youtube-player\" width=\"525\" height=\"296\" src=\"https:\/\/www.youtube.com\/embed\/htAk4Z6dIiA?version=3&#038;rel=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;fs=1&#038;hl=en-US&#038;autohide=2&#038;wmode=transparent\" allowfullscreen=\"true\" style=\"border:0;\" sandbox=\"allow-scripts allow-same-origin allow-popups allow-presentation allow-popups-to-escape-sandbox\"><\/iframe><\/span><\/p>\n<p>-Ram Kulkarni<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Before developing applications in any new language\/platform I make sure that the debugger works in the set up. I had been working on some projects in Python and PHP recently and I have already shared my notes on setting up and debugging Python (Django) application in Docker and how to debug the application. In this &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/ramkulkarni.com\/blog\/setting-up-and-debugging-php7-in-docker\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Setting up and Debugging PHP7 in Docker&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[135,139],"tags":[141,133,140,143,142],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2g9O8-v3","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1925"}],"collection":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/comments?post=1925"}],"version-history":[{"count":3,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1925\/revisions"}],"predecessor-version":[{"id":2177,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/1925\/revisions\/2177"}],"wp:attachment":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/media?parent=1925"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/categories?post=1925"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/tags?post=1925"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}