How to not lose data when deploying laravel to a docker image?

Viewed 23

I want to deploy a laravel application using a Dockerfile:

Dockerfile

FROM php:8.1-fpm

WORKDIR /var/www

RUN apt-get update && apt-get install -y --no-install-recommends wget \
    default-mysql-client libmagickwand-dev nano procps libzip-dev nginx \
    supervisor git-core
    && pecl install imagick \
    && docker-php-ext-enable imagick \
    && docker-php-ext-install pdo_mysql \
    && docker-php-ext-install zip

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

# Install NodeJS + NPM
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - \
    && apt-get install -y nodejs \
    && npm install -g npm

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

COPY . /var/www

RUN cp docker/supervisord.conf /etc/supervisord.conf
RUN cp docker/php.ini /usr/local/etc/php/conf.d/app.ini
RUN cp docker/nginx.conf /etc/nginx/sites-enabled/default

RUN mkdir /var/log/php
RUN touch /var/log/php/errors.log && chmod 777 /var/log/php/errors.log

RUN composer install --optimize-autoloader --no-dev
RUN chmod +x /var/www/docker/run.sh

RUN chown -R www-data:www-data \
        /var/www/storage \
        /var/www/bootstrap/cache

EXPOSE 80
ENTRYPOINT ["/var/www/docker/run.sh"]

docker-compose.yml

version: '3'
services:
    app:
        build:
            context: .
            dockerfile: Dockerfile
        image: myapp
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '80:80'
        volumes:
            - '/etc/localtime:/etc/localtime:ro'./data/upload:/var/www/storage/upload
        networks:
            - mynetwork
        depends_on:
            - mysql
    mysql:
        image: 'mysql/mysql-server:8.0'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: "%"
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 1
        volumes:
            - './data/mysql:/var/lib/mysql'
            - '/etc/localtime:/etc/localtime:ro'
        networks:
            - mynetwork
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
            retries: 3
            timeout: 5s
networks:
    mynetwork:
        driver: bridge

run.sh

#!/bin/sh

cd /var/www

php artisan key:generate
php artisan storage:link
php artisan migrate:fresh --seed
php artisan cache:clear
php artisan route:cache

npm i

npm run production

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

supervisord.conf

[supervisord]
nodaemon=true
loglevel = info
logfile=/var/log/supervisord.log
pidfile=/var/run/supervisord.pid

[group:laravel-worker]
priority=999
programs=nginx,php8-fpm

[program:nginx]
priority=10
autostart=true
autorestart=true
stderr_logfile_maxbytes=0
stdout_logfile_maxbytes=0
stdout_events_enabled=true
stderr_events_enabled=true
command=/usr/sbin/nginx -g 'daemon off;'
stderr_logfile=/var/log/nginx/error.log
stdout_logfile=/var/log/nginx/access.log

[program:php8-fpm]
priority=5
autostart=true
autorestart=true
stderr_logfile_maxbytes=0
stdout_logfile_maxbytes=0
command=/usr/local/sbin/php-fpm -R
stderr_logfile=/var/log/nginx/php-error.log
stdout_logfile=/var/log/nginx/php-access.log77

My entry point is the run.sh script, that I need to make everything ready (e.g. migrate and seed the database).

But when I have an update for the app, I will create a new image and this will run the php artisan migrate:fresh -seed command, what I need on the first load, but then never.

When I remove it from the script, I would need to migrate manually, what I want to avoid, as the app will later life build from GitHub Actions.

What can I do to avoid a database loss when I update my app?

0 Answers
Related