如何使用docker docker-compose nginx部署php应用

1.目录结构

我们将使用以下目录结构进行演示:

1
2
3
4
5
6
7
8
9
10
11
12
/data/wwwroot/app
├── docker-compose.yml
├── nginx
│   ├── default.conf
│   └── Dockerfile
├── php
│   └── Dockerfile
└── www
└── html
├── 1.txt
├── index.php
└── phpinfo.php

2.创建 nginx 容器

在开始之前,需要创建并启动一个 Nginx 容器来托管 PHP 应用程序。

首先,使用以下命令为项目创建一个 demo 目录:

1
2
mkdir -p /data/wwwroot/app && cd /data/wwwroot/app
vim docker-compose.yml

docker-compose.yml 添加内容:

1
2
3
4
5
6
7
8
9
10
version: '3'
services:
nginx:
image: nginx:1.20.2
container_name: nginx-container
restart: always
ports:
- 8000:80
environment:
- TZ=Asia/Shanghai

创建一个 nginx 容器,并将其公开在 8000 端口上:

1
docker-compose up -d

可以使用以下命令检查正在运行的容器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker ps 
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
26f3d4a617a1 nginx:1.20.2 "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:8000->80/tcp nginx-container

$ curl 127.0.0.1:8000 -I
HTTP/1.1 200 OK
Server: nginx/1.20.2
Date: Thu, 22 Jun 2023 00:16:52 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 16 Nov 2021 14:44:02 GMT
Connection: keep-alive
ETag: "6193c3b2-264"
Accept-Ranges: bytes

3.创建 php 容器

在 demo 项目中创建一个新的目录,用来存放 php 源码:

1
mkdir -p /data/wwwroot/app/www/html && cd /data/wwwroot/app/www/html

创建几个测试页:

1
2
3
4
5
6
7
8
9
10
11
12
$ cat 1.txt 
111

$ vim index.php
<?php
echo 'We are running PHP, version: ' . phpversion();
?>

$ vim phpinfo.php
<?php
phpinfo();
?>

接下来,创建一个 Nginx 默认配置文件来运行 PHP 应用程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ vim /data/wwwroot/app/nginx/default.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
root /var/www/html;
index index.html index.htm index.php;

location / {
try_files $uri $uri/ /index.php?$query_string;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

接下来,编辑 docker-compose.yml 文件,来增加 php 容器配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3'
services:
nginx:
image: nginx:1.20.2
container_name: nginx-container
restart: always
ports:
- 8000:80
links:
- php
volumes:
- /data/wwwroot/app/www/html:/var/www/html
- /data/wwwroot/app/nginx/default.conf:/etc/nginx/conf.d/default.conf

php:
image: php:7.3.29-fpm
container_name: php-container
restart: always
ports:
- 9000:9000
volumes:
- /data/wwwroot/app/www/html:/var/www/html

使用以下命令启动两个容器:

1
2
cd /data/wwwroot/app
docker-compose up -d

打开浏览器分别验证几个测试页:

1
2
3
http://ip:8000
http://ip:8000/1.txt
http://ip:8000/phpinfo.php

接下来,我们将检查挂载的卷是否有效。为此,请编辑 index.php 文件:

1
2
3
4
$ vim index.php 
<?php
echo 'Hello World!!! We are running PHP, version: ' . phpversion();
?>

现在刷新 http://ip:8000 ,您应该在屏幕上看到修改后的页面:

4.创建数据卷容器

如您所见,我们已经将目录 www/html 挂载到我们的容器 nginx-container 和 php-container 中。但是,这不是正确的方法。

在本节中,我们将创建一个单独的数据容器来保存数据并将其链接到所有其他容器。

为此,请编辑 docker-compose.yml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
version: '3'

services:
nginx:
image: nginx:1.20.2
container_name: nginx-container
restart: always
ports:
- 8000:80
links:
- php
volumes_from:
- app-data

php:
image: php:7.3.29-fpm
container_name: php-container
restart: always
ports:
- 9000:9000
volumes_from:
- app-data

app-data:
image: php:7.3.29-fpm
container_name: data-container
volumes:
- /data/wwwroot/app/nginx/default.conf:/etc/nginx/conf.d/default.conf # nginx vhost
- /data/wwwroot/app/www/html:/var/www/html # project code
command: "true"

现在,使用以下命令重新创建并启动所有容器:

1
2
cd /data/wwwroot/app
docker-compose up -d

现在,使用以下命令验证所有正在运行的容器:

1
2
3
4
5
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4a73a450a36d nginx:1.20.2 "/docker-entrypoint.…" 2 seconds ago Up 2 seconds 0.0.0.0:8000->80/tcp nginx-container
6f7df73269e8 php:7.3.29-fpm "docker-php-entrypoi…" 3 seconds ago Up 2 seconds 0.0.0.0:9000->9000/tcp php-container
0620b3403e63 php:7.3.29-fpm "docker-php-entrypoi…" 3 seconds ago Exited (0) 2 seconds ago data-container

本文仅仅演示了 php + nginx 应用如何在 docker 中的使用。

在真实的生产环境中这些是不够的,我们还需要:

  • 为 php 容器镜像定制符合业务环境的核心扩展、PECL扩展、编译安装扩展等
  • 对 php 容器镜像的 php.ini, www.conf 配置文件进行调优
  • 对 nginx 容器镜像配置进行调优
  • 把 nginx php 容器镜像中产生的日志进行挂载收集
  • 将 业务代码 docker image build 构建进容器镜像,而不是从宿主机挂载
  • 集成进 Jenkins Pipeline 流水线持续集成,持续构建

诸如以上问题一一解决才能够满足真实生产环境的需要。请关注本站关于 php docker 的其他博文,谢谢!

5.参考文献

How to Deploy a PHP Application with Nginx and MySQL Using Docker and Docker Compose
数据卷容器(—volumes-from)
docker-compose volumes_from usage example