Laravel 是 PHP 的一个 WEB 框架,部署操作有些复杂,且 PHP 不像 node.js 服务器和解释器在一块,而是分开的。

Composer 是包管理器,Laravel Artisan 是 Laravel 框架的工具,和数据库连接以及写入数据库初始数据等。

共需要六个容器。

首先创建一个 docker-compose 配置整个项目的运行:

version: '3.8'
 
services:
    server:
    php:
    mysql:
    composer:
    laravel:
    npm:

ngnix server

services:
    server:
        image: "nginx:stable-alpine"
        ports:
            - "7749:80"
        volumes:
           - "./nginx/nginx.conf:/etc/nginx/nginx.conf:ro"

使用官方的轻量镜像并开放端口以及配置 nginx,其中配置如下:

server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    root /var/www/html/public;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:3000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

php 解释环境

官方的php镜像会默认持续运行一个解释环境,当nginx请求时会自动处理,因此不需要我们写 CMD 或者 ENTRYPOINT,创建一个 php.dockerfile 文件配置镜像:

FROM php:8.2-fpm-alpine
 
WORKDIR /var/www/html
 
RUN docker-php-ext-install pdo pdo_mysql

其中 WORKDIR 是 Nginx 中设定的网站目录,RUN 指令安装了一些 php 扩展。

然后是 docker-compose

services:
    php:
        build:
            context: ./dockerfiles
            dockerfile: php.dockerfile
        volumes:
            - ./src/:/var/www/html:delegated

这里改了dockerfile名字所以需要 配置上下文,之后使用 bind mounts 来将之后会生成的代码同步到宿主机以便进一步修改,delegated 是一个优化参数,让双方的同步操作不那么频繁。

端口的话由于是 nginx 去和 php 交互,我们宿主机并不需要访问,故不需要设置,但得修改 nginx 配置,将 php:3000 替换为 php:9000 因为官方的php镜像默认是在 9000 端口。

mysql

services:
    mysql:
        image: "mysql:5.7"
        env_file:
            - ./env/mysql.env

其中 env 文件内容:

MYSQL_DATABASE=homeset
MYSQL_USER=admin
MYSQL_PASSWORD=admin
MYSQL_ROOT_PASSWORD=admin

composer

作为 Utility Container 不仅需要被 Laravel 使用,也会用于最开始设置项目初始化架构。

首先创建对应的 dockerfile:

FROM composer:latest
 
WORKDIR /var/www/html
 
ENTRYPOINT [ "composer", "--ignore-platform-reqs" ]

以及 docker-compose:

services:
    composer:
        build:
            context: ./dockerfiles
            dockerfile: composer.dockerfile
        volumes:
            - ./src:/var/www/html

之后用 composer 先创建项目代码框架:

docker-compose run --rm composer create-project --prefer-dist laravel/laravel .

执行后会在本地 src 目录下生成项目文件,我们需要进一步修改 .env 文件来指定数据库:

而由于PHP代码是由 nginx 处理并交给 php 解释器处理,所以需要在项目目录中也加入代码目录:

services:
    server:
        image: "nginx:stable-alpine"
        ports:
            - "7749:80"
        volumes:
            - "./nginx/nginx.conf:/etc/nginx/nginx.conf:ro"
            - "./src:/var/www/html"

这里不需要写 public,因为src下本身就有一个 public, 复制过去会直接替代。

至此就可以先运行服务器了,可以直接使用 docker-compose up 来全部运行,但 composer 是工具容器不是必要的,因此可以使用:

docker-compose up -d server php mysql

或者直接设定 server 依赖于 phpmysql,然后只需要启动 server 即可。

不过运行之后会发现报错,Failed to open stream: Permission denied,即 laravel 没有使用 /var/www/html 目录的权限,这是因为在 docker 管理中,每个容器程序的权限是独立的,需要在 PHP 容器中对文件夹开放:

FROM php:8.2-fpm-alpine
 
WORKDIR /var/www/html
 
RUN docker-php-ext-install pdo pdo_mysql
 
RUN chown -R www-data:www-data /var/www/html