在我关于在 Docker 上开发 PHP 的教程系列的这一部分中,我们将重温之前的教程,并在 2022 年更新一些内容。
所有代码示例都在我 在 Github 上的 Docker PHP 教程存储库中公开提供。您可以在part-4-1-docker-from-scratch-for-php-applications-in-2022
找到本教程的分支
Docker PHP 教程的所有已发布部分都收集在Docker PHP 教程的专用页面下 。上一部分是 为 PHP 项目构建 Docker 设置, 下 一部分是2022 年 PHP 8.1 上的 PhpStorm、Docker 和 Xdebug 3。
如果您想继续关注,请订阅RSS 提要 或通过电子邮件在下一部分发布时 获得自动通知:)
目录
- 介绍
- 本地Docker设置
- Docker
- Docker撰写
.docker/.env
文件和所需的 ENV 变量
- 图片
- PHP 图像
- ENV 与 ARG
- 图像命名约定
- 环境和构建目标
- PHP 图像
- Docker撰写
- 生成文件
.make/*.mk
包括- 共享变量:
.make/.env
- 手动修改
- 强制执行所需参数
- Make + Docker = <3
- 确保构建顺序
- 在 docker 容器中运行命令
- 解决权限问题
- PHP POC
- 包起来
介绍
如果您已阅读之前的教程Structuring the Docker setup for PHP Projects ,您可能会遇到一些重大变化。该教程发布于 2 年多前,Docker 已经发展,我对它有了更多的了解。另外,我通过以前的设置收集了实践经验(好的和坏的)。我现在将 基础知识下关于构建容器的大部分要点 视为“不需要”或只是“过度设计/过于复杂”。具体来说:
- 设置时区
- 如果默认值已经是 UTC,则不需要(几乎总是如此)
- 同步共享卷上的文件和文件夹所有权
- 如果文件需要由容器和主机系统修改,这只是一个问题- 这仅与 PHP 容器真正相关
- 此外,我建议添加一个全新的用户(例如
application
)而不是重新使用现有的用户 – 这大大简化了www-data
整个用户设置 - 从现在开始,我们将使用
application
用户名 (APP_USER_NAME
) 和10000
用户 ID (APP_USER_ID
;遵循最佳实践, 不使用低于 10,000 的 UID )
- 修改配置文件
- 只需使用
sed
– 无需专用脚本
- 只需使用
- 安装php扩展
- 查看PHP 图像– 现在将通过
apk add
- 查看PHP 图像– 现在将通过
- 安装常用软件
- 查看PHP 图像– 因为只有一个基础图像,所以不需要专门的脚本
- 打扫干净
- 没有真正的意义,因为“清理文件”已经是前一层的一部分
- 当我们优化图像大小以加快将图像推入/拉出注册表时,我们可能会“把它带回来”
- 为 linux 主机系统提供 host.docker.internal
- 现在可以通过
host-gateway
魔术参考来完成yaml services: myservice: extra_hosts: - host.docker.internal:host-gateway
- 因此,不再需要自定义入口点
- 现在可以通过
本地Docker设置
这部分的目标是介绍一个无需开发工具的本地工作设置。换句话说:我们希望最低限度的东西在本地运行。
主要成分是:
- 和目录中的
make
设置Makefile
.make/
.docker/
目录中的 docker 设置- 一些 PHP 文件充当 docker 设置的端到端功能的 POC
通过查看代码
git checkout part_4_section_1_docker_from_scratch_for_php_applications_in_2022_code_structure
通过初始化它
make make-init
make docker-build
并通过运行它
make docker-up
现在您可以通过http://127.0.0.1访问 Web 界面。下图显示了容器是如何连接的
有关设置的完整测试,另请参阅PHP POC。
Docker
docker设置包括
- 一个 nginx 容器作为网络服务器
- MySQL 数据库容器
- 充当队列的 Redis 容器
- 一个 php 基础镜像,由
- 一个 php 工作容器,通过它产生多个 PHP 工作进程
supervisor
- 一个 php-fpm 容器作为 nginx 容器的后端
- 我们用来运行命令的应用程序容器
- 一个 php 工作容器,通过它产生多个 PHP 工作进程
我们保留.docker/
上一个教程中的目录docker-compose/
, 尽管它会被拆分成images/
如下所示:
.
└── .docker/
├── docker-compose/
| ├── docker-compose.yml
| └── <other docker-compose files>
├── images/
| ├── nginx/
| | ├── Dockerfile
| | └── <other files for the nginx image>
| └── <other folders for docker images>
├── .env
└── .env.example
Docker撰写
所有图像都是通过构建docker-compose
的,因为docker-compose.yml
文件为构建配置提供了一个很好的抽象层。此外,我们还可以使用它来编排容器,即控制卷、端口映射、网络等 – 以及通过docker-compose up
和启动和停止它们docker-compose down
。
仅供参考:尽管这两种方法使用起来都很方便,但我发现它也使设置变得比在生产后期运行时(当我们不再使用时)docker-compose
所需的更复杂 。我认为这里的问题是,一些修改只需要构建,而其他修改只需要运行 – 并且将两者结合在同一个文件中会产生一定量的噪音。但是它就是这样啊。docker-compose
我们使用三个单独的docker-compose.yml
文件:
- Docker-compose.yml
- 包含适用于所有环境的所有信息
- docker-compose.local.yml
- 包含特定于
local
环境的信息,请参阅环境和构建目标
- 包含特定于
- docker-compose-php-base.yml
- 包含构建 php 基础映像的信息,请参阅PHP 映像
.docker/.env
文件和所需的 ENV 变量
在我们的 docker 设置中,我们基本上有 3 种不同类型的变量:
- 取决于单个开发人员的本地设置的 变量,例如
NGINX_HOST_HTTP_PORT
主机上的变量(因为默认的可能已经在使用) - 在多个图像中使用的变量,例如容器文件系统中代码库的位置
- 包含“可能改变”的信息的变量,例如基础图像的确切版本
因为 – 再次 – 我们努力保留单一的事实来源,我们将信息提取为变量并将它们放入.docker/.env
文件中。在一个完美的世界里,我想将这些不同的类型分开在不同的文件中——但docker-compose
只允许一个.env
文件,参见例如这个评论。如果文件不存在,则从.docker/.env.example
.
然后在docker-compose.yml
文件中使用变量。?
我发现总是在变量上使用修饰符是“最不痛苦的”, 这样docker-compose
如果变量丢失就会立即失败。
注意:一些变量在调用时需要通过环境变量传递docker-compose
(即它们是必需的,但未在.env
文件中定义;另请参阅 共享变量:.make/.env
图片
对于MySQL和redis,我们不使用自定义构建的镜像,而是直接使用官方 镜像,并在启动容器时通过环境变量进行配置。在生产中,我们不会对这些服务使用 docker,而是依赖于托管版本,例如
- redis => Memorystore for Redis (GCP)或 ElastiCache für Redis (AWS)
- mysql => Cloud SQL for MySQL (GCP)或 RDS for MySQL (AWS)
其余容器在目录中各自的子目录中定义.docker/images/
,例如nginx
容器的映像是通过Dockerfile
位于 .docker/images/nginx/Dockerfile
.
PHP 图像
我们需要 3 个不同的 PHP 映像(fpm、workers、应用程序)并使用与Structuring the Docker setup for PHP Projects中略有不同的方法:
我们不使用官方的 PHP 基础镜像(即 cli 或 fpm),而是使用“普通”的 alpine 基础镜像并在其中手动安装 PHP 和所需的扩展。这允许我们为所有 PHP 镜像构建一个通用的基础镜像。好处:
- 共享工具和配置的中心位置(不再需要
.shared/
目录) - 推送单个图像时减小图像大小(基础图像被识别为一个层,因此“已经存在”)
- 安装扩展 via
apk add
比via 快很多docker-php-ext-install
这种新方法有两个主要缺点:
- 我们依赖于 PHP(和 PHP 扩展)的高山发布周期
- 镜像构建过程比较复杂,因为我们必须先构建基础镜像,然后才能构建最终镜像
幸运的是,这两个问题都可以很容易地解决:
- codecasts/php-alpine维护一个
apk
存储库,其中包含 alpine 的最新 PHP 版本 - 我们使用专用
make
目标来构建图像而不是docker-compose
直接调用 – 这使我们能够定义“构建顺序”(首先是基础,然后是休息),同时仍然必须作为开发人员只运行一个命令(请参阅确保构建顺序)
ENV 与 ARG
我注意到在多个 PHP 容器中需要一些构建参数,例如在APP_USER_NAME
ENV 变量中定义的应用程序用户的名称。用户名是必需的
- 在基础镜像中创建用户
- 在 fpm 映像中定义运行 fpm 进程的用户(请参阅 参考资料
php-fpm.d/www.conf
) - 在工作映像中定义运行工作进程的用户(请参阅
supervisor/supervisord.conf
)
而不是通过构建参数将名称传递给所有图像,即
services.*.build.args
在docker-compose.yml
文件中明确定义它- 通过在 Dockerfile 中“检索”它
ARG APP_USER_NAME
我选择通过以下方式将用户名作为ENV
基础映像中的变量提供
ARG APP_USER_NAME
ENV APP_USER_NAME=${APP_USER_NAME}
因此能够直接在子图像中访问它,我现在可以写
RUN echo ${APP_USER_NAME}
代替
ARG APP_USER_NAME
RUN echo ${APP_USER_NAME}
我不能 100% 确定我喜欢这种方法,因为我或多或少地以可能不是有意的方式“滥用”ENV 变量(“为什么需要将用户名存储为 ENV 变量?”) -但我也没有看到任何其他实际的缺点。
图像命名约定
为图像定义一个完全限定的名称将使以后引用图像变得更加容易,例如在将它们推送到注册表时。
图像的命名约定是 $(DOCKER_REGISTRY)/$(DOCKER_NAMESPACE)/$(DOCKER_SERVICE_NAME)-$(ENV)
,例如
docker.io/dofroscra/nginx-local
$(DOCKER_REGISTRY)---^ ^ ^ ^ docker.io
$(DOCKER_NAMESPACE)-------------^ ^ ^ dofroscra
$(DOCKER_SERVICE_NAME)-------------------^ ^ nginx
$(ENV)-----------------------------------------^ local
它被用作 的值services.*.image
,例如nginx
services:
nginx:
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/nginx-${ENV?}:${TAG?}
如果您想知道:dofroscra
源于Do cker Fro m Scratch
环境和构建目标
我们的最终目标是我们可以使用的设置
- 地方发展
- 在 CI/CD 管道中
- 在生产中
即使我们努力在这些不同的环境之间实现平等,也会因为根本不同的要求而存在差异。例如
- 在生产中,我想要一个包含源代码的容器,没有任何测试依赖项
- 在CI上,我想要一个包含带有测试依赖项的源代码的容器
- 在本地我想要一个从我的主机安装源代码的容器(包括依赖项)
这通过ENV
环境变量反映出来。我们在两个地方使用它:
参见docker-compose-php-base.yml
文件,例如:
services:
php-base:
image: ${DOCKER_REGISTRY?}/${DOCKER_NAMESPACE?}/php-base-${ENV?}:${TAG?}
build:
dockerfile: images/php/base/Dockerfile
target: ${ENV?}
在同一个 Dockerfile 中使用多个目标使我们能够保持一个共同的基础,但也包括特定于环境的指令。php-base
例如查看镜像的 Dockerfile
ARG ALPINE_VERSION
FROM composer:${COMPOSER_VERSION} as composer
FROM alpine:${ALPINE_VERSION} as base
RUN apk add --update --no-cache \
bash
WORKDIR $APP_CODE_PATH
FROM base as local
RUN apk add --no-cache --update \
mysql-client \
- 它首先定义了一个
base
包含所有环境所需软件的阶段 - 然后定义一个
local
阶段,额外添加一个mysql-client
帮助我们调试连接问题的阶段
构建local
完成后,我们最终得到一个名为的映像,该映像php-base-local
使用local
构建阶段作为目标构建阶段。
生成文件
在下一节中,我将介绍一些命令,例如用于构建和运行容器。老实说,我发现在不必查找确切的选项和论点的情况下牢记它们有点挑战性。在这种情况下,我通常会在我的本地文件中创建一个辅助函数或别名.bashrc
– 但那时团队的其他成员将无法使用它,而且它对于这个项目来说非常具体。
相反,我们将使用一个自记录的 Makefile作为应用程序的中心入口点 。由于 Makefile 往往会随着时间的推移而增长,因此我采用了一些策略来通过包含、共享变量和更好的错误处理来保持它们“健全”。
.make/*.mk
包括
随着时间的推移,make
设置将大幅增长,因此我们将其拆分为目录.mk
中的多个文件.make/
。当我们将它们包含在主路径中时,各个文件都带有一个数字前缀,以确保它们的Makefile
顺序
include .make/*.mk
.
└── .make/
├── 01-00-application-setup.mk
├── 01-01-application-commands.mk
└── 02-00-docker.mk
共享变量:.make/.env
我们尝试在这里提供共享变量,因为我们可以将它们作为前缀传递给单个命令,例如
.PHONY: some-target
some-target: ## Run some target
ENV_FOO=BAR some_command --baz
这将使ENV_FOO
作为环境变量可用于some_command
.
共享变量被不同的组件使用,我们总是试图只维护一个单一的事实来源。一个例子是DOCKER_REGISTRY
我们需要 在文件中定义docker 镜像的镜像名称docker-compose.yml
的变量,以及稍后通过 make 目标推送/拉取/部署镜像时的变量。在这种情况下,变量是make
和 所必需的docker-compose
。
为了清楚地区分变量和“代码”,我们使用.env
位于. make/.env
. 它可以通过初始化
make make-init
通过复制.make/.env.example
到.make/.env
.
.
└── .make/
├── .make/.env.example
└── .make/.env
该文件包含在主Makefile
通过
-include .make/.env
-
前缀确保如果文件不存在(尚),make 不会失败,请参阅 GNU make:包括其他 Makefiles。
手动修改
如果需要,您可以随时手动修改.make/.env
文件。当您docker
在 Linux 上运行并且需要将user id
主机系统的 与 user id
docker 容器的匹配时,可能会出现这种情况。您的本地用户和组通常具有 id 1000
。在这种情况下,您将手动将条目添加到.make/.env
文件中。
APP_USER_ID=1000
APP_GROUP_ID=1000
另请参阅解决权限问题部分。
强制执行所需参数
我们有点“滥用”执行任意命令(而不是构建工件),其中一些命令需要可以 作为命令参数以形式传递的参数
make some-target FOO=bar
没有办法像在方法签名中那样“定义”这些参数 – 但我们仍然可以确保在缺少参数时尽早失败
@$(if $(FOO),,$(error FOO is empty or undefined))
例如,我们使用这种技术来确保在通过validate-docker-variables
前置条件目标执行 docker 目标时定义所有必需的变量:
.PHONY: validate-docker-variables
validate-docker-variables:
@$(if $(TAG),,$(error TAG is undefined))
@$(if $(ENV),,$(error ENV is undefined))
@$(if $(DOCKER_REGISTRY),,$(error DOCKER_REGISTRY is undefined - Did you run make-init?))
@$(if $(DOCKER_NAMESPACE),,$(error DOCKER_NAMESPACE is undefined - Did you run make-init?))
@$(if $(APP_USER_NAME),,$(error APP_USER_NAME is undefined - Did you run make-init?))
@$(if $(APP_GROUP_NAME),,$(error APP_GROUP_NAME is undefined - Did you run make-init?))
.PHONY:docker-build-image
docker-build-image: validate-docker-variables
$(DOCKER_COMPOSE) build $(DOCKER_SERVICE_NAME)
Make + Docker = <3
我们已经在我们的设置中引入了相当多的复杂性:
- “全局”变量(在
make
和之间共享docker
) - 多个
docker-compose.yml
文件 - 构建依赖项
“手动”将它们组合在一起是一项相当大的努力,而且容易出错。但是我们可以.make/02-00-docker.mk
通过定义两个变量 DOCKER_COMPOSE
和DOCKER_COMPOSE_PHP_BASE
DOCKER_DIR:=./.docker
DOCKER_ENV_FILE:=$(DOCKER_DIR)/.env
DOCKER_COMPOSE_DIR:=$(DOCKER_DIR)/docker-compose
DOCKER_COMPOSE_FILE:=$(DOCKER_COMPOSE_DIR)/docker-compose.yml
DOCKER_COMPOSE_FILE_LOCAL:=$(DOCKER_COMPOSE_DIR)/docker-compose.local.yml
DOCKER_COMPOSE_FILE_PHP_BASE:=$(DOCKER_COMPOSE_DIR)/docker-compose-php-base.yml
DOCKER_COMPOSE_PROJECT_NAME:=dofroscra_$(ENV)
DOCKER_COMPOSE_COMMAND:=ENV=$(ENV) \
TAG=$(TAG) \
DOCKER_REGISTRY=$(DOCKER_REGISTRY) \
DOCKER_NAMESPACE=$(DOCKER_NAMESPACE) \
APP_USER_NAME=$(APP_USER_NAME) \
APP_GROUP_NAME=$(APP_GROUP_NAME) \
docker-compose -p $(DOCKER_COMPOSE_PROJECT_NAME) --env-file $(DOCKER_ENV_FILE)
DOCKER_COMPOSE:=$(DOCKER_COMPOSE_COMMAND) -f $(DOCKER_COMPOSE_FILE) -f $(DOCKER_COMPOSE_FILE_LOCAL)
DOCKER_COMPOSE_PHP_BASE:=$(DOCKER_COMPOSE_COMMAND) -f $(DOCKER_COMPOSE_FILE_PHP_BASE)
DOCKER_COMPOSE
使用docker-compose.yml
并扩展它docker-compose.local.yml
DOCKER_COMPOSE_PHP_BASE
仅使用docker-compose-php-base.yml
这些变量可以稍后在制作配方中使用。
确保构建顺序
正如在PHP 图像中提到的,我们需要按照一定的顺序构建图像并使用以下 make 目标:
.PHONY: docker-build-image
docker-build-image: ## Build all docker images OR a specific image by providing the service name via: make docker-build DOCKER_SERVICE_NAME=<service>
$(DOCKER_COMPOSE) build $(DOCKER_SERVICE_NAME)
.PHONY: docker-build-php
docker-build-php: ## Build the php base image
$(DOCKER_COMPOSE_PHP_BASE) build $(DOCKER_SERVICE_NAME_PHP_BASE)
.PHONY: docker-build
docker-build: docker-build-php docker-build-image ## Build the php image and then all other docker images
作为开发人员,我现在可以简单地运行make docker-build
——它将首先通过构建php-base
图像docker-build-php
,然后通过构建所有剩余的图像docker-build-image
(通过不指定DOCKER_SERVICE_NAME
变量,docker-compose
将构建文件中列出的所有docker-compose.yml
服务)。
我认为make 配方本身是非常可读且易于理解的,但是当我们使用 仅“打印将执行的配方,但不执行它”-n
选项运行它们时,我们会感觉到复杂性:
$ make docker-build -n
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose-php-base.yml build php-base
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose.yml -f ./.docker/docker-compose/docker-compose.local.yml build
在 docker 容器中运行命令
工具是开发工作流程中的重要组成部分。这包括诸如 linter、静态分析器和测试工具之类的东西,还包括针对您特定工作流程的“自定义”工具。这些工具通常需要 PHP 运行时。目前,我们在文件中只定义了一个“工具” setup.php
。它确保jobs
创建了一个名为的表。
要运行这个工具,我们必须首先启动 docker setup via make docker-up
,然后在application
容器中执行脚本。相应的目标定义在 .make/01-00-application-setup.mk
:
.PHONY: setup-db
setup-db: ## Setup the DB tables
$(EXECUTE_IN_APPLICATION_CONTAINER) php setup.php $(ARGS);
这基本上转化为
docker-compose exec -T --user application application php setup.php
如果我们在一个容器之外并且
php setup.php
如果我们在一个容器内。这非常方便,因为我们可以直接从主机系统运行工具,而无需登录容器。
“魔术”发生在定义为的EXECUTE_IN_APPLICATION_CONTAINER
变量中 .make/02-00-docker.mk
EXECUTE_IN_WORKER_CONTAINER?=
EXECUTE_IN_APPLICATION_CONTAINER?=
EXECUTE_IN_CONTAINER?=
ifndef EXECUTE_IN_CONTAINER
# check if 'make' is executed in a docker container,
# see https://stackoverflow.com/a/25518538/413531
# `wildcard $file` checks if $file exists,
# see https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html
# i.e. if the result is "empty" then $file does NOT exist
# => we are NOT in a container
ifeq ("$(wildcard /.dockerenv)","")
EXECUTE_IN_CONTAINER=true
endif
endif
ifeq ($(EXECUTE_IN_CONTAINER),true)
EXECUTE_IN_APPLICATION_CONTAINER:=$(DOCKER_COMPOSE) exec -T --user $(APP_USER_NAME) $(DOCKER_SERVICE_NAME_APPLICATION)
EXECUTE_IN_WORKER_CONTAINER:=$(DOCKER_COMPOSE) exec -T --user $(APP_USER_NAME) $(DOCKER_SERVICE_NAME_PHP_WORKER)
endif
我们可以通过-n
再次查看主机系统上已解决的配方
pascal.landau:/c/_codebase/dofroscra# make setup-db ARGS=--drop -n
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose.yml -f ./.docker/docker-compose/docker-compose.local.yml exec -T --user application application php setup.php --drop
在一个容器中,它看起来像这样:
root:/var/www/app# make setup-db ARGS=--drop -n
php setup.php --drop;
解决权限问题
如果您使用的是 Linux,当用户 id 与 上一教程的在共享卷上同步文件和文件夹所有权部分中的说明 不同时,您可能会在修改主机系统和 docker 容器之间共享的文件时遇到权限问题.
在这种情况下,您需要根据本地设置手动修改.make/.env
并添加 APP_USER_ID
和变量。APP_GROUP_ID
这必须 在构建映像之前完成,以确保在映像user id
中使用正确的。
在极少数情况下,它可能会导致问题,因为您的本地 id已经存在于 docker 容器中。我个人从来没有遇到过这个问题,但你可以在Docker 和主机文件系统所有者匹配问题中更详细地了解它 。作者甚至 通过 Github 项目“FooBarWidget/matchhostfsowner”提出了一个通用的解决方案。
PHP POC
为确保一切按预期工作,存储库包含一个最小的 PHP 概念证明。默认情况下,主机的 80 端口被转发到nginx
容器的 80 端口。
仅供参考:我还建议 在主机上的 hosts 文件中添加以下条目
127.0.0.1 app.local
这样我们就可以通过http://app.local而不是http://127.0.0.1访问应用程序。
POC 的文件基本上确保 本地 docker 设置中概述的容器连接按预期工作:
dependencies.php
- 返回配置
Redis
和PDO
对象以与队列和数据库对话
- 返回配置
setup.php
- =>确保
application
可以交谈mysql
- =>确保
public/index.php
- 是可以通过http://app.local访问的 web 根文件
- =>确保
nginx
并且php-fpm
正在工作
- =>确保
- 包含 3 条不同的“路线”:
- http://app.local?dispatch=some-job-id
- 调度一个新的“作业”,队列中的 id
some-job-id
由工作人员拾取- =>确保
php-fpm
可以交谈redis
- =>确保
- 调度一个新的“作业”,队列中的 id
- http://app.local?queue
- 显示队列的内容
- http://app.local?db
- 显示数据库的内容
- =>确保
php-fpm
可以交谈mysql
- =>确保
- 显示数据库的内容
- http://app.local?dispatch=some-job-id
- 是可以通过http://app.local访问的 web 根文件
worker.php
- 在
php-worker
容器中作为守护进程启动 - 每秒检查一次 redis 数据库
0
中的密钥"queue"
- 如果找到一个值,则将其存储在
jobs
数据库的表中- =>确保
php-worker
可以redis
和mysql
- =>确保
- 在
完整的测试场景定义test.sh
如下:
$ bash test.sh
Building the docker setup
//...
Starting the docker setup
//...
Clearing DB
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose.yml -f ./.docker/docker-compose/docker-compose.local.yml exec -T --user application application php setup.php --drop;
Dropping table 'jobs'
Done
Creating table 'jobs'
Done
Stopping workers
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose.yml -f ./.docker/docker-compose/docker-compose.local.yml exec -T --user application php-worker supervisorctl stop worker:*;
worker:worker_00: stopped
worker:worker_01: stopped
worker:worker_02: stopped
worker:worker_03: stopped
Ensuring that queue and db are empty
Items in queue
array(0) {
}
Items in db
array(0) {
}
Dispatching a job 'foo'
Adding item 'foo' to queue
Asserting the job 'foo' is on the queue
Items in queue
array(1) {
[0]=>
string(3) "foo"
}
Starting the workers
ENV=local TAG=latest DOCKER_REGISTRY=docker.io DOCKER_NAMESPACE=dofroscra APP_USER_NAME=application APP_GROUP_NAME=application docker-compose -p dofroscra_local --env-file ./.docker/.env -f ./.docker/docker-compose/docker-compose.yml -f ./.docker/docker-compose/docker-compose.local.yml exec -T --user application php-worker supervisorctl start worker:*;
worker:worker_00: started
worker:worker_01: started
worker:worker_02: started
worker:worker_03: started
Asserting the queue is now empty
Items in queue
array(0) {
}
Asserting the db now contains the job 'foo'
Items in db
array(1) {
[0]=>
string(3) "foo"
}
包起来
恭喜,你成功了!如果现在有些事情还不完全清楚,请不要犹豫发表评论。除此之外,您现在应该有一个正在运行的 docker 设置以及通过make
.
php-on-docker-from-scratch-in-2022