{"id":220989,"date":"2021-04-07T15:00:08","date_gmt":"2021-04-07T12:00:08","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/"},"modified":"2021-04-07T15:00:08","modified_gmt":"2021-04-07T12:00:08","slug":"how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/","title":{"rendered":"#How to Use Docker to Containerise PHP and Apache \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a292079e8882\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a292079e8882\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#Creating_a_Dockerfile\" >Creating a Dockerfile<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#Customising_Apache_Configuration\" >Customising Apache Configuration<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#Adding_PHP_Extensions\" >Adding PHP Extensions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#PHP_Configuration\" >PHP Configuration<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#Using_Composer\" >Using Composer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#Custom_Entrypoint_Scripts\" >Custom Entrypoint Scripts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-docker-to-containerise-php-and-apache-cloudsavvy-it\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How to Use Docker to Containerise PHP and Apache \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-9034\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/01\/6dc7b5a0.jpeg?width=1200&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1602\" height=\"902\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Docker containers make your <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a> portable across environments. Once you\u2019ve got a container image, you can use it anywhere Docker is available. Here\u2019s how to containerise a PHP web application using the Apache server.<\/p>\n<p>We\u2019ll use the official <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/hub.docker.com\/_\/php\">PHP Docker image<\/a> as our base. Variants preconfigured with Apache are provided, so you won\u2019t need to install the web server yourself. The PHP base image also offers convenience utilities for managing PHP extensions.<\/p>\n<h2 id=\"creating-a-dockerfile\"><span class=\"ez-toc-section\" id=\"Creating_a_Dockerfile\"><\/span>Creating a Dockerfile<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Docker images are created from a <code>Dockerfile<\/code>. This file contains instructions which are used to build the image. Instructions include <code>COPY<\/code>, to copy files and folders into the container, and <code>RUN<\/code>, which runs a command within the container.<\/p>\n<p>You can get a simple PHP site running by simply copying its files into an image based on <code>php:8.0-apache<\/code>.<\/p>\n<pre class=\"dockerfile\"><code>FROM php:8.0-apache&#13;\nWORKDIR \/var\/www\/html&#13;\n&#13;\nCOPY index.php index.php&#13;\nCOPY src\/ src&#13;\nEXPOSE 80<\/code><\/pre>\n<p>This <code>Dockerfile<\/code> takes <code>index.php<\/code> and <code>src<\/code> from our working directory and copies them into the Apache document root. You could now build the image and start a container from it. You\u2019d see your site being served by Apache.<\/p>\n<pre><code>docker build -t my-php-site:latest .&#13;\ndocker run -d -p 80:80 my-php-site:latest<\/code><\/pre>\n<p>The PHP Docker images have the Apache document root at the default Debian location of <code>\/var\/www\/html<\/code>. The <code>WORKDIR<\/code> instruction in the <code>Dockerfile<\/code> means subsequent commands will be executed within the document root.<\/p>\n<p>Apache exposes itself on the default web server port of 80. The <code>EXPOSE<\/code> directive in the <code>Dockerfile<\/code> indicates this. By explicitly exposing the port, you can use the <code>-P<\/code> flag with <code>docker run<\/code> to automatically bind a random host port to the container\u2019s port 80.<\/p>\n<h2 id=\"customising-apache-configuration\"><span class=\"ez-toc-section\" id=\"Customising_Apache_Configuration\"><\/span>Customising Apache Configuration<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The official PHP\/Apache images are based on Debian. You can use the <code>apt<\/code> package manager to add extra software you need.<\/p>\n<p>You\u2019ve also got full access to Apache\u2019s built-in tools. You can use <code>a2enmod<\/code>\/<code>a2dismod<\/code> to manage modules and <code>a2ensite<\/code>\/<code>a2dissite<\/code> to interact with virtual hosts.<\/p>\n<p>The Apache configuration file defaults to <code>\/etc\/apache2\/apache2.conf<\/code>. Add lines to this file, or replace it entirely, to extend the Apache configuration.<\/p>\n<p>One change that\u2019s always worth making is to explicitly set the Apache <code>ServerName<\/code>. This stops the \u201cunable to reliably determine ServerName\u201d warning which usually appears in your container\u2019s logs.<\/p>\n<p>You\u2019ll also usually want to add your own Apache virtual host. This lets you set up custom configuration beyond what the Apache <code>000-default<\/code> site provides. Here\u2019s how to make those changes.<\/p>\n<pre class=\"dockerfile\"><code>COPY my-apache-site.conf \/etc\/apache2\/sites-available\/my-apache-site.conf&#13;\n&#13;\nRUN echo \"ServerName localhost\" &gt;&gt; \/etc\/apache2\/apache2.conf &amp;&amp;&#13;\n    a2enmod rewrite &amp;&amp;&#13;\n    a2dissite 000-default &amp;&amp;&#13;\n    a2ensite my-apache-site &amp;&amp;&#13;\n    service apache2 restart<\/code><\/pre>\n<p>This example disables the default site, enables the custom site and restarts Apache to apply the changes. The <code>mod_rewrite<\/code> module is enabled too, enabling use of <code>Rewrite<\/code> directives in <code>.htaccess<\/code> files. You may want to enable other modules as well, such as <code>headers<\/code> if your configuration will interact with response headers.<\/p>\n<h2 id=\"adding-php-extensions\"><span class=\"ez-toc-section\" id=\"Adding_PHP_Extensions\"><\/span>Adding PHP Extensions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>PHP Docker images come with extension management utilities built-in. Some extensions are enabled by default \u2013 you can check what\u2019s available by running <code>php -m<\/code> within a running container.<\/p>\n<p>Many common extensions can be installed using <code>docker-php-ext-install<\/code>:<\/p>\n<pre class=\"dockerfile\"><code>docker-php-ext-install pdo_mysql<\/code><\/pre>\n<p>Some extensions need to be configured before they can be installed. You can use <code>docker-php-ext-configure<\/code> to perform pre-install configuration. The available options will vary by extension. Read the extension\u2019s manual page to determine the flags you can supply.<\/p>\n<pre class=\"dockerfile\"><code>RUN docker-php-ext-configure gd --with-jpeg=\/usr\/include\/ &amp;&amp;&#13;\n    docker-php-ext-install gd<\/code><\/pre>\n<p>You can also use extensions distributed via PECL. These extensions require a two-step installation procedure. Install the PECL package first, then use <code>docker-php-ext-enable<\/code> to register the extension with your PHP installation.<\/p>\n<pre><code>RUN apt-get install -y libmcached-dev zlib1g-dev &amp;&amp;&#13;\n    pecl install memcached-3.1.5 &amp;&amp;&#13;\n    docker-php-ext-enable memcached<\/code><\/pre>\n<h2 id=\"php-configuration\"><span class=\"ez-toc-section\" id=\"PHP_Configuration\"><\/span>PHP Configuration<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Docker images are preconfigured to load PHP configuration files found in <code>\/usr\/local\/etc\/php\/conf.d<\/code>. Add your own <code>.ini<\/code> file to this directory. PHP will include its contents at runtime, overwriting any existing values. This is the recommended way to extend the default configuration.<\/p>\n<p>The configuration directory path could change in the future. You can get its current location using the <code>$PHP_INI_DIR<\/code> environment variable. It currently resolves to <code>\/usr\/local\/etc\/php\/conf.d<\/code>.<\/p>\n<h2 id=\"using-composer\"><span class=\"ez-toc-section\" id=\"Using_Composer\"><\/span>Using Composer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Composer isn\u2019t available by default. Composer is a community effort that exists independently of PHP. You need to manually install it if you want to use it in a Docker container.<\/p>\n<p>The best way of using Composer in your builds is to reference the tool\u2019s own Docker image via a multi-stage build. Use <code>COPY --from<\/code> to bring the Composer binary into your PHP container; you can then use Composer as normal to install your project\u2019s dependencies.<\/p>\n<pre class=\"dockerfile\"><code>COPY --from=composer:2 \/usr\/bin\/composer \/usr\/bin\/composer&#13;\nCOPY composer.json composer.json&#13;\nCOPY composer.lock composer.lock&#13;\nRUN composer install --no-dev<\/code><\/pre>\n<p>Using this approach reduces complexity. You don\u2019t need to download and run the Composer installation script. By referencing <code>composer:2<\/code>, Docker will pull the image and then copy out the Composer binary.<\/p>\n<h2 id=\"custom-entrypoint-scripts\"><span class=\"ez-toc-section\" id=\"Custom_Entrypoint_Scripts\"><\/span>Custom Entrypoint Scripts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You might need to use a custom entrypoint script if you want to run application migrations before the main server runtime starts. You can override the container <code>ENTRYPOINT<\/code> to use your own startup sequence.<\/p>\n<p>You can make the container execution continue as normal by executing <code>apache2-foreground<\/code>. This will run Apache in the foreground, preventing the container from exiting after the entrypoint script completes.<\/p>\n<pre class=\"dockerfile\"><code>ENTRYPOINT [\"bash\", \"\/Docker.sh\"]<\/code><\/pre>\n<p><strong><code>Docker.sh<\/code> contents:<\/strong><\/p>\n<pre><code>php app.php my-migration-command    # run migrations&#13;\nservice cron start                  # start some services&#13;\nexec apache2-foreground             # main execution<\/code><\/pre>\n<h2 id=\"conclusion\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Dockerising a PHP web service is straightforward when using the official images. You can readily configure Apache and PHP with extensions and your own configuration files.<\/p>\n<p>You\u2019re most likely to encounter difficulties when trying to use third-party community addons like Composer. These aren\u2019t included by default, so you\u2019ll need to use multi-stage Docker builds or manual installation procedures.<\/p>\n<p>Using Docker gives your application versatility in how and where it\u2019s deployed. With your image, you can spin up a working installation of your site using only <code>docker build<\/code> and <code>docker run<\/code> in your terminal.\n<\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/10528\/how-to-use-docker-to-containerise-php-and-apache\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How to Use Docker to Containerise PHP and Apache \u2013 CloudSavvy IT&#8221; Docker containers make your app portable across environments. Once you\u2019ve got a container image, you can use it anywhere Docker is available. Here\u2019s how to containerise a PHP web application using the Apache server. We\u2019ll use the official PHP Docker image as our&#8230;<\/p>\n","protected":false},"author":1,"featured_media":220990,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/01\/6dc7b5a0.jpeg","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-220989","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/220989","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=220989"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/220989\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/220990"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=220989"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=220989"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=220989"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}