Куда положить команду php artisan migrate

Попытка развернуть приложение laravel в стеке докера. Что меня смущает или я не могу понять, это где я могу запустить php artisan migrate:fresh для генерации таблиц, требуемых в mysql.

Услуги и задачи выполняются хорошо

докер-compose.yml

version: '3.3'

networks:
  smstake: 
    ipam:
      config:
        - subnet: 10.0.10.0/24

services:

    db:
        image: mysql:5.7
        networks:
          - smstake
        ports:
          - "3306:3306"
        volumes:
          - db_data:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: smstake
          MYSQL_USER: root
          MYSQL_PASSWORD: password
        deploy:
          mode: replicated
          placement:
            constraints:
              - node.role == manager
    app:

        image: smstake:latest          
        ports:
          - 8000:80
        networks:
          - smstake

        command: docker-compose exec app php artisan migrate --seed
        deploy:
          mode: replicated
          replicas: 1
          placement:
            constraints:
              - node.role == manager
volumes:
    db_data:

Вот докер-файл, с помощью которого генерируется изображение

FROM alpine

ENV \
  APP_DIR="/app" \
  APP_PORT="80"

# the "app" directory (relative to Dockerfile) containers your Laravel app...
COPY app/ $APP_DIR
# or we can make the volume in compose to say use this directory 

RUN apk update && \
    apk add curl \
    php7 \
    php7-opcache \
    php7-openssl \
    php7-pdo \
    php7-json \
    php7-phar \
    php7-dom \
    php7-curl \
    php7-mbstring \
    php7-tokenizer \
    php7-xml \
    php7-xmlwriter \
    php7-session \
    php7-ctype \
    php7-mysqli \
    php7-pdo \
    php7-pdo_mysql\
    && rm -rf /var/cache/apk/*

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

RUN cd $APP_DIR && composer install

WORKDIR $APP_DIR

RUN chmod -R 775 storage
RUN chmod -R 775 bootstrap

#CMD php artisan migrate:fresh
CMD php artisan serve --host=0.0.0.0 --port=$APP_PORT

Попытка добавления в Dockerfile как прокомментировано, но не решила проблему

Попробовал добавить на docker-compose как команду: php artisan migrate:fresh too

Раньше делал это в Дженкинс, чтобы заставить его работать. Теперь не хочу, чтобы через Дженкинс

docker-compose up -d --force-recreate --build 

#Running commands on already running service 
docker-compose exec -T app php artisan migrate:fresh --seed --force

6 ответов

На мой взгляд, автоматическая миграция - не лучший способ создания контейнера. Вы можете сделать это после того, как контейнер будет загружен с помощью этого однострочного кода вручную;

      docker exec your_container_name php artisan migrate

Вот как я это решил. Создал bash-скрипт run.sh и добавил команды миграции php artisan, а затем команду php serve.

run.sh

#!/bin/sh

cd /app  
php artisan migrate:fresh --seed
php artisan serve --host=0.0.0.0 --port=$APP_PORT

Добавлена точка входа в Dockerfile, удаляющая CMD в конце, который будет запускать нужные команды.

copy ./run.sh /tmp    
ENTRYPOINT ["/tmp/run.sh"]

Удалить команду из docker-compose.yml

Ну вот:

docker-compose run app php artisan migrate

Да, особый сценарий. Я пытаюсь создать развертывание и тестирование throw docker-compose, поэтому я запускаю миграции в скрипте перед запуском супервизора в "заданиях" docker-service:

#!/bin/sh

cd /var/www
php artisan migrate --seed

/usr/bin/supervisord -n -c /etc/supervisord.conf

И кусок из моего deploy-docker-compose.yml:

services:
    nginx:
        depends_on:
            - phpfpm ## NOT START BEFORE PHPFPM

    phpfpm:
        depends_on: 
            - jobs ## NOT START BEFORE MIGRATION
    jobs:
        # ....

Эта схема еще не запущена в производство;

UPD1

мне пришлось создать простую команду laravel wait_db_alive:

public function handle()
{
    $i = 1;
    $ret = 1;
    while($i <= 10){
        echo 'connecting to host:'.config('database.connections.'.config('database.default').'.host').' try '.$i.'..';
        try {
            DB::connection()->getPdo();
            echo 'ok'.PHP_EOL;
            $ret = 0;
            break;
        } catch (\Exception $e) {
            echo 'error:' . $e->getMessage() .PHP_EOL;
            sleep(1);
            $i++;
        }
    }
    return $ret;
}

и отредактируйте init.sh на

#!/bin/sh

php artisan wait_db_alive && php artisan migrate --seed && /usr/bin/supervisord -n -c /etc/supervisord.conf

Итак, ведем журнал вакансий:

jobs_1      | connecting to host:db try 1..error:SQLSTATE[HY000] [2002] Connection refused
jobs_1      | connecting to host:db try 2..error:SQLSTATE[HY000] [2002] Connection refused
jobs_1      | connecting to host:db try 3..ok
jobs_1      | Nothing to migrate.
jobs_1      | Seeding: ServicesTableSeeder
...
jobs_1      | Database seeding completed successfully.
jobs_1      | 2020-11-22 05:33:43,653 CRIT Supervisor is running as root.

UPD2

В некоторых случаях нам нужно запустить контейнер без.env-файла, тогда лучше для этого init.sh:

#!/bin/sh
php artisan wait_db_alive && php artisan migrate --seed 
/usr/bin/supervisord -n -c /etc/supervisord.conf

Одним из быстрых способов является создание временного маршрута для выполнения миграции.

      Route::get('/migrate', function () {
    \Artisan::call('migrate');
    return \Artisan::output();
});

Чтобы выполнить миграцию, вы должны находиться внутри вашего контейнера, для этого вам нужно запустить ваши контейнеры с docker-compose up, здесь вам нужно быть с терминалом в каталоге, где находится ваш файл docker-compose.yml.

после этого и с тем же местом в файле docker-compose.yml запустите этот комманд, чтобы он находился внутри контейнера ur:

docker exec -it name_of_ur_server bash

и когда вы будете внутри вашего контейнера, перейдите к вашему общему приложению внутри контейнера, я думаю, вот приложение так cd app,

после всего этого запуска:

php artisan migrate

Другие вопросы по тегам