如何通过Jenkins流水线为Docker化Laravel项目传递环境变量
问题核心
本地Docker化Laravel项目可正常运行,但Jenkins流水线部署时出现数据库连接拒绝错误:
SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = forge and table_name = migrations and table_type = 'BASE TABLE')
排查发现Jenkins创建的容器中无正确的.env文件,默认使用.env.example生成的配置(数据库为forge),与实际MySQL服务不匹配。
可行解决方案
方法一:通过Docker Compose直接注入环境变量(推荐)
Laravel会优先读取系统环境变量,无需依赖.env文件。直接在docker-compose.dev.yml的laravel服务中添加环境变量配置:
修改docker-compose.dev.yml的laravel服务:
services: laravel: # 原有配置保留 environment: - APP_ENV=development - DB_CONNECTION=mysql - DB_HOST=mysql - DB_PORT=3306 - DB_DATABASE=henriquedb10 - DB_USERNAME=root - DB_PASSWORD=xxx # 可选:APP_KEY可在启动时生成
同时调整Dockerfile,移除构建时生成.env的步骤(避免固化默认配置):
# 移除这一行:RUN cp .env.example .env && php artisan key:generate
在docker-compose.dev.yml的laravel服务中添加启动命令,自动生成APP_KEY:
command: bash -c "php artisan key:generate --force && apache2-foreground"
方法二:在Jenkins流水线中生成正确的.env文件
在Jenkins工作目录中生成符合环境的.env,确保Docker构建或容器启动时能读取到:
修改Jenkinsfile,在Clone Repository之后添加生成.env的阶段:
stage('Create .env File') { steps { sh ''' cat > .env << EOF APP_ENV=development APP_KEY= DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3306 DB_DATABASE=henriquedb10 DB_USERNAME=root DB_PASSWORD=xxx EOF ''' } }
然后在Run Dev Environment之后,执行生成APP_KEY的命令:
stage('Generate App Key') { steps { sh 'docker exec eventos-dev php artisan key:generate --force' } }
如果你的.env文件存放在Jenkins服务器的固定目录,可直接复制(确保Jenkins用户有权限访问目标目录):
stage('Populate .env file') { steps { sh 'cp /var/lib/jenkins/workspace/envs/laravel/.env ${WORKSPACE}/' } }
方法三:等待MySQL服务就绪后执行迁移
depends_on仅保证MySQL容器启动,不保证服务就绪。在执行迁移前添加等待步骤:
在Jenkinsfile中Run Dev Environment之后添加:
stage('Wait for MySQL Ready') { steps { sh 'until docker exec banco-dev mysqladmin ping -h localhost -uroot -pxxx --silent; do sleep 5; done' } }
最终调整后的Jenkinsfile示例
pipeline { agent any stages { stage('Clone Repository') { steps { git branch: 'main', url: 'https://github.com/setmehemg/arq-software-uni.git' } } stage('Create .env File') { steps { sh ''' cat > .env << EOF APP_ENV=development APP_KEY= DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3306 DB_DATABASE=henriquedb10 DB_USERNAME=root DB_PASSWORD=xxx EOF ''' } } stage('Build Docker Image') { steps { sh 'docker build -t henriquemg/gcs-laravel:latest .' } } stage('Run Dev Environment') { steps { sh 'docker compose -f docker-compose.dev.yml -p dev up -d' } } stage('Wait for MySQL Ready') { steps { sh 'until docker exec banco-dev mysqladmin ping -h localhost -uroot -pxxx --silent; do sleep 5; done' } } stage('Generate App Key') { steps { sh 'docker exec eventos-dev php artisan key:generate --force' } } stage('Execute Tests') { steps { sh 'docker exec eventos-dev php artisan migrate --force' sh 'docker exec eventos-dev php artisan db:seed --class=EventosTableSeeder' sh 'docker exec -t eventos-dev php artisan test' } } stage('Deploy to Docker Hub') { steps { script { sh 'docker login -u xxx -p xxx' sh 'docker push henriquemg/gcs-laravel:latest' } } } } }
内容的提问来源于stack exchange,提问作者Heng

