Docker не запускает контейнер php-cli

149
14 марта 2022, 15:50

Всем привет, подскажите пожалуйста почему не запускается контейнер?

проект на laravel

nginx, php-fpm и тд тут все ок

version: '3' 
services: 
    freelara-nginx: 
        build: 
            context: ./docker 
            dockerfile: nginx.docker 
        volumes: 
            - ./:/app 
            - ./docker/nginx/ssl:/etc/nginx/ssl 
        depends_on: 
            - freelara-php-fpm 
        ports: 
            - "8080:443" 
    freelara-php-fpm: 
        build: 
            context: ./docker 
            dockerfile: php-fpm.docker 
        volumes: 
            - ./:/app 
        depends_on: 
            - freelara-mysql 
    freelara-php-cli: 
        build: 
            context: ./docker 
            dockerfile: php-cli.docker 
        volumes: 
            - ./:/app 
            - composer:/root/.composer/cache 
        depends_on: 
            - freelara-mysql     
 
volumes:     
    composer:

FROM php:7.3-cli 
 
RUN pecl install -o -f redis \ 
    && rm -rf /tmp/pear \ 
    && docker-php-ext-enable redis 
 
RUN apt-get update && apt-get install -y libpq-dev unzip \ 
    && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ 
    && docker-php-ext-install pdo_pgsql \ 
    && pecl install xdebug-2.7.2 \ 
    && docker-php-ext-enable xdebug 
 
RUN docker-php-ext-install mysqli pdo pdo_mysql 
 
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/bin --filename=composer --quiet 
 
ENV COMPOSER_ALLOW_SUPERUSER 1 
 
WORKDIR /app

FROM php:7.3-fpm 
 
RUN pecl install -o -f redis \ 
    && rm -rf /tmp/pear \ 
    && docker-php-ext-enable redis 
 
RUN apt-get update && apt-get install -y libpq-dev \ 
    && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ 
    && docker-php-ext-install pdo_pgsql 
 
RUN docker-php-ext-install mysqli pdo pdo_mysql 
 
WORKDIR /app

FROM nginx:1.15-alpine 
 
ADD ./nginx/default.conf /etc/nginx/conf.d/default.conf 
 
WORKDIR /app

server { 
    listen 443 ssl; 
    index index.php index.html; 
    root /app/public; 
 
    ssl on; 
    ssl_certificate /etc/nginx/ssl/ssl-cert-snakeoil.pem; 
    ssl_certificate_key /etc/nginx/ssl/ssl-cert-snakeoil.key; 
 
    index index.html; 
 
    location / { 
        try_files $uri /index.php?$args; 
    } 
 
    location /docs { 
        try_files $uri $uri/; 
    } 
 
    location ~ \.php$ { 
        fastcgi_split_path_info ^(.+\.php)(/.+)$; 
        fastcgi_pass freelara-php-fpm:9000; 
        fastcgi_index index.php; 
        include fastcgi_params; 
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
        fastcgi_param PATH_INFO $fastcgi_path_info; 
    } 
}

Answer 1

Здесь нужно понимать что такое работающий контейнер. Работающий контейнер это ничто иное как работающий процесс, т.е. активный работающий процесс.

Ну смотрите. Сейчас поймете зачем я делаю вот такие манипуляции:

docker pull php:7.3-fpm

docker inspect php:7.3-fpm

вывожу информацию об образе и нахожу вот это

"Cmd": [
            "php-fpm"
        ]

т.е. при запуске контейнера по-умолчанию запускается php-fpm, но важно понимать что php-fpm висит как процесс и за счет этого живет и сам контейнер.

Дабы убедиться - находим Dockerfile данной сборки

и в самом низу видим что действительно мы запускаем php-fpm.

Однако я могу запустить контейнер изменяя точку входа

docker run -ti --entrypoint /bin/bash php:7.3-fpm

и вот я попадаю в контейнер.

и прям тут мы можем выполнить php-fpm и увидим что действительно процесс работает

[28-Jan-2020 09:55:17] NOTICE: fpm is running, pid 12
[28-Jan-2020 09:55:17] NOTICE: ready to handle connections

Теперь давайте посмотрим что же касается php-cli Чтоб сократить время - вот ссылка на 7.3-cli образ и мы видим что по-умолчанию запускается php -a при старте контейнера. Это интерактивная консоль, однако ежели вы запустите данный контейнер docker run php:7.3-cli то вы увидите в выводе

Interactive shell

и все, контейнер перестал работать. Все дело в том что при php -a не запускается ни какой демон, а в силу того что вы запустили контейнер без ключей -ti то и к контейнеру не подключается STDIN и процесс php shell как открывается так сразу и закрывается.

Резюмируя я хочу сказать что на самом деле у вас запускается php-cli контейнер строго в соответствии вашего docker-compose файла, вы даже чтобы убедиться можете посмотреть docker ps -a и увидите остановленный контейнер php-cli (по крайней мере должны), но он останавливается т.к. останавливается пораждающий его процесс и это стандартное поведение контейнеров.

Дополню ответ по поводу запуска консольных комманд.

Говорить о том что контейнер для консольных комманд должден быть все время запущен, скорее всего не приходится. По сути вам нужно запустить контейнер по мере надобности и при выходе из него его потушить. Соответственно так как у нас (у вас) cli контейнер живет во время работы какого либо процесса, а в данном конкретном случае это будет процесс bash, то при разлогинивании контейнер остановится. Соответственно при повторном запуске поднимется ровным счетом тот же контейнер, осталось только правильно все это описать.

Основную сложность всегда представляло из себя именно то, как связать друг с другом контейнеры, чтоб они друг друга видели и взаимодействовали. Если раньше (сейчас deprecated) использовалсь link в docker-compose и возможно при вынесении какого либо сервиса в другой docker-compose файл было проблематично, то сейчас это не составляет проблем используя network. Теперь от теории к практике.

Чтобы сделал я.

Я бы создал cli-compose.yml где описал бы отдельно сервис freelara-php-cli и соответственно вынес бы его из docker-compose.yml существующего

Нужно добавить network c одинаковым именем во все сервисы. (и в новый файл тоже)

version: '3.5'
  services:
    freelara-nginx:
      build:
        context: ./docker
        dockerfile: nginx.docker
      volumes:
        - ./:/app
        - ./docker/nginx/ssl:/etc/nginx/ssl
      depends_on:
        - freelara-php-fpm
      ports:
        - "8080:443"
      networks:
        - mynetwork
    freelara-php-fpm:
      build:
        context: ./docker
        dockerfile: php-fpm.docker
      volumes:
        - ./:/app
      depends_on:
        - freelara-mysql
      networks:
        - mynetwork
volumes:
  composer:
networks:
  mynetwork:
    name: freelara-network
    driver: bridge

Ну и соответственно файл cli-compose.yml

version: '3.5'
services:
  freelara-php-cli:
    build:
        context: ./docker
        dockerfile: php-cli.docker
    volumes:
        - ./:/app
        - composer:/root/.composer/cache
        networks:
            - mynetwork
volumes:    
    composer:
networks:
    mynetwork:
        name: freelara-network
        driver: bridge

Собственно дело осталось за малым - нужно запустить все это хозяйство. Сервисы из docker-compose.yml вы запускаете как обычно - docker-compose up -d , а вот сервис консольный вы запускаете в два этапа, во первых вам нужно собрать сервис

docker-compose -f ./cli-compose.yml build

И наконец для того чтобы вы запустили bash или любую другую команду

docker-compose -f ./cli-compose.yml run freelara-php-cli bash

где вы видите имя сервиса который запускается и команду, которую вы хотите запустить. Можете например

docker-compose -f ./cli-compose.yml run freelara-php-cli php -r 'phpinfo();'

И зная вот все это дело, вы можете сделать alias и запускать в нужный момент любую консольную комманду через алиас, что то типа

dcli ls -lah где dcli - алиас для docker-compose -f ... и так далее, но это возможно лишнее.

Надеюсь я достаточно понятно описал происходящее. Старался как мог. :)

READ ALSO
Как использовать Express js? Вывод базы данных mysql в HTML

Как использовать Express js? Вывод базы данных mysql в HTML

Пишу сайтДелаю всё по информации в интернете и урокам

124
Виснет ие при использование яндекс карты более 600 меток

Виснет ие при использование яндекс карты более 600 меток

Подвисают браузера при отрисовке объектов на яндекс карте, объединили их в кластера, но Internet Explorer виснет само страшноЧто можно сделать? Вот...

145
Проверка на целое число JS

Проверка на целое число JS

Вступление: Писал проверку на то что вводит пользователь, реализовывал через input type = 'text', однако потом решил попробовать через prompt и результат...

299