Drone与GitLab实现Laravel项目自动构建、自动部署

Laravel 项目目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
├── .drone.yml
├── .editorconfig
├── .env.example
├── .git
├── .gitattributes
├── .gitignore
├── .gitlab-ci.yml
├── .idea
├── README.md
├── app
├── artisan
├── bin
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── docker
├── env
├── lang
├── package.json
├── phpstan.neon
├── phpunit.xml
├── pint.json
├── public
├── resources
├── routes
├── storage
├── tests
└── vite.config.js

docker 目录

1
2
3
4
5
6
7
8
9
10
11
docker
├── etc
│   └── cron
├── nginx
│   └── vhost.conf
├── prod
│   ├── Dockerfile
│   ├── docker-compose.yml
└── test
├── Dockerfile
└── docker-compose.yml

prod/Dockerfile 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 基础镜像
FROM webdevops/php-nginx:8.0-alpine

# 安装所需的 PHP 扩展
#RUN apk update && apk add --no-cache git gcc g++ make autoconf openssl-dev zlib-dev librdkafka-dev && pecl install rdkafka && docker-php-ext-enable rdkafka && pecl install swoole-5.1.1 && docker-php-ext-enable swoole
## && echo "swoole.use_shortname = 'Off'" >> /usr/local/etc/php/conf.d/docker-php-ext-swoole.ini
#
#RUN apk del git gcc g++ make autoconf openssl-dev zlib-dev && rm -rf /var/cache/apk/*

# 清除缓存
#RUN rm -rf /tmp/*

# php配置
ENV PHP_MEMORY_LIMIT '2048M'
ENV PHP_POST_MAX_SIZE '200M'
ENV PHP_UPLOAD_MAX_FILESIZE '200M'
ENV PHP_MAX_EXECUTION_TIME 600

#nginx配置
ENV SERVICE_NGINX_CLIENT_MAX_BODY_SIZE '200m'

#php-fpm配置
ENV FPM_PM_MIN_SPARE_SERVERS 10
ENV FPM_PM_MAX_SPARE_SERVERS 30
ENV FPM_PM_START_SERVERS 10
ENV FPM_PM_MAX_CHILDREN 150
ENV FPM_MAX_REQUESTS 1000

# 设置工作目录
WORKDIR /app

ARG LARAVEL_PATH=/app

# 复制 Laravel 应用代码到镜像中
COPY . ${LARAVEL_PATH}

COPY docker/nginx/vhost.conf /opt/docker/etc/nginx/vhost.conf
COPY docker/etc/cron /opt/docker/etc/cron/

RUN rm -rf ${LARAVEL_PATH}/.git

# 安装 Laravel 依赖
RUN set -ex ; cd ${LARAVEL_PATH} \
&& composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \
&& composer install \
--ignore-platform-reqs \
--no-interaction \
--no-plugins \
--no-scripts \
--prefer-dist \
--no-dev

# 设置文件权限
RUN set -ex ; cd ${LARAVEL_PATH} \
&& chmod +x artisan \
&& rm -rf bootstrap/cache/* \
&& mkdir -p storage \
&& mkdir -p storage/framework/cache \
&& mkdir -p storage/framework/sessions \
&& mkdir -p storage/framework/testing \
&& mkdir -p storage/framework/views \
&& mkdir -p storage/logs \
&& chmod 0777 -R storage bootstrap/cache \
&& cp env/.env.prod .env \
&& php artisan package:discover --ansi \
&& php artisan config:cache \
&& php artisan route:cache \
&& php artisan view:cache

prod/docker-compose.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
version: '3.9'
services:
app:
image: registry.cn-shenzhen.aliyuncs.com/thomas-hub/laravel-basic:latest
deploy:
replicas: 3
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
update_config:
parallelism: 1
delay: 10s
order: start-first
ports:
- "80:80"
networks:
- laravel-network
volumes:
- /var/log/apps/laravel-basic/nginx/:/var/log/nginx/
- /var/log/apps/laravel-basic/storage/logs/:/app/storage/logs/

networks:
laravel-network:
driver: overlay

nginx/vhost.conf 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server {
listen 80 default;

server_name _;
root /app/public;

access_log /var/log/nginx/laravel-basic.access.log;
error_log /var/log/nginx/laravel-basic.log;

add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";

index index.html index.php;

charset utf-8;

location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }

error_page 404 /index.php;

include /opt/docker/etc/nginx/vhost.common.d/*.conf;

location ~ /\.(?!well-known).* {
deny all;
}
}

etc/cron/app 文件

注:此文件用于运行定时任务脚本

1
2
3
4
SHELL=/bin/bash

# m h dom mon dow user command
* * * * * application cd /app && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1

env 目录

注:这里所有环境的配置文件统一管理

1
2
3
4
5
env
├── .env.dev
├── .env.local
├── .env.prod
└── .env.test

配置 GitLab

创建 GitLab Application



最后Save applications即可,保存后,记下相关信息,安装drone会用到。

创建 GitLab Laravel 项目的 Integration



部署 Drone Server 服务

注: drone server 服务与 drone runner 服务分开不同服务器部署,且都支持 docker 环境

drone有个Server和Runner(Agent)的概念,我们先来理解下:
Server:为Drone的管理提供了Web页面,用于管理从Git上获取的仓库中的流水线任务。
Runner(Agent):一个单独的守护进程,会轮询Server,获取需要执行的流水线任务,之后执行。
drone-runner不是必选的,官方不推荐吧runner和server安装在一个实例上

创建共享密钥

注:生产共享密钥,用于连接Server和Runner之间,两者需一致。

1
2
openssl rand -hex 16
8141566fc1aa1a8815f7b5a1bae671b8

创建 data 目录

1
mkdir -p /usr/docker/drone-server/data

创建 docker-compose.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: "3.7"

services:
drone-server:
image: drone/drone:2.20.0
container_name: drone-server
ports:
- '4000:80' # Web管理面板的入口 PROTO=http 时使用该端口
volumes:
- /var/run/docker.sock:/var/run/docker.sock # docker.sock [1]
- ./data/server:/data # drone数据存放路径
environment:
- DRONE_AGENTS_ENABLED=true # 使用Runner
- DRONE_GITLAB_SERVER=${DRONE_GITLAB_SERVER} # gitlab的地址
- DRONE_GITLAB_CLIENT_ID=${DRONE_GITLAB_CLIENT_ID} # gitlab获得的ClientID
- DRONE_GITLAB_CLIENT_SECRET=${DRONE_GITLAB_CLIENT_SECRET} # gitlab获得的ClientSecret
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET} # RPC秘钥 [2]
- DRONE_SERVER_HOST=${DRONE_SERVER_HOST} # RPC域名(在一个实例上可以不用)
- DRONE_SERVER_PROTO=${DRONE_SERVER_PROTO} # git webhook使用的协议(建议http)
- DRONE_OPEN=true # 开发drone
#- DRONE_DATABASE_DATASOURCE=/var/lib/drone/drone.sqlite # 数据库文件
#- DRONE_DATABASE_DRIVER=sqlite3 # 数据库驱动,我这里选的sqlite
- DRONE_DEBUG=true # 调试相关,部署的时候建议先打开
- DRONE_LOGS_DEBUG=true # 调试相关,部署的时候建议先打开
- DRONE_LOGS_TRACE=true # 调试相关,部署的时候建议先打开
- DRONE_ADMIN=${DRONE_ADMIN}
- DRONE_USER_CREATE=username:${DRONE_ADMIN},admin:true # 初始管理员用户
- DRONE_RUNNER_PRIVILEGED_IMAGES=plugins/docker
- DRONE_RUNNER_PRIVILEGED=true
- TZ=Asia/Shanghai # 时区
restart: always

创建.env 文件

1
2
3
4
5
6
7
8
9
DRONE_GITLAB_SERVER=https://gitlab.com
DRONE_GITLAB_CLIENT_ID=b281a70e999axxxxxxxxxxxxxxxxxxxxxe56cc78e1
DRONE_GITLAB_CLIENT_SECRET=gloas-0b76517c97fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxbfc87515e6c
DRONE_RPC_SECRET=8141566fc1aa1a8815f7b5a1bae671b8
DRONE_SERVER_HOST=14.xxx.xxx.227:4000
DRONE_SERVER_PROTO=http
DRONE_RPC_HOST=14.xxx.xxx.227:4000
DRONE_RPC_PROTO=http
DRONE_ADMIN=chendujin

目录结构概览

1
2
3
4
5
├── data
│ └── server
│ └── database.sqlite
├── docker-compose.yml
└── .env

启动 Drone Server 服务

注:在/usr/docker/drone-server 目录下执行

1
docker-compose up -d

其他

Trusted 选项,一般在部署docker项目时需要打开,如果不打开,部署docker项目时,无法使用挂在功能,即volume。
Drone 用户名需和gitlab登录用户一致,才会有Project Setting选项,我的 gitlab和drone都是 chendujin 可见。

登录 Drone 控制面板

浏览器访问14.103.55.227:4000,点击继续Continue,自动跳转gitlab,授权即可进入drone。

进入可看到gitlab所有项目,选择一个项目,进入点击activate 激活进入项目即可。

打开设置里面的 Truste 开关,允许容器挂载主机。

部署 Drone Runner 服务

创建 Drone Runner 目录

1
mkdir -p /usr/local/docker/drone-runner

创建 docker-compose.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: "3.7"

services:
drone-runner:
image: drone/drone-runner-docker:latest
container_name: drone-runner
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_HOST=${DRONE_RPC_HOST} # RPC服务地址
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET} # RPC秘钥
- DRONE_RPC_PROTO=${DRONE_RPC_PROTO} # RPC协议(http || https)
- DRONE_RUNNER_CAPACITY=2 # 最大并发执行的 pipeline 数
- DRONE_RUNNER_NAME=drone-runner
- DRONE_RUNNER_PRIVILEGED_IMAGES=plugins/docker
- DRONE_UI_USERNAME=${DRONE_UI_USERNAME} # 设置 Drone Runner 的 UI 用户账号
- DRONE_UI_PASSWORD=${DRONE_UI_PASSWORD} # 设置 Drone Runner 的 UI 用户密码
- DRONE_RUNNER_PRIVILEGED=true
- DRONE_DEBUG=true # 调试相关,部署的时候建议先打开
- DRONE_LOGS_DEBUG=true # 调试相关,部署的时候建议先打开
- DRONE_LOGS_TRACE=true # 调试相关,部署的时候建议先打开
- TZ=Asia/Shanghai
restart: always

创建.env 文件

1
2
3
4
5
DRONE_RPC_SECRET=8141566fc1aa1a8815f7b5a1bae671b8
DRONE_RPC_HOST=14.xxx.xxx.227:4000
DRONE_RPC_PROTO=http
DRONE_UI_USERNAME=thoxxx
DRONE_UI_PASSWORD=thoxxxxxx

目录结构概览

1
2
├── docker-compose.yml
└── .env

启动 Drone Runner 服务

注:在/usr/docker/drone-runner 目录下执行

1
docker-compose up -d

配置 Laravel 项目的 .drone.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
kind: pipeline # 定义一个管道
type: docker # 当前管道的类型
name: drone-laravel-demo # 当前管道的名称

platform:
os: linux
arch: amd64

workspace:
path: /drone/src

volumes:
- name: docker_sock
host:
path: /var/run/docker.sock
- name: cache
host:
path: /var/cache

clone:
disable: true #禁用默认克隆

steps:
- name: 克隆代码
image: plugins/git
when:
branch:
- main

# - name: 加载缓存 # 加载缓存
# pull: if-not-exists # 如果镜像不存在则拉取,免去每次都要重新下载
# image: drillster/drone-volume-cache
# settings:
# restore: true
# mount:
# - /var/cache
# key: ${DRONE_REPO}_${DRONE_BRANCH}_${DRONE_COMMIT_SHA}

- name: 构建镜像
pull: if-not-exists
image: plugins/docker
privileged: true # 启用特权模式
environment:
DOCKER_BUILDKIT: 1
settings:
purge: false
use_cache: true
dockerfile: docker/prod/Dockerfile # Dockerfile地址, 注意是相对地址
registry: #镜像仓库域名
from_secret: registry_url
repo: #镜像仓库详细地址
from_secret: registry_repo
tags:
- latest
username: #镜像仓库账户
from_secret: registry_user_name
password: #镜像仓库密码
from_secret: registry_password
cache_from: #镜像缓存
from_secret: registry_cache
command_timeout: 5m
mirrors: https://4t16iqyd.mirror.aliyuncs.com
volumes:
- name: docker_sock
path: /var/run/docker.sock
when:
branch:
- main

# - name: 构建缓存 # 构建缓存
# image: drillster/drone-volume-cache
# settings:
# rebuild: true
# mount:
# - /var/cache
# key: ${DRONE_REPO}_${DRONE_BRANCH}_${DRONE_COMMIT_SHA}

- name: 部署镜像
pull: if-not-exists
image: plugins/docker
privileged: true # 启用特权模式
volumes:
- name: docker_sock
path: /var/run/docker.sock
settings:
swarm: true
swarm_stack: swarm-app
swarm_services: app
insecure: true
registry: registry_repo
username:
from_secret: registry_user_name
password:
from_secret: registry_password
mirrors: https://4t16iqyd.mirror.aliyuncs.com
commands:
- ls -alh
- docker stack deploy -c docker/prod/docker-compose.yml --with-registry-auth --resolve-image always swarm
when:
branch:
- main

- name: 飞书通知
image: ydq1234/drone-lark
settings:
webhook:
from_secret: feishu_token
secret:
from_secret: feishu_secret
debug: true
when:
status:
- success
- failure

# - name: 邮箱通知 # 邮件通知
# pull: if-not-exists # 如果镜像不存在则拉取,免去每次都要重新下载
# image: drillster/drone-email
# settings:
# recipients_only: true # 只发送给指定邮件收件人,不默认发送给流水线创建人
# host: smtp.qq.com #SMTP服务器 例如 smtp.qq.com
# port: 465 #SMTP服务端口 例如QQ邮箱端口465
# subject: "Drone Build Notification!"
# username: #邮箱用户名
# from_secret: email_username
# password: #邮箱密码
# from_secret: email_passwd
# from:
# from_secret: email_username
# recipients:
# - 13xxxxxx48@163.com #收件人邮箱
# when:
# status:
# - success
# - failure

# - name: 企微通知
# pull: if-not-exists
# image: plugins/webhook
# settings:
# urls:
# from_secret: wechat_webhook_url
# content_type: application/json
# template: |
# {
# "msgtype": "markdown",
# "markdown": {
# "content": "{{#success build.status}}✅{{else}}❌{{/success}}**{{ repo.owner }}/{{ repo.name }}** (Build #{{build.number}})\n
# >**构建结果**: {{ build.status }}
# >**构建耗时**: {{since build.started}}
# >**构建详情**: [点击查看]({{ build.link }})
# >**代码分支**: {{ build.branch }}
# >**提交标识**: {{ build.commit }}
# >**提交发起**: ${DRONE_COMMIT_AUTHOR_NAME}
# >**提交信息**: {{ build.message }}
# "
# }
# }
# when:
# status:
# - success
# - failure

配置 Drone CICD 流水线的秘钥

注:在 Drone 管理面板配置以下 secret

1
2
3
4
5
6
7
registry_url=registry.cn-shenzhen.aliyuncs.com
registry_repo=registry.cn-shenzhen.aliyuncs.com/xxxx-hub/laravel-xxxx
registry_user_name=1096xxxxxx@qq.com
registry_password=xxxxxxx
registry_cache=registry.cn-shenzhen.aliyuncs.com/xxxx-hub/laravel-xxxx:cache
feishu_token=https://open.feishu.cn/open-apis/bot/v2/hook/759xxx1e-xxx-49df-xxx-4290cxxxxd858
feishu_secret=Ya4CTxxxxxxxxxxptJRf


触发流水示例





Drone与GitLab实现Laravel项目自动构建、自动部署
https://www.chendujin.com/posts/464192a3.html
作者
托马斯
发布于
2024年6月3日
许可协议