使用 Docker Compose 安装 Gitea

Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。

项目网址:https://github.com/go-gitea/gitea
官方文档: https://docs.gitea.com/zh-cn/

目录

1. 镜像选择

Gitea 提供的镜像包括 标准 和 rootless 。

rootless 镜像使用 Gitea 内部 SSH 功能来提供 Git 协议,不支持 OpenSSH,不需要 root 权限。

项目 标准镜像 rootless 镜像
执行用户 root 非 root
ssh 端口 22 2222
git 用户与组 任意(由配置文件中指定) 1000:1000
openssh 支持 不支持
AppPath /usr/local/bin/gitea /usr/local/bin/gitea
WorkPath /data/gitea /var/lib/gitea
CustomPath /data/gitea /var/lib/gitea/custom
ConfigFile /data/gitea/conf/app.ini /etc/gitea/app.ini

2. 安装部署

2.1. 使用 rootless 镜像

2.1.1. 创建工作目录

docker 自动创建的目录是root 权限,因此需要手动创建目录,以确保权限一致。

rootless 镜像内的git 用户与组的id是1000:1000 ,所以建议主机也使用1000:1000 。

当然了,不一致也没关系,但需要通过user: xxxx:xxxx 指定具体值。

shell
mkdir data config
sudo chown 1000:1000 data config

2.1.2. 创建配置文件

特别注意:data config 文件夹应由user: xxxx:xxxx指定的用户所有,以确保主机能够正常访问这两个文件夹。

shell
services:
  server:
    image: gitea/gitea:1.21-rootless
    container_name: gitea
    hostname: gitea
    restart: always
    user: 1000:1000
    volumes:
      - ./data:/var/lib/gitea
      - ./config:/etc/gitea
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "0.0.0.0:3000:3000"
      - "0.0.0.0:2222:2222"

2.1.3. 启动运行

注意:如果在 HTTP 上使用的是非 3000 端口,请将 app.ini 更改为匹配 LOCAL_ROOT_URL = http://localhost:3000/。

shell
docker compose up -d
docker compose logs -f

2.2. 使用 标准 镜像

2.2.1. 创建工作目录

docker 自动创建的目录是root 权限,因此要手动创建目录。

与 rootless 镜像不同,标准镜像内的 git 用户id可以通过环境变量指定,自由度更高。

shell
mkdir data
chown 1000:1000 data

2.2.2. 创建配置文件

注意事项:

  • data 文件夹应由 environment 指定的用户所有。
  • 只需挂载一个路径 /data ,相比rootless 更简单
  • 支持 openssh 标准 22 端口
  • 特别注意:生成的 ssh 文件夹是 root 权限的,因此主机要有 root 权限。
shell
services:
  server:
    image: gitea/gitea:latest
    container_name: gitea
    hostname: gitea
    restart: always
    environment:
    # - GITEA___server__PROTOCOL=http
    # - GITEA___server__DOMAIN=code.wangyan.cloud/
    # - GITEA___server__ROOT_URL=https://code.wangyan.cloud/
    # - GITEA___server__HTTP_ADDR=0.0.0.0
    # - GITEA___server__HTTP_PORT=3000
    # - GITEA___server__SSH_DOMAIN=wangyan.cloud/
    # - GITEA___server__SSH_PORT=22
    # - GITEA___server__LFS_START_SERVER=true
    # - GITEA__database__DB_TYPE=mysql
    # - GITEA__database__HOST=127.0.0.1:3306
    # - GITEA__database__NAME=gitea
    # - GITEA__database__USER=gitea
    # - GITEA__database__PASSWD=123456
    # - GITEA__mailer__ENABLED=true
    # - GITEA__mailer__PROTOCOL=smtp+starttls
    # - GITEA__mailer__SMTP_ADDR=smtp-mail.outlook.com
    # - GITEA__mailer__SMTP_PORT=587
    # - GITEA__mailer__FROM="No-Reply" <no-reply@outlook.com>
    # - GITEA__mailer__USER=no-reply@outlook.com
    # - GITEA__mailer__PASSWD=123456
      - USER_UID=1000
      - USER_GID=1000
    volumes:
      - ./data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "0.0.0.0:3000:3000"
      - "0.0.0.0:2222:22"

2.2.3. 启动运行

shell
docker compose up -d
docker compose logs -f

3. SSH 容器直通

由于 SSH 在容器内运行,如果需要 SSH 支持,则需要将 SSH 从主机传递到容器。

3.1. 创建 git 用户

这里的git 用户用于ssh 容器透传。如果不需要 git clone git@host:username 功能,可以忽略。

shell
# uid 和 gid 也可以随机不指定。
sudo groupadd -g 1100 git && \
sudo useradd -c "Git Version Control" -m -d /home/git -s /bin/bash -u 1100 -g 1100 git

# 将用户添加到docker用户组
sudo usermod -aG docker git

3.2. 方法一:使用 AuthorizedKeysCommand

该方法最大优点是:通过 AuthorizedKeysCommand 进入容器获取git用户的 authorized_keys,不需要挂载主机的 .ssh 目录到容器。

  1. 客户端执行 git clone 命令后,会进入容器执行 gitea keys 命令,返回用户的 authorized_keys 公钥信息完成认证,该信息是带有 command="/usr/local/bin/gitea 路径的,与容器上 Gitea 二进制文件的位置匹配。
  2. 通过验证后,主机 SSH 服务器为git用户建立会话,并使用主机git用户的 shell 执行后续命令。

3.2.1. Docker 获取 authorized_keys(推荐)

主机使用 docker exec 方式进入容器获取 authorized_keys。

shell
# gitea 是容器名称,请根据实际修改。
# 标准镜像需要加 "-u git" 指定用户,root 身份运行 docker exec 会报错。
cat <<"EOF" | sudo tee -a /etc/ssh/sshd_config
Match User git
  AuthorizedKeysCommandUser git
  AuthorizedKeysCommand /usr/bin/docker exec -i -u git gitea /usr/local/bin/gitea keys -e git -u %u -t %t -k %k
EOF

sudo systemctl restart sshd

3.2.2. SSH 获取 authorized_keys(二选一)

与docker shell 基本一样,不同地方在于没有使用 docker exec 进入容器,而是通过 ssh git@127.0.0.1 进入容器。

此方法需要将容器的 22 端口映射到主机,比如映射为 2222,并且主机git用户要创建一个密钥对,并提前将公钥添加到容器的 /data/git/.ssh/authorized_keys 目录。

shell
cat <<"EOF" | sudo tee -a /etc/ssh/sshd_config
Match User git
  AuthorizedKeysCommandUser git
  AuthorizedKeysCommand /usr/bin/ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 /usr/local/bin/gitea keys -e git -u %u -t %t -k %k
EOF

sudo systemctl restart sshd

3.3. 方法二:共享 authorized_keys

此方法是通过与容器共享 authorized_keys文件的方式来进行用于认证,用于带有 openssh 的标准镜像。

  1. 为了使转发正常工作,需要将容器的 SSH 端口(22)映射到主机端口 2222。
shell
#docker-compose.yml
ports:
  - "127.0.0.1:2222:22"
  1. 接下来要使容器git用户的uid 和 gid 与主机上的git用户一致。
shell
#docker-compose.yml
environment:
  - USER_UID=1000
  - USER_GID=1000
  1. 然后,创建主机与容器互联的密钥。
shell
# 生成 authorized_keys 文件
sudo -u git mkdir /home/git/.ssh/
sudo -u git ssh-keygen -f "/home/git/.ssh/idrsa" -t rsa -b 4096 -C "Gitea Host Key"
sudo -u git echo "$(cat /home/git/.ssh/idrsa.pub)" >> /home/git/.ssh/authorized_keys
sudo -u git chmod 600 /home/git/.ssh/authorized_keys
  1. 接下来将主机/home/git/.ssh挂载到容器中。这可确保authorized_keys文件在主机用户和容器之间共享。
shell
volumes:
  - /home/git/.ssh/:/data/git/.ssh

通过 Gitea 界面添加的所有用户公钥都将有前缀 command="/usr [...]。

/home/git/.ssh/authorized_keys内容如下:

shell
# SSH pubkey from git user
ssh-rsa <Gitea Host Key>

# other keys from users
command="/usr/local/bin/gitea --config=/data/gitea/conf/app.ini serv key-1"...

因此,当客户端执行 git clone 命令时会执行 /usr/local/bin/gitea 文件。

3.4. 转发主机命令到容器

3.4.1. 方法1:shell 方式(推荐)

为了能够在容器内执行命令,我们还需要修改git 用户的默认shell

shell
# gitea 是容器名称,请根据实际修改。
cat <<"EOF" | sudo tee /home/git/docker-shell
#!/bin/sh
/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
EOF

sudo chmod +x /home/git/docker-shell
sudo usermod -s /home/git/docker-shell git

当然,也可以使用下面SSH方式执行。(二选一)

shell
cat <<"EOF" | sudo tee /home/git/ssh-shell
#!/bin/sh
ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $@"
EOF

sudo chmod +x /home/git/ssh-shell
sudo usermod -s /home/git/ssh-shell git

3.4.2. 方法2:Shim 方式

在主机创建虚假gitea可执行文件,该文件将把命令从主机转发到容器。

shell
# gitea 是容器名称,请根据实际修改。
# 与 shell 相比多了 $0
cat <<'EOF' | sudo tee /usr/local/bin/gitea
#!/bin/sh
/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh $0 "$@"
EOF
sudo chmod +x /usr/local/bin/gitea

当然,也可以使用下面SSH方式执行。(二选一)

shell
cat <<"EOF" | sudo tee /usr/local/bin/gitea
#!/bin/sh
ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
EOF
sudo chmod +x /usr/local/bin/gitea

4. Gitea Actions

4.1. Act Runner

4.1.1. 使用二进制文件

shell
# 下载
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.7/act_runner-0.2.7-linux-amd64
mv act_runner-0.2.7-linux-amd64 gitea-runner
chmod +x gitea-runner
./gitea-runner --version

# 导出默认配置文件
./gitea-runner generate-config > config.yaml

# 注册
# ./gitea-runner --config config.yaml register
./gitea-runner register \
 --no-interactive \
 --instance https://codes.wangyan.cloud/ \
 --token xx \
 --name gitea-runner

4.1.2. 使用 Docker 镜像

导出配置文件

shell
sudo docker pull gitea/act_runner:latest
sudo docker run --entrypoint="" --rm -it gitea/act_runner:latest act_runner generate-config > config.yaml

配置 Cache

shell
#vim config.yaml
cache:
enabled: true
dir: ""
# 使用步骤 1. 获取的 LAN IP
host: "192.168.8.17"
# 使用步骤 2. 获取的端口号
port: 3030

运行

shell
#vim docker-compose.yml
version: "3.8"
  services:
    runner:
    image: gitea/act_runner:nightly
    environment:
    CONFIG_FILE: /config.yaml
    GITEA_INSTANCE_URL: "http://119.29.17.197:3000"
    GITEA_RUNNER_REGISTRATION_TOKEN: "xx"
    GITEA_RUNNER_NAME: "gitea-runner"
    volumes:
    - ./config.yaml:/config.yaml
    - ./data:/data
    - /var/run/docker.sock:/var/run/docker.sock
    ports:
    - "3030:3030"

4.2. Actions Demo

shell
vim .gitea/workflows/demo.yaml
yaml
name: Gitea Actions Demo
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [push]
  
jobs:
 Explore-Gitea-Actions:
 runs-on: ubuntu-latest
 steps:
 - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
 - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
 - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
 - name: Check out repository code
 uses: actions/checkout@v3
 - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
 - run: echo "🖥️ The workflow is now ready to test your code on the runner."
 - name: List files in the repository
 run: |
 ls ${{ gitea.workspace }}
 - run: echo "🍏 This job's status is ${{ job.status }}."

参考文档:

ESC