
github和dockerhub非常好用,是很多CI/CD平台的关键环节。不过它们作为互联网平台,天生具有开放共享的特点,对于企业内部代码开发来说,私密性不够,存在代码泄露的风险。
gitea是一套类似于github的软件,它的功能特性高度接近github,很容易上手。它还内置了一个容器注册表,几乎可以平替dockerhub。
gitea也支持actions,语法几乎和github actions一模一样,可以作为CI/CD工具使用。
使用gitea,可以在局域网内部搭建一个私有的CI/CD平台,满足企业软件开发的需要。
操作系统debian 12 ,kubernetes 1.28.4, gitea 1.21.11
一、安装与设置
1. 安装gitea容器
gitea的安装,最好是在docker或者裸机环境下进行。
在一台独立主机上,先安装docker
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
新建文件docker-compose.yaml,内容如下
version: "3"
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:1.21.11
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- gitea
volumes:
- ./gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
运行
docker compose up -d
启动gitea。访问http://<gitea-server-ip>:3000 可以看到gitea界面。
进行初始配置,如果用户量不大,数据库类型可以选择SQLite。
设置管理员账号,并登录。
2. 修改docker设置
修改文件/etc/docker/daemon.json,增加如下内容
{
"insecure-registries" : ["<gitea-server-ip>:3000"]
}
其中<gitea-server-ip>是gitea服务器的ip地址,根据实际情况修改。
然后运行
systemctl restart docker
重启docker。
3. 安装runner容器
gitea的actions,运行在一个独立的runner容器里面,需要单独安装。
先把runner镜像拉到本地
docker pull gitea/act_runner:latest
然后获取token, 用来让runner连接到gitea。
访问http:///<gitea-server-ip>:3000/admin/actions/runners进入gitea管理界面,点击创建Runner,会显示一个REGISTRATION TOKEN, 把它复制出来。<gitea-server-ip>是gitea服务器的IP地址,根据实际情况修改。
运行
docker run \
-v /var/run/docker.sock:/var/run/docker.sock \
-e GITEA_INSTANCE_URL=http://<gitea-server-ip>:3000 \
-e GITEA_RUNNER_REGISTRATION_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--name my_runner \
-d gitea/act_runner:latest
其中<gitea-server-ip>是gitea服务器的ip地址,xxxxxxxxxxxxxxxxxxxxxxxxxxxx就是上面步骤得到的token,根据实际情况修改。
访问http://<gitea-server-ip>:3000/admin/actions/runners,可以看到runner已经在线了。
4. 安装https反向代理
使用nginx和acme.sh,给gitea套上https。
首先需要给gitea服务器申请一个域名,假设域名为gitea.yourdomain.com。
在gitea服务器上,运行
apt install nginx
安装nginx。
修改/etc/nginx/nginx.conf,在 http{} 配置内,添加以下内容
server {
listen 80;
server_name gitea.yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl;
server_name gitea.yourdomain.com;
ssl_certificate /etc/nginx/certs/gitea.yourdomain.com/cert;
ssl_certificate_key /etc/nginx/certs/gitea.yourdomain.com/key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
运行
curl https://get.acme.sh | sh -s email=my@example.com
alias acme.sh=~/.acme.sh/acme.sh
安装acme.sh。
如果域名是在google domain申请的,那么运行下列命令,申请证书
export GOOGLEDOMAINS_ACCESS_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxx"
acme.sh --issue --dns dns_googledomains -d gitea.yourdomain.com
其中xxxxxxxxxxxxxxxxxxxxxxxxxxx是令牌,可以进入google domain的管理界面,在域名管理中点击安全->ACME DNS API->创建令牌,获得一个令牌。
运行
mkdir /etc/nginx/certs
mkdir /etc/nginx/certs/gitea.yourdomain.com
acme.sh --install-cert -d gitea.yourdomain.com \
--cert-file /etc/nginx/certs/gitea.yourdomain.com/cert \
--key-file /etc/nginx/certs/gitea.yourdomain.com/key \
--fullchain-file /etc/nginx/certs/gitea.yourdomain.com/fullchain \
--reloadcmd "systemctl reload nginx.service"
访问https://gitea.yourdomain.com, 就可以看到gitea的web界面了。
5. 在kubernetes集群上安装证书
登录到Kubernetes集群的每台master和worker主机上,运行下列命令
cd /usr/local/share/ca-certificates/
openssl s_client -showcerts -verify 5 -connect gitea.yourdomain.com:443 < /dev/null 2>/dev/null | openssl x509 -outform PEM | tee ca.crt
update-ca-certificates
systemctl restart containerd
把gitea的https证书添加到每台kubernetes主机上。
6.修改kubernetes代理服务器配置(可选)
如果kubernetes为镜像下载设置过代理服务器,那么需要修改配置。
在每台master和worker主机上,编辑文件/etc/systemd/system/containerd.service.d/http-proxy.conf,在NO_PROXY配置中加入gitea服务器的域名。类似于
[Service]
Environment="HTTP_PROXY=http://username:password@proxy-server-ip:port"
Environment="HTTPS_PROXY=http://username:password@proxy-server-ip:port"
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,aliyuncs.com,gitea.yourdomain.com,.svc,.cluster.local,.ewhisper.cn,<nodeCIDR>,<APIServerInternalURL>,<serviceNetworkCIDRs>,<etcdDiscoveryDomain>,<clusterNetworkCIDRs>,<platformSpecific>,<REST_OF_CUSTOM_EXCEPTIONS>"
其中gitea.yourdomain.com是gitea服务器的域名,根据实际情况修改。
然后在每台主机上重启containerd,运行
systemctl daemon-reload
systemctl restart containerd
二、样例部署和测试
1.部署测试案例
登录到gitea的web管理界面,新建一个仓库,名为gitea-action-runner。
在开发主机上运行下列命令,同步代码
git clone http://<gitea-server-ip>:3000/<gitea-username>/gitea-action-runner.git
其中<gitea-server-ip>是gitea服务器的IP地址,<gitea-username>是你在gitea上的账号名,根据实际情况修改。
运行下列命令,安装nodejs
curl -fsSL https://deb.nodesource.com/setup_21.x | sudo -E bash -
sudo apt-get install -y nodejs
运行下列命令,新建一个react应用。
npm create vite@latest gitea-action-runner
选择react和javascript。
运行
cd gitea-action-runner
npm install
修改vite.config.js如下
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
base: "/",
plugins: [react()],
preview: {
port: 5173,
strictPort: true,
},
server: {
port: 5173,
strictPort: true,
host: true,
origin: "http://0.0.0.0:5173",
},
});
运行
npm run build
npm run preview
可以看到web服务的运行情况,ctrl+c退出。
在gitea-action-runner目录下,创建Dockerfile文件,内容如下
#It will use node:21-alpine3.19 as the parent image for
#building the Docker image
FROM node:21-alpine3.19
#It will create a working directory for Docker. The Docker
#image will be created in this working directory.
WORKDIR /app
#Copy the React application dependencies from the
#package.json to the react-app working directory.
COPY package.json .
#install all the React application dependencies
RUN npm i
COPY . .
RUN npm run build
#Expose the React application container on port 5173
EXPOSE 5173
#The command to start the React application container
CMD ["npm", "run", "preview"]
创建deployment.yaml文件,内容如下
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea-react
labels:
app: gitea-react-app
spec:
replicas: 2
selector:
matchLabels:
app: gitea-react-app
template:
metadata:
labels:
app: gitea-react-app
spec:
containers:
- name: gitea-react-app
image: gitea.yourdomain.com/gitea-username/gitea-react-app:latest
ports:
- containerPort: 5173
其中gitea.yourdomain.com是gitea服务器的域名,gitea-username是你在gitea上的账号名,按照实际情况修改。
创建service.yaml文件,内容如下
apiVersion: v1
kind: Service
metadata:
name: gitea-react
spec:
selector:
app: gitea-react-app
type: LoadBalancer
ports:
- protocol: TCP
port: 5173
targetPort: 5173
在gitea-action-runner目录下,新建目录.github/workflows,进入该目录,新建文件workflow.yaml,内容如下
name: Deploy act-react
on:
push:
branches:
- main
env:
REGISTRY_URL: <gitea-server-ip>:3000/<gitea-username>
REGISTRY_SITE: http://<gitea-server-ip>:3000
SERVICE_NAME: gitea-react-app
SERVICE_TAG: latest
jobs:
build:
runs-on: ubuntu-latest
if: gitea.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: https://gitea.com/actions/checkout@v4
- name: Login to Docker Hub
uses: https://gitea.com/docker/login-action@v3
with:
registry: ${{ env.REGISTRY_SITE }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: https://gitea.com/docker/setup-buildx-action@v3
with:
config-inline: |
[registry."<gitea-server-ip>:3000"]
http = true
insecure = true
- name: Build and push orchestration service
uses: https://gitea.com/docker/build-push-action@v5
with:
context: .
tags: |
${{ env.REGISTRY_URL }}/${{ env.SERVICE_NAME }}:${{gitea.sha}}
${{ env.REGISTRY_URL }}/${{ env.SERVICE_NAME }}:latest
push: true
- name: Deploying
uses: http://<gitea-server-ip>:3000/<gitea-username>/kubectl@master
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: apply -f deployment.yaml -f service.yaml
- name: Update image
uses: http://<gitea-server-ip>:3000/<gitea-username>/kubectl@master
env:
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
with:
args: set image deployment/gitea-react ${{ env.SERVICE_NAME }}=<gitea.yourdomain.com>/<gitea-username>/${{ env.SERVICE_NAME }}:${{gitea.sha}}
其中<gitea-server-ip>是gitea服务器的IP地址,gitea.yourdomain.com是gitea服务器的域名,<gitea-username>是你在gitea上的账号,根据实际情况修改。
登录到gitea的web管理界面,进入仓库gitea-action-runner,点击设置->Actions->密钥,添加3个密钥:
DOCKERHUB_USERNAME,值为你在gitea上的账号名。
DOCKERHUB_TOKEN,值为你在gitea上的账号密码。
KUBE_CONFIG,值为kubernetes master主机的config文件内容,通过在master主机上运行 cat $HOME/.kube/config | base64
得到。
登录到gitea的web管理界面,点击右上角的“+”,点击“迁移外部仓库”,选择github,克隆URL填写https://github.com/actions-hub/kubectl ,选中“该仓库将是一个镜像”,点击”迁移仓库”,完成对kubectl action的克隆。
2. 测试自动触发
在gitea-action-runner目录下,运行下列命令,把代码同步到gitea。
git add -A
git commit -m "first commit"
git branch -M main
git push origin main
push操作自动触发了工作流,登录到gitea的web界面,在仓库的actions下面,可以看到工作流的整个运行过程,包括代码检出、docker镜像构建、docker镜像推送,最后把deployment和service部署到kubernetes集群的整个流程。
登录到Kubernetes的master主机,运行
kubectl get deployment
kubectl get svc
可以看到新增的deployment和service,名为gitea-react。
访问http://<gitea-react-svc-ip>:5173 ,可以看到react应用的界面。
<gitea-react-svc-ip>是名为gitea-react的service的外部ip地址,根据实际情况修改。
这样gitea actions就安装部署完成了,每次push代码,就会自动触发运行,完成CI/CD的整个过程。
参考:
https://docs.gitea.com/installation/install-with-docker
https://medium.com/@lokanx/how-to-build-docker-containers-using-gitea-runners-600729555e07