You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置GitHub Actions构建Laravel镜像至Docker Hub的问题排查

问题描述

我正在开发一个基于以下技术栈的项目:

  • Laravel 10
  • Tailwind
  • MySQL

希望实现自动化流程:每次向GitHub推送代码时,GitHub Actions自动运行测试、构建项目并将Docker镜像推送至Docker Hub,之后可以从Docker Hub拉取镜像运行项目。但在配置.yml文件和Dockerfile时遇到了问题。

当前配置文件

GitHub Actions配置(laravel.yml)

name: Laravel CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  laravel-tests:
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:5.7
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
        env:
          MYSQL_DATABASE: laravel
          MYSQL_ROOT_PASSWORD: password
        ports:
          - 3306:3306
        
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.1'
          extensions: mbstring, pdo_mysql, bcmath
          ini-values: post_max_size=256M, max_execution_time=300

      - name: Cache Composer dependencies
        uses: actions/cache@v2
        with:
          path: vendor
          key: composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: composer-

      - name: Install Composer dependencies
        run: composer install --prefer-dist --no-progress --no-suggest

      - name: Setup .env file
        run: |
          cp .env.example .env
          php artisan key:generate

      - name: Run database migrations
        run: php artisan migrate --force

      - name: Install Node.js dependencies
        run: |
          npm install
          npm run build

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: mydockerhubusername/myproject:latest

Dockerfile

FROM php:8.2-fpm

RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libonig-dev \
    libxml2-dev \
    libzip-dev \
    nodejs \
    npm \
    && docker-php-ext-install pdo pdo_mysql mbstring exif pcntl bcmath gd zip

COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

COPY composer.json composer.lock ./

RUN composer install --no-dev --optimize-autoloader --no-scripts --prefer-dist

COPY . .

RUN mkdir -p storage bootstrap/cache

RUN chmod -R 777 storage bootstrap/cache

RUN npm install && npm run build

EXPOSE 9000

CMD ["php-fpm"]

遇到的问题

  • 有时构建成功,但部署后Laravel应用显示空白页面
  • 有时会出现连接重置错误
  • 不确定Dockerfile或.yml的配置是否适用于Docker Hub的推送与拉取

问题分析与修正方案

一、Dockerfile 核心问题与修复

1. PHP版本不匹配

GitHub Actions使用PHP 8.1,但Dockerfile用PHP 8.2-fpm,版本不一致可能引发依赖或运行时异常。建议统一版本,比如都用PHP 8.1-fpm。

2. 缺少Laravel必需环境变量

镜像中未设置APP_KEY、DB_CONNECTION等关键环境变量,部署时如果没传入正确的.env,会导致应用启动失败,出现空白页面。

  • 修复:在Dockerfile中添加默认环境变量(敏感变量如APP_KEY建议启动容器时传入):
    ENV APP_ENV=production
    ENV DB_CONNECTION=mysql
    
    启动容器时通过docker run -e APP_KEY=your-key-here或挂载.env文件提供敏感配置。

3. 文件权限过于宽松

chmod -R 777 storage bootstrap/cache权限风险高,应改用PHP-FPM默认用户www-data设置权限:

RUN chown -R www-data:www-data storage bootstrap/cache
RUN chmod -R 755 storage bootstrap/cache
RUN chmod -R 775 storage/app/public # 若有文件上传需求

4. 未执行生产环境缓存命令

生产环境需要缓存配置、路由和视图来提升性能,避免加载异常,在Dockerfile中添加:

RUN php artisan config:cache
RUN php artisan route:cache
RUN php artisan view:cache

注意:执行前需确保APP_ENV=production。

5. PHP-FPM监听配置错误

默认PHP-FPM仅监听127.0.0.1:9000,容器外部无法访问,需修改为监听所有地址:

RUN sed -i 's/listen = 127.0.0.1:9000/listen = 0.0.0.0:9000/' /usr/local/etc/php-fpm.d/www.conf

6. 前端构建重复执行

GitHub Actions和Dockerfile中都执行了npm install && npm run build,浪费资源。改用多阶段构建优化:

# 第一阶段:构建前端资源
FROM node:20 as frontend
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 第二阶段:构建PHP镜像
FROM php:8.1-fpm

# 安装依赖和扩展(省略重复部分)
RUN apt-get update && apt-get install -y ... && docker-php-ext-install ...

COPY --from=composer:2.6 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-scripts --prefer-dist

# 复制代码和前端构建产物
COPY . .
COPY --from=frontend /app/public/build ./public/build
COPY --from=frontend /app/public/mix-manifest.json ./public/

# 设置权限、缓存命令等(省略重复部分)

二、GitHub Actions 配置优化

1. 缺失测试环节

当前仅执行了数据库迁移,未运行测试,无法保障代码质量,添加测试步骤:

- name: Run tests
  run: php artisan test

2. Docker镜像标签优化

仅打latest标签不利于版本追溯,添加基于提交哈希的标签:

tags: |
  mydockerhubusername/myproject:latest
  mydockerhubusername/myproject:${{ github.sha }}

3. 启用Docker构建缓存

添加缓存配置加速构建:

- name: Build and push Docker image
  uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: |
      mydockerhubusername/myproject:latest
      mydockerhubusername/myproject:${{ github.sha }}
    cache-from: type=gha
    cache-to: type=gha,mode=max

三、部署与运行问题解决

1. 缺少反向代理

PHP-FPM不处理HTTP请求,需搭配Nginx反向代理。示例Docker Compose配置(docker-compose.yml):

version: '3.8'

services:
  app:
    image: mydockerhubusername/myproject:latest
    environment:
      - APP_KEY=your-app-key-here
      - DB_HOST=db
    networks:
      - laravel-network

  webserver:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - app
    networks:
      - laravel-network

  db:
    image: mysql:5.7
    environment:
      - MYSQL_DATABASE=laravel
      - MYSQL_ROOT_PASSWORD=password
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - laravel-network

volumes:
  db-data:

networks:
  laravel-network:
    driver: bridge

对应的Nginx配置(nginx/default.conf)需正确转发PHP请求到app:9000。

2. 连接重置错误排查

  • 检查PHP-FPM监听地址是否为0.0.0.0:9000;
  • 确认Nginx配置中fastcgi_pass指向正确的容器地址;
  • 确保容器在同一个Docker网络中;
  • 查看容器日志:docker logs <app-container-id>。

3. 空白页面排查

  • 查看Laravel日志:docker exec <app-container-id> cat storage/logs/laravel.log,日志会显示具体错误(如缺少APP_KEY、数据库连接失败);
  • 确认APP_ENV=production时调试模式已关闭,错误详情不会直接显示在页面上;
  • 检查public目录是否可访问,静态资源是否存在。

内容的提问来源于stack exchange,提问作者Papazy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 07:20:55