如何正确配置docker中的supervisor

I have a working laravel environment using docker. my projects has multiple services in different container such as redis, mongodb, mysqldb and nodejs. I want to use supervisor on my project to interact with redis for the queues and php to run the job. I have done some testing and research but I really can't make it work.

so here is my DockerFile:

FROM php:7.3-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    mariadb-client \
    libpng-dev \
    libzip-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    cron \
    supervisor

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd
RUN docker-php-ext-configure bcmath --enable-bcmath
RUN docker-php-ext-install bcmath

# install mongodb ext
RUN pecl install mongodb \
    && docker-php-ext-enable mongodb

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy supervisor configs
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

CMD ["/usr/bin/supervisord"]

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

and my docker-compose.yml file

version: '3'
services:

  #PHP Service
  php:
    build:
      context: .
      dockerfile: Dockerfile
    image: digitalocean.com/php
    container_name: php
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: php
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes:
      - ./:/var/www
      - ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
      - ./supervisord.conf:/etc/supervisor/conf.d/supervisord.conf
    networks:
      - app-network

  #NODEJS Service
  nodejs: 
    image: node:10
    container_name: nodejs
    restart: unless-stopped
    working_dir: /var/www
    volumes:
      - ./:/var/www
    tty: true
    networks:
      - app-network

  #Nginx Service
  nginx:
    image: nginx:alpine
    container_name: nginx
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./:/var/www
      - ./nginx/conf.d/:/etc/nginx/conf.d/
    networks:
      - app-network

  #MySQL Service
  mysqldb:
    image: mysql:5.7.22
    container_name: mysqldb
    restart: unless-stopped
    tty: true
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USERNAME}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
    volumes:
      - dbdata:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
    networks:
      - app-network

  #MongoDB Service
  mongodb:
    image: mongo:3
    container_name: mongodb
    restart: unless-stopped
    tty: true
    ports: 
      - "27017:27017"
    networks: 
      - app-network

  #Redis Service
  redis:
    image: redis
    container_name: redis
    restart: unless-stopped
    tty: true
    ports: 
      - "${REDIS_PORT}:6379"
    networks:
      - app-network

#Docker Networks
networks:
  app-network:
    driver: bridge

#Volumes
volumes:
  dbdata: 
    driver: local

you might also want to see my supervisord.conf

[supervisord]
user=www
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/var/run/supervisord.pid
loglevel = INFO

[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700
username=www
password=www

[supervisorctl]
serverurl=unix:///var/run/supervisord.sock
username=www
password=www

[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface

[program:php-fpm]
command = /usr/local/sbin/php-fpm
autostart=true
autorestart=true
priority=5
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:ohwo-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/artisan horizon
autostart=false
autorestart=true
user=www
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/laravel-worker.log

so from that setup. when the containers is UP it seems that supervisord is not working because if I run php artisan horizon manually on my php container the queuing works perfectly. btw horizon is the tool i use for queuing.

and then I also try to run supervisorctl on my php container and I got this error unix:///var/run/supervisord.sock no such file

so I'm just pretty new to docker just started few months ago. I do know how to configure supervisord on linux but i can't make it work on docker.

so please pardon my stupidity :)

dttwois6098
dttwois6098 所以我做错了?我该怎么办?我应该把主管放在不同的容器上吗?
大约一年之前 回复
dovzrfr0506
dovzrfr0506 请记住,Docker方法是让多个容器各有一个进程,而不是某个容器本身管理多个进程。这增加了一个与许多容器管理工具不兼容的层。
大约一年之前 回复
douhang1913
douhang1913 没有问题:你应该把#Clear缓存的代码放在上一个RUN命令中,因为docker会创建一个新的层将所有这些文件。如何通过错误增加您的泊坞窗图像的经典问题
大约一年之前 回复

2个回答



这里的想法是消除主管,而是运行主管用于在几个不同容器中运行的任何东西。 您可以使用 docker-compose </ code>轻松编排它,例如,所有运行相同的容器,使用不同的 CMD </ code>覆盖,或者使用不同的 CMD覆盖相同的容器</ 代码>最后一层将它拆分出来。 这里的问题是主管将无法将其管理的进程的状态传达给Docker。 即使它的所有进程都完全被破坏,它也将永远“活着”。 直接暴露这些意味着你会看到它们崩溃。</ p>

最好将每个服务分解为单独的容器。 由于有 MySQL 等正式预建的,因此没有理由自己构建一个 。 您要做的是将 supervisord </ code>配置转换为 docker-compose </ code>格式。</ p>

使用单独的容器,您可以执行以下操作: 代码> docker ps </ code>以查看您的服务是否正常运行,它们都将单独列出。 如果你需要升级一个,那么你就可以轻松地做到这一点,你只需使用那个容器,而不是必须完成整个过程。</ p>

你在这里攻击它的方式 正在将Docker视为一个奇特的虚拟机,实际上并非如此。 它是一个进程管理器</ em>,其中这些进程碰巧有预先构建的磁盘映像和围绕它们的安全层。</ p>

构建您的环境 从单一进程容器中,从维护角度和监视角度来看,您的生活将更加轻松。</ p>

如果您可以将此配置表达为 docker-compose < / code>可以处理,然后你更接近于转向更复杂的管理层,如Kubernetes,这可能是这次特定迁移的逻辑结论。</ p>
</ div>

展开原文

原文

The idea here is to eliminate the supervisor and instead run whatever the supervisor used to run in several different containers. You can easily orchestrate this with docker-compose, for example, all running the same container with different CMD overrides, or the same container with a different CMD layer at the end to split it out. The trouble here is the supervisor won't be able to communicate the status of the processes it manages to Docker. It will always be "alive" even if all of its processes are completely trashed. Exposing those directly means you get to see they crashed.

What's best is to break out each of these services into separate containers. Since there's official pre-built ones for MySQL and so on there's really no reason to build one yourself. What you want to do is translate that supervisord config to docker-compose format.

With separate containers you can do things like docker ps to see if your services are running correctly, they'll all be listed individually. If you need to upgrade one then you can do that easily, you just work with that one container, instead of having to pull down the whole thing.

The way you're attacking it here is treating Docker like a fancy VM, which it really isn't. What it is instead is a process manager, where these processes just so happen to have pre-built disk images and a security layer around them.

Compose your environment out of single-process containers and your life will be way easier both from a maintenance perspective, and a monitoring one.

If you can express this configuration as something docker-compose can deal with then you're one step closer to moving to a more sophisticated management layer like Kubernetes which might be the logical conclusion of this particular migration.

douzhimao8656
douzhimao8656 感谢这个想法,虽然它没有直接回答它解决我的问题的问题。 所以现在我不再担心主管了:D
大约一年之前 回复
doutan3040
doutan3040 例如,从这个PHP容器和此Node容器开始,作为两个构建的基础。 这些都为各自的环境提供了干净整洁的东西。 如果你需要它,可能有一个预先构建的容器,或者足够接近一些RUN命令可以解决它。
大约一年之前 回复
doutang6819
doutang6819 重点是构建您的PHP(和Node?)容器,然后使用预先构建的官方容器分层,其中必要的配置作为环境设置传入。 这意味着您可以选择每个依赖项的特定版本,而不是卡在您的发行版附带的任何内容中。
大约一年之前 回复
douyuanqia665858
douyuanqia665858 我想如果你想有效地使用Docker,你需要放弃一些先入之见,其中之一就是像这样的systemd和服务管理器。 让Docker为您做到这一点。 这就是它的用途。 用一堆内部流程制作这样的容器太复杂了。 将其拆分为一堆单用途容器。 这很烦人但从长远来看会更容易,特别是如果你可以使用现成版本的MySQL,MongoDB等。
大约一年之前 回复
doubi7346
doubi7346 所以你认为在我的php容器上运行php artisan horizo​​n比安装supervisord更好吗?
大约一年之前 回复
dps123456789
dps123456789 我也不太确定。 但我只想让我的php容器上的supervisord工作。 是的我同意我做错了但我找不到任何关于在不同容器上工作supervisord的资源。
大约一年之前 回复



根据官方文档:</ p>

  Dockerfile中只能有一条CMD指令。 如果列出多个CMD,则只有最后一个CMD生效。
</ code> </ pre>

您的Dockerfile有两个CMD命令,因此命令 php-fpm < / code>将覆盖</ p>

  / usr / bin / supervisord 
</ code> </ pre>

这样您就可以执行PHP命令但是 找不到容器中创建的超级用户套接字。</ p>

您可以通过删除与PHP-FPM相关的最后一个CMD命令来修复您的问题,因为您已配置Supervisor启动它并且您的Dockerfile应该 有一个CMD命令:</ p>

  CMD [“/ usr / bin / supervisord”] 
</ code> </ pre>
</ div>

展开原文

原文

According to official documentation:

There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.

And your Dockerfile has two CMD commands so the command php-fpm will override

/usr/bin/supervisord

So that you can execute PHP commands but can't find supervisor's socket created in the container.

You can fix your issue by deleting the last CMD command related to PHP-FPM as you already configured Supervisor to start it and your Dockerfile should have one CMD command:

CMD ["/usr/bin/supervisord"]

dpnhp20440
dpnhp20440 RUN在构建过程中执行命令,但CMD在运行时为容器设置默认命令。
大约一年之前 回复
doujie3888
doujie3888 大。 感谢您的信息..那么如何在RUN / usr / bin / supervisord上运行它呢? 那很好吗? 生病了以后再试
大约一年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐