Gitlab: PHP项目CI/CD实践

目录

1 说明

2 CI/CD

2.1 部署方式一:增量部署

2.1.1 目标服务器准备 

2.2.2 Gitlab及Envoy脚本

2.2 部署方式二:镜像构建与部署

2.2.1 推送到私有化容器仓库

准备工作

脚本

要点

2.2.2 推送到hub.docker.com

准备工作

脚本

3 参考:


1 说明

  • 以一个laravel blog项目为例,做dev分支的CI/CD实践
  • 结合laravel envoy工具做多个远程服务器部署,分两种方式:A. 增量部署 B.镜像构建与部署

服务器:

SiteServerIP站点目录
team1-prj2.dev.iahost001.dev.ia192.168.0.130/www/wwwroot/team1-prj2.dev.ia
team1-prj2.dev.iahost002.dev.ia192.168.0.131/www/wwwroot/team1-prj2.dev.ia

2 CI/CD

2.1 部署方式一:增量部署

通过Lavavel/Envoy和git拉取新版本文件进行部署

2.1.1 目标服务器准备 
  • php8.2, 安装所需扩展,务必在cli下测试是否正常, 有些被disable的functions要打开
  • composer self-update, 兼容php8.2
  • 使用Laravel/Envoy分发部署,确保Envoy.blade.php是utf8格式文件
  • 站点目录结构
    root@host001:/www/wwwroot/team1-prj2.dev.ia# tree -d -L 3 ./
    ./
    ├── current -> /www/wwwroot/team1-prj2.dev.ia/releases/default
    ├── releases
    │   └── default
    │       ├── app
    │       ├── bootstrap
    │       ├── config
    │       ├── database
    │       ├── public
    │       ├── resources
    │       ├── routes
    │       ├── storage -> /www/wwwroot/team1-prj2.dev.ia/storage
    │       ├── tests
    │       └── vendor
    └── storage
        ├── app
        │   └── public
        ├── framework
        │   ├── cache
        │   ├── sessions
        │   ├── testing
        │   └── views
        └── logs
    

说明:

team1-prj2.dev.ia应用目录
team1-prj2.dev.ia/releases版本发布目录,这里只设置了一个default目录,也可根据需要做日期变量发布
team1-prj2.dev.ia/current

链接到最新版本,被nginx访问的站点目录路径

current -> /www/wwwroot/team1-prj2.dev.ia/releases/default/

team1-prj2.dev.ia/storage

链接到最新版本的应用数据保存目录,如:日志,缓存等

storage -> /www/wwwroot/team1-prj2.dev.ia/storage

team1-prj2.dev.ia/.dev

.dev文件是运维人员建立的服务器定制环境文件,不进入仓库,链接到项目同名文件

.env -> /www/wwwroot/team1-prj2.dev.ia/.env*

team1-prj2.dev.ia/releases/default/.gitlab-ci.ymlgitlab 部署脚本
team1-prj2.dev.ia/releases/default/Envoy.blade.phpenvoy 部署脚本

nginx配置

server
{
    listen 80;
    server_name team1-prj2.dev.ia;
    index index.php index.html index.htm default.php default.htm default.html;
    root /www/wwwroot/team1-prj2.dev.ia/current/public;
    #CERT-APPLY-CHECK--START
    # 用于SSL证书申请时的文件验证相关配置 -- 请勿删除
    include /www/server/panel/vhost/nginx/well-known/team1-prj2.dev.ia.conf;
    #CERT-APPLY-CHECK--END

    #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
    #error_page 404/404.html;
    #SSL-END

    #ERROR-PAGE-START  错误页配置,可以注释、删除或修改
    #error_page 404 /404.html;
    #error_page 502 /502.html;
    #ERROR-PAGE-END

    #PHP-INFO-START  PHP引用配置,可以注释或修改
    include enable-php-82.conf;
    #PHP-INFO-END

    #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
    include /www/server/panel/vhost/rewrite/team1-prj2.dev.ia.conf;
    #REWRITE-END

    #禁止访问的文件或目录
    location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md)
    {
        return 404;
    }

    #一键申请SSL证书验证目录相关设置
    location ~ \.well-known{
        allow all;
    }

    #禁止在证书验证目录放入敏感文件
    if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
        return 403;
    }

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
    {
        expires      30d;
        error_log /dev/null;
        access_log /dev/null;
    }

    location ~ .*\.(js|css)?$
    {
        expires      12h;
        error_log /dev/null;
        access_log /dev/null;
    }
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    access_log  /www/wwwlogs/team1-prj2.dev.ia.log;
    error_log  /www/wwwlogs/team1-prj2.dev.ia.error.log;
}
2.2.2 Gitlab及Envoy脚本

.gitlab-ci.yml

# default:
#  image: edbizarro/gitlab-ci-pipeline-php:7.4
#default:
# image: bennybi/php8.2
# image: bennybi/php7.4

stages:
  - test
  - deploy

.init_ssh: &init_ssh |
  which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )
  eval $(ssh-agent -s)
  echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
  mkdir -p ~/.ssh
  chmod 700 ~/.ssh
  [[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - vendor/

unit_test:
  stage: test
  tags:
    - php
  script:
    - cp .env.test .env
    - composer install
    - composer global require "laravel/envoy"
    - php artisan key:generate
    - php artisan migrate
    - vendor/bin/phpunit

deploy_dev:
  stage: deploy
  tags:
    - php
  environment:
    name: dev
    url: http://team1-prj2.dev.ia
  script:
    - *init_ssh
    - vendor/bin/envoy run deploy --branch="$CI_COMMIT_BRANCH" --commit="$CI_COMMIT_SHA"
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"

deploy_live:
  stage: deploy
  tags:
    - php
  script:
    - *init_ssh
    - vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
  environment:
    name: live
    url: http://team1-prj2.dev.ia
  when: manual
  rules:
    - if: $CI_COMMIT_BRANCH == "live"

Envoy.blade.php

@servers(['local' => 'deployer@host001.dev.ia','staging' => 'deployer@host002.dev.ia'])

@setup
    $repository = 'git@host001.dev.ia:dev1/team1-prj2.git';
    $releases_dir = '/www/wwwroot/team1-prj2.dev.ia/releases';
    $app_dir = '/www/wwwroot/team1-prj2.dev.ia';
    $release = 'default';
    $new_release_dir = $releases_dir .'/'. $release;
    $user = get_current_user();
@endsetup

@story('deploy', ['on' => ['local','staging']])
    sync_repository
    run_composer
    update_symlinks
@endstory

@task('sync_repository')
    echo "Current User: {{$user}}, branch:{{$branch}}, commit:{{$commit}}"
    if [ -d "{{$new_release_dir}}" ]; then
        echo 'Pulling repository'
        cd {{ $new_release_dir }}
        git checkout {{ $branch }}
        git fetch
        git reset --hard HEAD
        git merge origin/{{ $branch }}
    else
        echo 'Cloning repository'
        [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
        git clone --branch {{ $branch }}  --single-branch --depth 1 {{ $repository }} {{ $new_release_dir }}
        cd {{ $new_release_dir }}
        git reset --hard {{ $commit }}
        git config --global --add safe.directory '*'
    fi
@endtask

@task('run_composer')
    echo "Starting deployment ({{ $release }})"
    cd {{ $new_release_dir }}
    composer install --prefer-dist --no-scripts -q -o
@endtask

@task('update_symlinks')
    if [ ! -d "{{ $app_dir }}/current" ]; then
        echo "Linking storage directory"
        {{-- rm -rf {{ $new_release_dir }}/storage  --}}
        mv {{ $new_release_dir }}/storage {{ $app_dir }}
        ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage
        
        echo 'Linking .env file'
        ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env
        
        echo 'Linking current release'
        ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current
        
        chmod 775 -Rf {{ $releases_dir }}
    fi
    chmod 775 -Rf {{ $new_release_dir }}/storage
    {{-- chown deployer:www -Rf {{ $new_release_dir }}/.git  --}}
@endtask
2.2 部署方式二:镜像构建与部署
2.2.1 推送到私有化容器仓库
准备工作

-  新建项目team1-prj1,初始化git 仓库为:http://host001.dev.ia:18181/dev1/team1-prj1.git

-  建好容器仓库(见前文相关部分)

-  需要在Admin Area->CI/CD->Variables添加docker访问用户变量

$LOCAL_REGISTRY_LOGIN = your docker username
$LOCAL_REGISTRY_PASSWORD
脚本

 项目中添加Dockerfile 文件,这里用到的原型镜像是我之前定制的php8.2

# Set the base image for subsequent instructions
FROM bennybi/php8.2:latest

# Update packages
RUN apt-get update

# Install PHP and composer dependencies
# RUN apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev

# Clear out the local repository of retrieved package files
RUN apt-get clean

# Install needed extensions
# Here you can install any other extension that you need during the test and deployment process
# RUN docker-php-ext-install mcrypt pdo_mysql zip

# Install Composer
RUN curl --silent --show-error "https://getcomposer.org/installer" | php -- --install-dir=/usr/local/bin --filename=composer

# Install Laravel Envoy
RUN composer global require "laravel/envoy=~1.0"

# Laravel? Add your user
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

 .gitlab-ci.yml

default:
  image: docker:19.03.8
  services:
    - mysql:5.7
  before_script:
    - docker info

variables:
  MYSQL_DATABASE: test
  MYSQL_ROOT_PASSWORD: fa843c707ce26702
  DB_HOST: host001.dev.ia
  DB_USERNAME: developer

stages:
  - test
  - build
  # - deploy

unit_test:
  stage: test
  tags:
    - php
  script:
    - cp .env.test .env
    - composer install
    - php artisan key:generate
    - php artisan migrate
    - vendor/bin/phpunit

build_image:
  stage: build
  variables:
    REGISTRY_URL: 'http://host001.dev.ia:5050'
    DOCKER_IMAGE_TAG: 'host001.dev.ia:5050/dev1/team1-prj1'
  tags:
    - php
  script:
    - docker login ${REGISTRY_URL} -u $LOCAL_REGISTRY_LOGIN -p $LOCAL_REGISTRY_PASSWORD
    - docker build --output type=registry,oci-mediatypes=false --cache-from "${DOCKER_IMAGE_TAG}" -t "${DOCKER_IMAGE_TAG}" --push --provenance=false .
    # - docker push ${DOCKER_IMAGE_TAG}:latest
    - docker push ${DOCKER_IMAGE_TAG}
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"

# deploy_dev:
#   stage: deploy
#   tags:
#     - php
#   script:
#     - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
#     - eval $(ssh-agent -s)
#     - ssh-add <(echo "$SSH_PRIVATE_KEY")
#     - mkdir -p ~/.ssh
#     - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
#     # - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
#   environment:
#     name: dev
#     url: http://team1-prj1.dev.ia
#   when: manual
#   rules:
#     - if: $CI_COMMIT_BRANCH == "dev"
要点

- 注意build时所需的参数,缺少会诱发错误: “Invalid tag: missing manifest digest”

We used the buildx flag “–output type=registry,oci-mediatypes=false” to generate a Docker v2.2 manifest list.  We could set the value to “true” and generate an OCI manifest index, but the GitLab UI will incorrectly display “Invalid tag: missing manifest digest”. 

 推送结果图示:

2.2.2 推送到hub.docker.com
准备工作

-  新建项目team1-prj1,初始化git 仓库为:http://host001.dev.ia:18181/dev1/team1-prj1.git

-  构建的镜像将push到hub.docker.com,因此需要在Admin Area->CI/CD->Variables添加docker访问用户变量

$DOCKER_LOGIN = your docker username
$DOCKER_PASSWORD 
脚本

Dockerfile 

同上 ...

.gitlab-ci.yml

default:
  image: docker:19.03.8
  services:
    - mysql:5.7
  before_script:
    - docker info

variables:
  MYSQL_DATABASE: test
  MYSQL_ROOT_PASSWORD: fa843c707ce26702
  DB_HOST: host001.dev.ia
  DB_USERNAME: developer

stages:
  - test
  - build
  # - deploy

unit_test:
  stage: test
  tags:
    - php
  script:
    - cp .env.test .env
    - composer install
    - php artisan key:generate
    - php artisan migrate
    - vendor/bin/phpunit

build_image:
  stage: build
  variables:
    DOCKER_IMAGE_TAG: 'bennybi/team1-prj1'
  tags:
    - php
  script:
    - docker build --cache-from "${DOCKER_IMAGE_TAG}" -t "${DOCKER_IMAGE_TAG}" .
    - docker login --username $DOCKER_LOGIN --password $DOCKER_PASSWORD
    # - docker run my-docker-image /script/to/run/tests
    - docker push ${DOCKER_IMAGE_TAG}:latest
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"

# deploy_dev:
#   stage: deploy
#   tags:
#     - php
#   script:
#     - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
#     - eval $(ssh-agent -s)
#     - ssh-add <(echo "$SSH_PRIVATE_KEY")
#     - mkdir -p ~/.ssh
#     - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
#     # - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
#   environment:
#     name: dev
#     url: http://team1-prj1.dev.ia
#   when: manual
#   rules:
#     - if: $CI_COMMIT_BRANCH == "dev"

3 参考:

- GitLab: automated build and publish of multi-platform container image with GitLab pipeline | Fabian Lee : Software Engineer

- https://jaumemule.medium.com/build-a-php8-0-fpm-gitlab-ci-cd-application-docker-google-cloud-5f2868e8370

- https://docs.gitlab.com/ee/ci/docker/using_docker_build.html

 - https://github.com/papertank/envoy-deploy/blob/master/readme.md

- https://warrickbayman.medium.com/zero-downtime-laravel-deployments-with-envoy-version-2-227c8259e31c

- Test and deploy Laravel applications with GitLab CI/CD and Envoy | GitLab

- GitLab CI/CD examples | GitLab

- 使用GitLab Runner为基于Laravel的PHP项目进行部署 

- GitLab CI/CD for Beginners [FREE Course] - DEV Community

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/429325.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入探讨 AutoGPT:彻底改变游戏的自主 AI

原文地址&#xff1a;Deep Dive into AutoGPT: The Autonomous AI Revolutionizing the Game 2023 年 4 月 24 日 AutoGPT 是一个功能强大的工具&#xff0c;它通过 API 使用 GPT-4 和 GPT-3.5&#xff0c;通过将项目分解为子任务并在自动循环中使用互联网和其他工具来创建完…

力扣hot8---滑动窗口

这里先跳过力扣hot7啦&#xff0c;这几天就回更~ 题目&#xff1a; 滑动窗口思路&#xff1a; 首先左窗口&#xff08;left&#xff09;指向的是第0个元素&#xff0c;依次遍历循环每一个元素&#xff0c;维护一个unordered_set&#xff0c;如果当前被遍历的元素存在于unorder…

Python实现ADTM工具判断信号:股票技术分析的工具系列(6)

Python实现ADTM工具判断信号&#xff1a;股票技术分析的工具系列&#xff08;6&#xff09; 介绍算法解释 代码rolling函数介绍完整代码data代码ADTM.py 介绍 ADTM&#xff08;动态买卖气指标&#xff09;是一种用于衡量市场买卖力量对比的指标。它通过计算动态买盘指标&#…

【源码】imx6ull实现触摸屏单点实验-移植tslib和qt

一、本实验实验的器材&#xff1a; 1.正点原子imx6ull的阿尔法开发板v2.2 2.屏幕ALIENTEK 4.3 RGBLCD 二、实验已经移植好的文件&#xff1a; 仓库代码&#xff1a;https://gitee.com/wangyoujie11/atkboard_-linux_-driver.git 1.文件说明 arm-qt.tar.bz2&#xff1a;移植好的…

tsc : 无法加载文件 C:\Users\Administrat\AppData\Roaming\npm\tsc.ps 1,因为在此系统上禁止运行脚本

报错&#xff1a;tsc : 无法加载文件 C:\Users\Administrat\AppData\Roaming\npm\tsc.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 解决 使用命令行时出现ab…

idea中引入新JDK环境

在不同的项目中往往会需要不同的运行环境&#xff0c;那么如何下载一个新的环境并运用到idea中呢&#xff1f; 下面给出的就是oracle官网&#xff0c;以JDK17为例教大家如何下载 Java Archive Downloads - GraalVM for JDK 17https://www.oracle.com/java/technologies/javase…

世界的本质是旋转(5)-在复平面上驱动软件无线电SDR发射BPSK波形

在上一篇文章中&#xff0c;我们介绍了复平面、拍照采样的一些思维实验。从本节开始&#xff0c;转入现实应用&#xff0c;通过控制复平面向量的位置&#xff0c;实现一个完整的BPSK全双工通信通道。 发射方&#xff1a;通过控制复平面向量在各个时刻的位置来携带信息的技术&a…

108. 将有序数组转换为二叉搜索树【简单】

108. 将有序数组转换为二叉搜索树【简单】 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉…

电脑不小心格式化了,怎么恢复?

在这个数字化时代&#xff0c;电脑已经成为我们日常生活和工作中不可或缺的工具。然而&#xff0c;有时我们可能会不小心格式化电脑硬盘&#xff0c;导致重要数据的丢失。那么&#xff0c;电脑不小心格式化了&#xff0c;怎么恢复&#xff1f; 别着急&#xff0c;在本篇攻略中&…

vue3页面内容切换(类似登录、注册内容切换)

一、内容描述 页面有俩块内容&#xff0c;分别是验证码登录页面内容&#xff0c;账号密码登录页面内容。有俩种处理方式&#xff0c;一个是写俩个页面跳转使用&#xff0c;还有一种是一个页面俩个内容&#xff0c;切换的只是不同的内容&#xff0c;相同的内容保留。一般都是选择…

音视频开发之旅——音频基础概念、交叉编译原理和实践(LAME的交叉编译)(Android)

本文主要讲解的是音频基础概念、交叉编译原理和实践&#xff08;LAME的交叉编译&#xff09;&#xff0c;是基于Android平台&#xff0c;示例代码如下所示&#xff1a; AndroidAudioDemo 音频基础概念 在进行音频开发的之前&#xff0c;了解声学的基础还是很有必要的。 声音…

Windows安装SSH教程

Windows安装SSH教程 一、SSH1.SSH简介2.SSH功能3.SSH验证3.1 第一种级别&#xff08;基于口令的安全验证&#xff09;3.2 第二种级别&#xff08;基于密匙的安全验证&#xff09; 4.SSH层次4.1 传输层协议 [SSH-TRANS]4.2 用户认证协议 [SSH-USERAUTH]4.3 连接协议 [SSH-CONNEC…

改造muduo,不依赖boost,用C++11重构

组件的实现 1. 序 1.1. 总述 muduo库是基于多Reactor-多线程模型实现的TCP网络编程库&#xff0c;性能良好。如libev作者&#xff1a;“One loop per thread is usually a good model”&#xff0c;muduo库的作者陈硕在其《Linux多线程服务端编程》中也力荐这种“One loop pe…

linux中对信号的认识

信号的概念与相关知识认识 信号是向目标进程发送消息通知的的一种机制。 信号可以以异步的方式发送给进程&#xff0c;也就是说&#xff0c;进程无需主动等待&#xff0c;而是在任何时间都可以接收到信号。 信号的种类 用kill-l命令查看系统定义的信号列表&#xff1a; 前台…

初识Hive

官网地址为&#xff1a; Design - Apache Hive - Apache Software Foundation 一、架构 先来看下官网给的图&#xff1a; 图上显示了Hive的主要组件及其与Hadoop的交互。Hive的主要组件有&#xff1a; UI&#xff1a; 用户向系统提交查询和其他操作的用户界面。截至2011年&…

Linux - 安装 maven(详细教程)

目录 一、下载二、安装三、配置环境变量四、镜像资源配置 一、下载 官网&#xff1a;https://maven.apache.org/download.cgi 打开 maven 的官网下载页面&#xff0c;点击 bin.tar.gz 文件链接 即可下载最新版本的 maven 如果想要下载旧版本的 meven&#xff0c;则点击 Maven…

【短时交通流量预测】基于GRNN神经网络

课题名称&#xff1a;基于GRNN神经网络的短时交通流量预测 版本时间&#xff1a;2023-04-27 代码获取方式&#xff1a;QQ&#xff1a;491052175 或者 私聊博主获取 模型简介&#xff1a; 城市交通路网中交通路段上某时刻的交通流量与本路段前几个时段的交通流量有关&#x…

Python类 __init__() 是一个特殊的方法

设计者&#xff1a;ISDF工软未来 版本&#xff1a;v1.0 日期&#xff1a;2024/3/5__init__() 是一个特殊的方法 类似c# C的构造函数 两头都包含两个下划线&#xff0c;这是约定&#xff0c;用于与普通的函数保持区分class User:用户类def __init__(self,first_name,last_name):…

软件应用,财务收支系统试用版操作教程,佳易王记录账单的软件系统

软件应用&#xff0c;财务收支系统试用版操作教程&#xff0c;佳易王记录账单的软件系统 一、前言 以下软件操作教程以 佳易王账单记账统计管理系统V17.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 如上图&#xff0c;统计报表包含 收支汇…

JavaScript基础2之运算符、函数

JavaScript基础 运算符一元操作符递增/递减一元加和减 布尔操作符逻辑非逻辑与逻辑或 乘性操作符乘法操作符除法操作符取模操作符 加性操作符加法操作符减法操作符 比较操作符相等操作符关系操作符 函数函数声明函数表达式箭头函数函数的实参和形参arguments 默认参数参数的拓展…