# ul-php-docker-env **Repository Path**: ulthon/ul-php-docker-env ## Basic Information - **Project Name**: ul-php-docker-env - **Description**: 使用docker部署通用php环境的资料。 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2024-10-14 - **Last Updated**: 2025-08-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## ul-php-docker-env 使用 docker 实现通用 php 环境搭建的配置资料。 优先自动化部署的服务器运维方案。 ### 这是什么 - 使用 docker 搭建环境的具体的配置文件(已踩坑) - php 构建 docker 配置 - caddy 服务器配置 - mysql 部署文件 - redis 部署文件 - 项目部署规范指导 - 守护进程 - 日志管理(暂未实现) - 定时任务管理(暂未实现) - 备份方案(暂未实现) - 数据备份 - 程序备份 - 安全规范(未实现) - 接入更多的常见配套服务 - PostgreSQL - MongoDB ### 为什么有这个项目 目前 php 最主流的部署方式就是使用面板,再一个就是把项目打包为的 docker 镜像(参 考 ulthon_admin),不过后者的方式也不是特别主流。 本项目希望实现一套无其他因素的简单好用的部署方式,希望所有的实现方案都是开源的, 可靠地,原始的。 ### 整体说明 #### 设计思路 所有站点(php 或 docker 应用)都是虚拟主机的运维方式实现,只需要对应的应用目录下 配置即可。 #### php 和 web 使用 docker 实现 php 通用环境的配置,使用 caddy 作为 web 服务器,其他服务也都使 用 docker 部署。 #### docker 所有 docker 服务均通过`compose.yaml`启动。 #### 端口 - php 端口规则`9+大版本+0`,如 php74 服务占用`9740`,php81 服务占用`9810`等。 - mysql 端口规则`3+大版本+0`,如 mysql5.7 占用`3570`,mysql8.0 占用`3800`。 - mariadb 端口规则`4+版本+0`,目前只有 10 版本,因此使用`4100`,虽然 mariadb 的 小版本之间也有不同的支持周期和特性,但一般而言他们都是兼容的,无需特别指定。 - redis 使用 6379 端口,一般不会出现多版本的情况。 端口规则保留的 0 是预留的,有必要的话可以改为其他数字。 > 关于端口可以任意分配,比如 mysql 端口是 3306,其他的版本分别是 3307,3308 这样 > 。 每个 docker 服务的目录映射都是 compose 文件的相对目录下。 ### 应用 除了 caddy 和 supervisor 使用原生安装方式,其他的都用 docker 方式部署,无论是基 础服务还是自己的服务。 php 的源码放到/data/projects/\*/site 下。 如果需要自己启动 docker 应用,配置文件或目录放到/data/projects/\*/docker 下。 自己启动的服务,都在/data/projects 下,有对应的 caddy 和 supervisor 配置方式,未 来可能会增加更多的配置方式,比如缓存、定时任务等。 ## 密码 很多配置文件中都有密码,需要手动修改。 ## 目录映射 `/data/projects` 本项目默认把网站放到`/data/projects`中,如需要改动,所有文件都要同步修改。 php-fpm 的工作原理是服务器(nginx、caddy)把请求信息转发到 cgi 上,由于 php 运行 在 docker 中,所以 php 网站的路径和容器需要注意统一。 例如本项目中的 php 的 dockerfile 中,映射`/data/projects`,在宿主机中,实际的代 码就要放到`/data/projects`下,绝对不能放到其他路径。 可能懂 docker 的老师会说,docker 的目录映射是可以随意指定的,我可以把任意的目录 映射到`/data/projects`,难道不是吗?是的,但是服务器在转发到 php 服务的时候,会 把 php 文件的路径一起转发过去,如果 php 代码是其他目录,比 如`/var/www/ulthon.com`,服务器会把`/var/www/ulthon.com`发送到 php-fpm 服务,此 时 php-fpm 就会去`/var/www/ulthon.com`找文件,但实际上,对于 php 的容器,代码不 在`/var/www/ulthon.com`里,而是`/data/projects`,所以会找不到文件。也有解决办法 ,就是配置一下服务器(nginx、caddy)设置文件的路径,但这不就更麻烦了吗。 ## 目录规范 - 在系统中创建一个`/data`目录,本项目所有文件都放在这个目录下 - php 的代码放到/data/projects/\*/site/下,创建一个目录,作为独立的站点 - 系统其他的服务(例如使用 docker 实现邮箱、网盘、博客等支持 docker 配套部署的) ,放到/data/projects/\*/docker ## 镜像 每个镜像都配置了`host.docker.internal`网络,指向宿主机。一般而言使用局域网 ip 也 都能访问到宿主机。内置的 docker 镜像使用 socat 工具转发了指定端口,因此容器里 127.0.0.1 的特定端口也能指向宿主机。 ## caddy 的使用 ### 配置文件 目前已经实现了 php 的、tp 的、跨域的通用配置块,可以直接使用。对于 tp8 的项目, 可直接这样配置: ``` admin.demo.ulthon.com { import tp8 {host} } ``` 这时候只要在 projects 下创建一个名为 admin.demo.ulthon.com 的目录即可。如果 ### 安装部署 [安装文档](./doc/INSTALL.md) ## php 使用 直接到对应目录下执行即可: ```bash docker compose up ``` 该命令会自动根据目录下的 Dockerfile 构建。如果修改了 Dockerfile,需要运行以下命 令强制使用构建。 ```bash docker compose up --build ``` > 只要 Dockerfile 没有变化,虽然仍然重复构建,但各各层都缓存下来,能够很快生成镜 > 像。 当需要使用命令行时,需要这样运行: ```bash docker exec -it php80 php /data/projects/ulthon.com/think ``` 可以运行对应目录下的`alias.sh`,以后可以直接这样运行: ```bash php80 /data/projects/ulthon.com/think ``` > 这里有个隐含的坑和优势,如果你内部代码需要 exec php 命令,直接使用 php,而不能 > 使用 php80。(没办法调用 php81 等其他指令) > 运行后可以通过`/etc/alternatives/php`使用系统原始php 经过测试,虽然宿主机可以快速运行命令,但如果该命令是无限运行的,无限循环或workerman之类的,只能通过用户在终端中运行,不能通过supervisor或php的shell_exec等机制终止。主要原因是运行-it时,无法创建tty终端,如果只使用-i,则无法正确杀死容器内的进程。 因此目前有一个不可破解的局限性,无法提供有效的守护进程方式。 除非采用其他方案, 1:守护进程根据命令特征运行或杀死,不太稳固。 2:在容器内实现守护进程,每个php容器内都能够处理supervisor的配置,但操作起来后,更新守护进程配置变得可能会很复杂,并且只有内置的php的docker服务支持这一特性 3:在容器内自己实现一个进程监控,让其支持快速命令操作。但这个可能会有问题,他们之间是共享配置文件的,可能重复运行,2也有这个问题 3:不再支持通用的php-fpm的服务了,所有的应用都采用独立的docker镜像的方式运行和分发,但这导致php包太大,一个容器可能要600M,并且要求每个项目支持自动构建,除非他们支持同一个镜像,但这不太可能。 4:要求所有的项目都是使用frankenphp,但是frankenphp的本身容器大小和ulthon_admin构建的也差不多,直接替换意义不大,但可以要求都把frankenphp作为独立而二进制来使用,一般只有100M-200M,然后我们针对这个架构出一个统一的镜像,来运行项目。相比3,占用的空间更小 考虑到宿主机调用容器内的长期运行的机制不健全,可以先不考虑这一部分。目前整个使用最终效果,是很方便开发和调试的(composer的问题还没解决)。 后续优先以运行docker为主,让项目自己解决服务、守护进程的问题。 ## 项目管理 ### 创建项目 使用脚本创建站点 ``` php create-project.php [project-name] [type:site|docker] ``` ### 创建站点守护进程命令 ``` php create-project-supervisor.php [project-name] [program-name] [command] [dir|默认项目目录] ``` ### 修改站点守护进程命令 ``` php set-project-supervisor.php [project-name] [program-name] [command] [dir|默认项目目录] ``` ### 创建站点域名配置 ``` php create-project-supervisor.php [project-name] [rule-name] [domain-names] ``` ### 修改站点域名配置 ``` php set-project-supervisor.php [project-name] [rule-name] [domain-names] ``` ### 创建数据库 使用脚本创建数据库 ``` php create-database.php [database-name] [version:57|80] ``` ### 备份程序 包括程序、站点配置、守护进程配置等。 ``` php backup-project.php [project-name] --backup-name=[backup-name|非必填] --backup-point=[backup-point] ``` ### 还原程序 ``` php restore-project.php [project-name] --backup-name=[backup-name|非必填] --backup-point=[backup-point] ``` ### 备份数据库 ``` php backup-database.php [project-name] --backup-name=[backup-name] --backup-point=[backup-point] ``` ### 恢复数据库 ``` php restore-database.php [project-name] --backup-name=[backup-name] --backup-point=[backup-point] ``` ### 备份快照 备份程序和数据库,包装执行程序和数据库备份。可以通过快照功能快速在多个服务器之间迁移项目。 ``` php backup-snapshot.php [project] --backup-name=[backup-name] --backup-point=[backup-point] ``` ### 恢复快照 ``` php restore-snapshot.php [project] --backup-name=[backup-name] --backup-point=[backup-point] ``` ### backup-point 备份的存储位置,项目下的backup目录仅用于临时备份处理文件,不是持久的存储,包括一些配置文件的变动记录的备份。 默认本地存储,/data/backup。 backup-name一般是hostname+时间戳,不能有斜线,一般是时间戳、短横线、下划线。 实际的存储文件名会有`项目名/backup-name`。 所以存储的目录规则是/data/backup/project-name/backup-name。 其中/data/backup是前缀。 可以是远程存储,比如对象存储。 可以设置前缀。如果两个服务器的备份位置是同一个对象存储,且配置一样,则可以快速从一个服务器备份,再从另一个服务器恢复。