如何在docker容器内重新启动Laravel队列工作人员



我正在制作一个生产docker compose来运行我的Laravel应用程序。它有以下容器(以及其他容器(:

应用程序的
  • php fpm
  • nginx
  • mysql
  • redis
  • 队列工作者(我的php-fpm的副本,加上supervisord(
  • 部署(我的php-fpm的另一个副本,其中安装了Gitlab运行程序,以及node+npm、composer等(

当我推送到我的生产分支时,部署容器内的gitlab运行程序执行我的部署脚本,该脚本构建所有内容,运行composer更新等

最后,我的部署脚本需要重新启动队列工作者容器中的队列工作者。当所有东西都一起安装在VPS上时,这很容易:php artisan queue:restart

但是我如何让部署容器在队列工作者集装箱内运行该命令

潜在解决方案

我的研究表明,容器基本上不应该相互交谈,但如果必须的话,我已经找到了四种可能的解决方案:

  1. 在两个容器中安装SSH
  2. 部署容器共享docker.sock,以便它可以通过docker控制其他容器
  3. 队列工作者容器监视文件系统中的一个目录;更改后,重新启动队列工作程序
  4. 容器与队列工作者容器中的小型http服务器之间进行通信

出于复杂性和安全性的原因,我确实希望分别避免1和2。

我倾向于3,但担心监控fs会浪费资源。有没有一种真正轻量级的方法可以监视一个目录,其中的文件数量与Laravel安装的文件数量一样多?

4看起来有点疯狂,但确实做得很好。是否有任何真正微小、简单的http服务器可以安装到队列工作者容器中,当部署集装箱到达端点时,这些服务器可以触发单个命令?

我希望能得到其他建议,或者如果真的没有比上面的3或4更好的方法,希望能得到关于如何实施这两个选项的任何建议

删除现有容器并创建新容器。

容器基本上是单个进程的包装器,因此这类似于使用Ctrl+Ckill(1(停止工作程序,然后重新启动它们。对于后台工作人员来说,这不应该干扰他们当前的任务,Docker给了他们一个在被杀之前完成工作的机会。

由于Docker映像中的代码是固定的,因此当CI系统生成新映像时,您需要删除并重新创建容器,以便使用新映像运行它们。在您的设计中;"部署";容器需要访问主机的Docker套接字(选项#2(才能执行任何与Docker相关的操作。我可能会在不同的系统上运行实际的构建序列,并通过Docker注册表推送映像,但从根本上讲,作为部署过程的一部分,需要在目标系统上sudo docker-compose ...

一个简单的基于Compose的解决方案是给每个图像一个唯一的标签,然后将其作为环境变量传递:

version: '3.8'
services:
app:
image: registry.example.com/php-app:${TAG:-latest}
...
worker:
image: registry.example.com/php-worker:${TAG:-latest}
...

然后,您的部署只需要使用新标签重新运行docker-compose up

ssh root@production.example.com 
env TAG=20210318 docker-compose up -d

Compose将负责重新创造已经改变的事物。

我相信@David Maze的回答是推荐的方式,但我决定发布我最终所做的事情,以防对任何人都有帮助。

我采取了一种不同的方法,因为我在我的容器中运行我的CI脚本,而不是使用Docker注册表&使CI脚本重建图像。

我仍然可以让部署容器访问docker.sock(选项#2(,从而允许我的CI脚本控制docker(例如重建容器等(,但我不喜欢这对安全的影响,所以我最终做了#3,用一个简单的inotifywait监视我在CI脚本中修改的特殊"timestamp.txt"文件中的更改。因为它只监视一个文件,所以它在CPU上运行得很好。

# Start watching the special directory so we know when to restart the workers.
SITE_DIR=/var/www/projectname/public_html
WATCH_DIR=/var/www/projectname/updated_at
while true
do
inotifywait -e create -e modify $WATCH_DIR
if [ $? -eq 0 ]
then
echo "Detected Site Code Change. Executing artisan queue:restart."
sudo -H -u www-data php $SITE_DIR/artisan queue:restart
fi
done

所有部署脚本必须做的触发队列:重新启动是:

date > $WATCH_DIR/timestamp.txt

最新更新