From 49b7d83dfa4a6dca6f4e2d282091deada82ec9b5 Mon Sep 17 00:00:00 2001 From: y9938 Date: Wed, 10 Dec 2025 02:57:17 +0300 Subject: [PATCH] feat(docker): refactor to use pre-built images - Add build/load script for image management - Use .env config for image naming and PHP version - Switch to www-data user in Dockerfile - Update compose.yaml to use pre-built images - Add .dockerignore - Simplify entrypoint script --- .dockerignore | 3 ++ .env.example | 15 +++++++++ README.md | 16 ++-------- compose.yaml | 9 ++---- docker/Dockerfile | 26 +++++----------- docker/docker-entrypoint.sh | 31 ++++++------------- docker/php-fpm.conf | 2 -- run.sh | 62 +++++++++++++++++++++++++++++++++++++ 8 files changed, 103 insertions(+), 61 deletions(-) create mode 100644 .dockerignore create mode 100644 .env.example create mode 100755 run.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f514cf0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +* +!docker/docker-entrypoint.sh +!docker/php-fpm.conf diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..44959e6 --- /dev/null +++ b/.env.example @@ -0,0 +1,15 @@ +DB_CONNECTION=mysql +DB_HOST=mysql +DB_PORT=3306 +DB_DATABASE=app +DB_USERNAME=laravel +DB_PASSWORD=secret +DB_ROOT_PASSWORD=secret + +# Docker +PHP_VERSION=8.3-fpm +IMAGE_NAME=dev-pj1-laravel +IMAGE_TAG=${PHP_VERSION} + +APP_UID=1000 +APP_GID=1000 diff --git a/README.md b/README.md index 0ccba2f..84a644d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ ## Создание проекта: ```bash -touch .env +cp .env.example .env +# !change .env for yourself +./run.sh build docker compose up -d php-fpm docker compose exec php-fpm bash ``` @@ -20,15 +22,3 @@ laravel new example-app mv example-app/* example-app/.* ./ rmdir example-app ``` - -Изменить в `.env` - -``` -DB_CONNECTION=mysql -DB_HOST=mysql -DB_PORT=3306 -DB_DATABASE=app -DB_USERNAME=laravel -DB_PASSWORD=secret -DB_ROOT_PASSWORD=secret -``` diff --git a/compose.yaml b/compose.yaml index 52f473b..22dbd33 100644 --- a/compose.yaml +++ b/compose.yaml @@ -13,17 +13,12 @@ services: condition: service_started php-fpm: - build: - context: . - dockerfile: ./docker/Dockerfile - args: - UID: ${UID:-1000} - GID: ${GID:-1000} + image: "${IMAGE_NAME}:${IMAGE_TAG}" + user: "${APP_UID}:${APP_GID}" env_file: - .env volumes: - ./:/var/www - - ./docker/docker-entrypoint.sh:/usr/local/bin/docker-entrypoint.sh depends_on: mysql: condition: service_started diff --git a/docker/Dockerfile b/docker/Dockerfile index 7561ae8..2bae4a1 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,31 +1,21 @@ -FROM php:8.3-fpm +ARG PHP_VERSION=8.3-fpm +FROM php:${PHP_VERSION} -ARG UID -ARG GID - -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + libpng-dev libonig-dev libxml2-dev libzip-dev \ + zip unzip git \ netcat-traditional \ - libpng-dev \ - libonig-dev \ - libxml2-dev \ - libzip-dev \ - zip \ - unzip \ - git \ && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \ && apt-get clean && rm -rf /var/lib/apt/lists/* -COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ - COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +COPY --chown=www-data:www-data ./docker/docker-entrypoint.sh /usr/local/bin/ COPY ./docker/php-fpm.conf /usr/local/etc/php-fpm.d/zz-docker.conf -COPY ./docker/docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh -RUN groupadd -g $GID laravel && useradd -u $UID -g $GID -m laravel -USER laravel - +USER www-data WORKDIR /var/www EXPOSE 9000 diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index a5ce269..9c5e6ab 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -1,35 +1,26 @@ #!/bin/sh set -e -cd /var/www - -echo ">> Running in ${APP_ENV:-unknown} mode" +APP_ENV=${APP_ENV:-unknown} +echo ">> Running in $APP_ENV mode" +# Only for Laravel project if [ -f "artisan" ]; then - chown -R laravel:laravel storage bootstrap/cache - chmod -R 775 storage bootstrap/cache - if [ ! -d "vendor" ]; then - echo ">> Installing composer dependencies..." - if [ "$APP_ENV" = "production" ]; then - composer install --no-dev --optimize-autoloader - else - composer install --optimize-autoloader - fi + echo ">> Ensuring composer dependencies are up to date..." + if [ "$APP_ENV" = "production" ]; then + composer install --no-dev --optimize-autoloader else - echo ">> Vendor directory exists, skipping installation" + composer install --optimize-autoloader fi if [ -f ".env" ] && grep -q '^APP_KEY=$' .env; then - echo ">> APP_KEY is missing. Generating application key..." + echo ">> Generating application key..." php artisan key:generate --ansi fi - echo ">> Waiting for MySQL to be ready..." - while ! nc -z mysql 3306; do - sleep 1 - done - echo ">> MySQL is ready!" + echo ">> Waiting for MySQL..." + while ! nc -z mysql 3306; do sleep 1; done echo ">> Running migrations..." php artisan migrate --force || true @@ -37,8 +28,6 @@ if [ -f "artisan" ]; then if [ ! -L "public/storage" ] && [ -d "storage/app/public" ]; then echo ">> Creating storage link..." php artisan storage:link - else - echo ">> Storage link already exists or storage directory missing" fi if [ "$APP_ENV" = "local" ]; then diff --git a/docker/php-fpm.conf b/docker/php-fpm.conf index 56a58f6..061471c 100644 --- a/docker/php-fpm.conf +++ b/docker/php-fpm.conf @@ -2,8 +2,6 @@ daemonize = no [www] -user = laravel -group = laravel listen = 9000 pm = dynamic pm.max_children = 5 diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..ea6bda6 --- /dev/null +++ b/run.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -euo pipefail + +# Help +if [[ $# -eq 0 ]]; then + echo "Usage: $0 {build|load} [source]" + echo " build - Build image and save archive" + echo " load [source] - Load image from:" + echo " (no arg) - Use archive or build from source" + echo " URL - download from URL then load" + echo " file - load from specified file via docker load command" + echo "" + echo "Archive location: \${IMAGE_NAME}_\$IMAGE_TAG.tar.gz in current directory" + exit 0 +fi + +# Load config +[[ ! -f .env ]] && cp .env.example .env +source .env + +# Validate +if [[ -z "${IMAGE_NAME:-}" ]] || [[ -z "${IMAGE_TAG:-}" ]] || [[ -z "${PHP_VERSION:-}" ]]; then + echo "Error: IMAGE_NAME or IMAGE_TAG or PHP_VERSION not set in .env" + echo "Please add to .env (check vars in .env.example):" + echo "PHP_VERSION=8.3-fpm # Used in Dockerfile" + echo "IMAGE_NAME=your-image-name" + echo "IMAGE_TAG=\${PHP_VERSION} # Or custom tag" + exit 1 +fi + +IMAGE="$IMAGE_NAME:$IMAGE_TAG" +TAR_FILE="${IMAGE_NAME}_$IMAGE_TAG.tar.gz" + +ACTION="${1:-}" +SOURCE="${2:-}" + +case "$ACTION" in + build) + docker build -f docker/Dockerfile --build-arg PHP_VERSION=$PHP_VERSION -t "$IMAGE" . + docker save "$IMAGE" | gzip > "$TAR_FILE" + ;; + load) + if [[ -f "$TAR_FILE" ]]; then + docker load < "$TAR_FILE" + elif [[ -n "$SOURCE" ]]; then + if [[ "$SOURCE" =~ ^https?:// ]]; then + curl -L "$SOURCE" -o "$TAR_FILE" + docker load < "$TAR_FILE" + else + # Handle local file path + docker load < "$SOURCE" + fi + else + docker build -f docker/Dockerfile --build-arg PHP_VERSION=$PHP_VERSION -t "$IMAGE" . + fi + ;; + *) + echo "Error: Unknown action '$ACTION'" + echo "Usage: $0 {build|load} [source]" + exit 1 + ;; +esac