How to Use Docker to Containerise PHP and Apache – CloudSavvy IT


    Docker containers make your app portable across environments. Once you’ve got a container image, you can use it anywhere Docker is available. Here’s how to containerise a PHP web application using the Apache server.

    We’ll use the official PHP Docker image as our base. Variants preconfigured with Apache are provided, so you won’t need to install the web server yourself. The PHP base image also offers convenience utilities for managing PHP extensions.

    Creating a Dockerfile

    Docker images are created from a Dockerfile. This file contains instructions which are used to build the image. Instructions include COPY, to copy files and folders into the container, and RUN, which runs a command within the container.

    You can get a simple PHP site running by simply copying its files into an image based on php:8.0-apache.

    FROM php:8.0-apache
    WORKDIR /var/www/html
    
    COPY index.php index.php
    COPY src/ src
    EXPOSE 80

    This Dockerfile takes index.php and src 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’d see your site being served by Apache.

    docker build -t my-php-site:latest .
    docker run -d -p 80:80 my-php-site:latest

    The PHP Docker images have the Apache document root at the default Debian location of /var/www/html. The WORKDIR instruction in the Dockerfile means subsequent commands will be executed within the document root.

    Apache exposes itself on the default web server port of 80. The EXPOSE directive in the Dockerfile indicates this. By explicitly exposing the port, you can use the -P flag with docker run to automatically bind a random host port to the container’s port 80.

    Customising Apache Configuration

    The official PHP/Apache images are based on Debian. You can use the apt package manager to add extra software you need.

    You’ve also got full access to Apache’s built-in tools. You can use a2enmod/a2dismod to manage modules and a2ensite/a2dissite to interact with virtual hosts.

    The Apache configuration file defaults to /etc/apache2/apache2.conf. Add lines to this file, or replace it entirely, to extend the Apache configuration.

    One change that’s always worth making is to explicitly set the Apache ServerName. This stops the “unable to reliably determine ServerName” warning which usually appears in your container’s logs.

    You’ll also usually want to add your own Apache virtual host. This lets you set up custom configuration beyond what the Apache 000-default site provides. Here’s how to make those changes.

    COPY my-apache-site.conf /etc/apache2/sites-available/my-apache-site.conf
    
    RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf &&
        a2enmod rewrite &&
        a2dissite 000-default &&
        a2ensite my-apache-site &&
        service apache2 restart

    This example disables the default site, enables the custom site and restarts Apache to apply the changes. The mod_rewrite module is enabled too, enabling use of Rewrite directives in .htaccess files. You may want to enable other modules as well, such as headers if your configuration will interact with response headers.

    Adding PHP Extensions

    PHP Docker images come with extension management utilities built-in. Some extensions are enabled by default – you can check what’s available by running php -m within a running container.

    Many common extensions can be installed using docker-php-ext-install:

    docker-php-ext-install pdo_mysql

    Some extensions need to be configured before they can be installed. You can use docker-php-ext-configure to perform pre-install configuration. The available options will vary by extension. Read the extension’s manual page to determine the flags you can supply.

    RUN docker-php-ext-configure gd --with-jpeg=/usr/include/ &&
        docker-php-ext-install gd

    You can also use extensions distributed via PECL. These extensions require a two-step installation procedure. Install the PECL package first, then use docker-php-ext-enable to register the extension with your PHP installation.

    RUN apt-get install -y libmcached-dev zlib1g-dev &&
        pecl install memcached-3.1.5 &&
        docker-php-ext-enable memcached

    PHP Configuration

    The Docker images are preconfigured to load PHP configuration files found in /usr/local/etc/php/conf.d. Add your own .ini 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.

    The configuration directory path could change in the future. You can get its current location using the $PHP_INI_DIR environment variable. It currently resolves to /usr/local/etc/php/conf.d.

    Using Composer

    Composer isn’t 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.

    The best way of using Composer in your builds is to reference the tool’s own Docker image via a multi-stage build. Use COPY --from to bring the Composer binary into your PHP container; you can then use Composer as normal to install your project’s dependencies.

    COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
    COPY composer.json composer.json
    COPY composer.lock composer.lock
    RUN composer install --no-dev

    Using this approach reduces complexity. You don’t need to download and run the Composer installation script. By referencing composer:2, Docker will pull the image and then copy out the Composer binary.

    Custom Entrypoint Scripts

    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 ENTRYPOINT to use your own startup sequence.

    You can make the container execution continue as normal by executing apache2-foreground. This will run Apache in the foreground, preventing the container from exiting after the entrypoint script completes.

    ENTRYPOINT ["bash", "/Docker.sh"]

    Docker.sh contents:

    php app.php my-migration-command    # run migrations
    service cron start                  # start some services
    exec apache2-foreground             # main execution

    Conclusion

    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.

    You’re most likely to encounter difficulties when trying to use third-party community addons like Composer. These aren’t included by default, so you’ll need to use multi-stage Docker builds or manual installation procedures.

    Using Docker gives your application versatility in how and where it’s deployed. With your image, you can spin up a working installation of your site using only docker build and docker run in your terminal.



    Source link