serversideup / docker-php

🐳 Production-ready Docker images for PHP. Optimized for Laravel, WordPress, and more!
https://serversideup.net/open-source/docker-php/
GNU General Public License v3.0
1.67k stars 109 forks source link

Laravel migration with database cache errors because cannot obtain lock #298

Closed ivandokov closed 5 months ago

ivandokov commented 5 months ago

Affected Docker Images

Currently using serversideup/php:beta-8.2-unit but I believe the issue applies to all images

Docker Labels of the affected images

No response

Current Behavior

I am trying to build an image which includes my source code. I bundle all the files and create database.sqlite with an entrypoint script. My cache driver is set to database (default for Laravel 11). When I build the image and run it the init setup errors as the migration command has --isolated from https://github.com/serversideup/docker-php/pull/129. The issue is that this process isolation requires the cache to obtain a lock and the lock cannot be created before the migrations are executed initially so the requried tables are created. This is not the case with any other cache driver.

This is the SQL error I receive:

SQLSTATE[HY000]: General error: 1 no such table: cache_locks (Connection: sqlite, SQL: update "cache_locks" set "owner" = WHrlN9OYqWwipG0v, "expiration" = 1711379426 where "key" = framework/command-migrate and ("owner" = WHrlN9OYqWwipG0v or "expiration" <= 1711375826))

I know this is not directly a docker issue but a Laravel one as the Laravel installer migrates the database locally when the project is created but I don't think the migrated database should be a dependency to the builded image. I think a fresh database is more suitable for a docker image. I think the workaround should be included in the implementation for docker. Maybe a new flag for isolation mode. Something like AUTORUN_LARAVEL_MIGRATION_ISOLATION=true

Expected Behavior

The initial migrations should be executed successfully.

Steps To Reproduce

laravel new test
cd test

# Removed the initial database because I want a clean one in the image
rm database/database.sqlite 

# Create init script
cat > 20-init-database.sh <<EOT
#!/bin/sh
if [ ! -f "\$APP_BASE_DIR/database/database.sqlite" ]; then
    touch "\$APP_BASE_DIR/database/database.sqlite"
    chown www-data:www-data "\$APP_BASE_DIR/storage/database.sqlite"
fi
EOT

chmod +x 20-init-database.sh

# Start the container
docker run -p 127.0.0.1:8080:80 \
    --env AUTORUN_ENABLED=true \
    -v .:/var/www/html/ \
    -v ./20-init-database.sh:/etc/entrypoint.d/20-init-database.sh \
    serversideup/php:beta-8.2-unit

Host Operating System

macOS Sonoma 14.2.1

Docker Version

Client:
 Cloud integration: v1.0.35+desktop.11
 Version:           25.0.3
 API version:       1.44
 Go version:        go1.21.6
 Git commit:        4debf41
 Built:             Tue Feb  6 21:13:26 2024
 OS/Arch:           darwin/arm64
 Context:           desktop-linux

Server: Docker Desktop 4.28.0 (139021)
 Engine:
  Version:          25.0.3
  API version:      1.44 (minimum version 1.24)
  Go version:       go1.21.6
  Git commit:       f417435
  Built:            Tue Feb  6 21:14:22 2024
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.28
  GitCommit:        ae07eda36dd25f8a1b98dfbf587313b99c0190bb
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Anything else?

No response

jaydrogers commented 5 months ago

Thanks for pointing this out @ivandokov!

I took what you did and factored it to support SQLite out of the box.

Since the --isolated feature depended on certain Laravel versions, I decided to default that to false. Users can enable it if needed.

Here are the updated docs on how this works:

Screenshot 2024-04-04 at 16 49 33@2x