· web development · 4 min read

Dockerize your PHP application with Nginx and PHP8-FPM

How do I build a small web server with Nginx and PHP8 FPM using Docker Compose?

Dockerize PHP apps using Nginx & PHP8-FPM! Build a web server with Docker Compose, leveraging official PHP & Nginx repositories.

If you’re new to Docker, I recommend reading the numerous “What is Docker?” and “Getting Started with Docker” articles and tutorials before returning here.

Because you’re still reading, I’ll presume you’re familiar with Docker and wish to run your PHP applications in containers. After all, who wants to deal with installing all of the dependencies on their own workstation or managing a slew of virtual machines for their numerous projects?

We will deploy a simple PHP application using the official Docker repositories for PHP and Nginx. There are several Docker repositories that combine PHP-FPM with Nginx, but if you rely only on the official repositories, you are absolutely on the safe side and right way.

First, install Docker on your machine if you haven’t already done so. The second requirement is to install Docker Compose. We have our necessary tools and the target in mind.

Nginx setup

Based on our requirements, Nginx will be a container. This container will run the official Nginx image. Since we are using Docker Compose, we will now create the following docker-compose.yml file. This YAML will run the latest Nginx image and set port 80 to port 8080:

version: '3.9'

services:
  web:
    image: nginx:latest
    ports:
      - '8080:80'

Now we can run the container.

docker-compose up

Now you should see the welcome page of Nginx on port 8080 via localhost or the IP of your local machine, via a browser of your choice.

Now that we have a running web server, let’s configure it a bit more. First, we need to update the docker-compose.yml file to mount a local directory that we need inside our Nginx container. I’ll use a folder called src, which is in the same directory as our docker-compose.yml file.

version: '3.9'

services:
  web:
    image: nginx:latest
    ports:
      - '8080:80'
    volumes:
      - ./src:/var/www/html

The next step is to let Nginx know that this folder exists.

Let’s create the following default.conf at the same level as the docker-compose.yml file:

server {
    index index.html;
    server_name phpfpm.local;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html;
}

We’ll take a look at what we’re doing here in the first place. The index.html will be our default index, the server name is phpfpm.local and it should point (Update your hosts file if necessary) to your Docker environment (Linux: localhost, Mac or Windows: Local IP). We still set the logs in case of access or error, so that later we can see the logs in our Docker compose log as well. Finally, we specify the root folder that we mounted in the container.

For this extension to take effect, we need to make one more change to our docker-compose.yml file:

version: '3.9'

services:
  web:
    image: nginx:latest
    ports:
      - '8080:80'
    volumes:
      - ./src:/var/www/html
      - ./default.conf:/etc/nginx/conf.d/default.conf

This adds the default.conf to the directory where Nginx looks for configuration files to include. You can now place an index.html file with any content in the src folder.

We start our container again:

docker-compose up

Now look at the content of the index.html in your browser under phpfpm.local:8080.

Add PHP FPM

Now that our Nginx web server is up and running, we can bring PHP into play. First, we get the official PHP8-FPM repo and link it to our Nginx container.

The following should be noted: PHP runs in its own environment (container) and has no access to the code. We need to mount the src folder in the PHP container as well. This way Nginx will be able to serve all static files and PHP will be able to find its files to interpret.

Our docker-compose.yml should now look like this:

version: '3.9'

services:
  web:
    image: nginx:latest
    ports:
      - '8080:80'
    volumes:
      - ./src:/var/www/html
      - ./default.conf:/etc/nginx/conf.d/default.conf
    links:
      - php-fpm
  php-fpm:
    image: php:8-fpm
    volumes:
      - ./src:/var/www/html

Next, you need to configure Nginx to use the PHP FPM container to interpret PHP files.

Our updated default.conf:

server {
    index index.php index.html;
    server_name phpfpm.local;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

To test our changes, we rename the index.html file to index.php and replace its contents:

<?php
echo phpinfo();

And last but not least.

docker-compose up

We go back to our browser. After a refresh, we see the coveted PHP info.

Now you can run any simple PHP application using Docker containers, using the official images for Nginx and PHP.

You can find the example project here: https://github.com/IshtarStar/docker-compose-nginx-phpfpm

This guide and configuration, should never be used on a production server and is not an example of best practice. This post is intended as an introduction to Docker Compose for beginners.

you want to make a local domain on your private network accessible to other devices or services, carefully read this article: How to easily assign a static local domain to a Raspberry Pi?

Back to Blog