×

Docker+PHP+Nginx

2020-11-28 22:00:44 Falcon

Key Takeways

  • File permission is the pain in docker development, better to change default user in php-fpm
  • Be careful with $document_root in nginx configuration, maybe no need to use it
  • sudo docker exec -it {container name} sh/bash: enter into running container

Recently, I have been studying how to use docker as development enviroment, and I find there are some important info for beginners to know. This tutorial mainly aims to show how to combine docker, PHP-fpm and Nginx, and the tricky part behind it. It's not complete, also won't start from the basics.

All the example code is shown in git repo, you can pull it from the following link.
Example

Concept Model

Concept Model

As the above picture shows, all we need to do is to mount the php project file(I use laravel file) to right mount point of php container and nginx container, which both are generated from their image, and link them together correctly.
The tricky part behind this is to find right mount point and give file right permission, and how we use docker command to check and debug.

Project Structure

laravel/
|—— laravel project files
|    |___app files
|—— docker-compose.yml
|—— nginx.conf
|—— www.conf

Start Building

The essential part is 'docker-compose.yml', I write it like this:

docker-compose.yml

version: '3'
services:
  php-fpm:
    image: php:7.2-fpm-alpine
    container_name: php-fpm
    volumes:
      - .:/var/www/html
      - ./www.conf:/usr/local/etc/php-fpm.d/www.conf
    ports:
      - 9000:9000

  nginx:
    image: nginx
    container_name: nginx
    depends_on:
      - php-fpm
    ports:
      - 8888:8888
    volumes:
      - .:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/conf.d/default.conf

Docker Compose is a tool for defining and running multi-container Docker applications, and 'docker-compose.yml' is file to configure it.

  • version: '3' is the newest and most recommended version of the docker-compose engine
  • Services, I define 'php-fpm' and 'nginx' service below it
  • volumes specifies a mount point in container where the code will reside
  • port, I expose '8888' instead of default '80' for nginx
  • depends on tells docker to start 'php-fpm' before 'nginx'

Now inside the laravel directory, I run the command sudo docker-compose up, it's running!!! And go into '0.0.0.0:8888' in browser, there is laravel homepage!

So where is the tricky part? Let me break dowm.

Two tiny detail: I add 'nginx.conf' to mount point: '/usr/local/etc/php-fpm.d/www.conf', and 'nginx.conf' to '/etc/nginx/conf.d/default.conf', they are the key.

nginx.conf configuration file

While the container is running, executes the command sudo docker exec -it nginx sh, we enter into the 'nginx' container. With cat /etc/nginx/conf.d/default.conf command, you can see the nginx configuration, which is exactly as the './nginx.conf', I edit 'nginx.conf' and use it cover the default conf file. Cause I expose port 8888 for nginx, so in 'nginx.conf', I edit listen port to 8888.

And in 'nginx.conf', at line 37, I use fastcgi_param SCRIPT_FILENAME /var/www/html/public$fastcgi_script_name, instead of fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name as line 36. $document_root means the 'root' in nginx.conf, which is /usr/share/nginx/html/public in my case. The fastcgi_param parameter would be used by php-fpm as filepath in its own container, however, as 'docker-compose.yml' shows, the mount point in php-fpm is /var/www/html not /usr/share/nginx/html/public. Be careful with this, otherwise you would see 'primary script unkonwn' error in the nginx error log.

www.conf configuration file

The most difficult problem I encounter is file perssion, and this is notorious for docker. You can learn more detail in the article: File Permissions: the painful side of Docker.

In my case, it shows up when laravel tries to mkdir(), the error message is 'perssion denied'. The cause is when php-fpm execute mkdir(), it's executing by it's default user: www-data, but when you go into 'php-fpm' container, check the file perssions under '/var/www/html', they are owned by '1000', why? If I less /etc/passwd in my own computer, not inside container, I would see id 1000 point to myself. So there are two solutions: one to change the permission for project file, another is to change the user in php-fpm. I choose the second.

Service php-fpm defines its user and group in '/usr/local/etc/php-fpm.d/www.conf', so I copy it to my project from the container with command sudo docker cp php-fpm:/usr/local/etc/php-fpm.d/www.conf {path}, and change it to 1000 as line 24 and 26 shows in 'www.conf'. This is why I mount './www.conf' to '/usr/local/etc/php-fpm.d/www.conf' to cover its default configuration.

These are the lesson from my experient with docker, hope it can help you.

本文收录于