如何使用Docker在Ubuntu上安装Gitea

来自菜鸟教程
跳转至:导航、​搜索

介绍

在进行软件开发时,能够以高效且可追溯的方式管理源代码非常重要。 源代码管理 (SCM) 系统是一种出色的方式,可以为与任意数量的开发人员一起处理任意规模的项目提供高效和灵活的流程。 多年来,已经存在许多不同的 SCM 软件,从 CVS 到 SubVersion,从 Perforce 到 Mercurial,但目前的行业领导者是 Git,随着 GitHub 和 GitLab 等网站的普及,它已经有了很大的增长.

但是,由于这些服务的免费帐户面向公共、开源存储库,因此使用私有或专有软件的能力会给开发人员带来成本。 此外,一个人对存储库的访问受制于外部组织,许多人更愿意从头到尾控制自己的软件。

为此,在过去几年中已经开发了几种自托管解决方案,例如 GogsGiteaGitLab。 本教程侧重于设置更流行的解决方案之一,Gitea,以允许您托管私有存储库并在其整个生命周期中管理您自己的项目。 Gitea 体积小、独立且轻巧,使其成为一个快速部署过程,而不会因硬件要求而耗费大量资金。 您将使用 Gitea 的 Docker 安装,以确保软件保持最新。

先决条件

在开始本教程之前,您应该具备以下条件:

  • Ubuntu 20.04 服务器,非 root 用户配置了 sudo 权限,如 Ubuntu 20.04 初始服务器设置中所述。
  • Docker 安装在您的服务器上。 按照如何在Ubuntu 20.04上安装Docker的步骤1和2安装Docker。
  • Docker Compose 安装在您的服务器上。 按照我们关于 如何在 Ubuntu 20.04 上安装和使用 Docker Compose 的指南的 Step 1 进行设置。
  • 指向您的服务器的域名。 如果您使用的是 DigitalOcean Droplet,您可以按照我们的 Domains 和 DNS 文档来完成此操作。 本教程将在整个示例中使用 your_domain

第 1 步——创建 Git 用户

与许多源代码存储库一样,Gitea 使用 SSH 访问远程存储库。 这允许用户通过在 Gitea 内部管理他们的 SSH 密钥来控制对其代码的访问。 但是,为了让用户能够通过 SSH 访问主机,您需要在主机上创建一个 git 用户。 此步骤首先完成,以便您可以访问用户的用户和组 ID。

首先,在主机上创建将接受这些连接的用户:

sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git

在此命令中,您创建一个使用 bash 作为其 shell,但没有登录密码的系统用户。 这允许您使用 sudo 以该用户身份运行命令,但阻止以该用户身份登录。 您还将用户的主目录设置为 /home/git

此命令将输出有关它刚刚创建的用户的一些信息:

OutputAdding system user `git' (UID 112) ...
Adding new group `git' (GID 119) ...
Adding new user `git' (UID 112) with group `git' ...
Creating home directory `/home/git' …

记下此处提供的 UID 和 GID 值(在本例中,UID 为 112 和 GID 为 119),因为它们将在以后的步骤中使用。

第 2 步 — 安装 Gitea Docker 镜像

Gitea 在全球 Docker 存储库中有一个可用的映像,这意味着,使用 Docker Compose,您可以安装和运行该映像作为服务,而无需额外的工作。 镜像本身运行 Gitea web 和 SSH 服务,允许 Git 从浏览器和命令行访问。

为了启动 Gitea 容器,您将使用 Docker Compose,这是一个用于设置环境的声明性工具。

首先,创建一个目录来托管您的服务并输入它:

mkdir ~/gitea
cd ~/gitea

在那里,使用您喜欢的文本编辑器创建一个名为 docker-compose.yml 的文件。 以下示例使用 nano。 此文件将包含将作为 Gitea 安装的一部分运行的容器的描述:

nano docker-compose.yml

将以下内容添加到这个新文件中:

~/gitea/docker-compose.yml

version: "3"

networks:
  gitea:
    external: false

services:
  server:
    image: gitea/gitea:1.16.5
    container_name: gitea
    environment:
      - USER_UID=UID_from_step_1
      - USER_GID=GID_from_step_1
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /home/git/.ssh/:/data/git/.ssh
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "127.0.0.1:3000:3000"
      - "127.0.0.1:2222:22"

让我们看一下这个文件的作用:

  • version: "3":这让 Docker Compose 这是什么版本的配置文件。
  • networks:这部分声明了我们的容器集合的网络设置。 在这种情况下,会创建一个 gitea 网络,但不会对外暴露。
  • services
    • image: gitea/gitea:1.16.5:这指定我们将使用 Gitea 版本 1.16.5; 但是,您可以更改冒号后的值以指定其他版本,无论是特定版本、主要版本(例如 :1)还是标签(例如 :latest:dev)。
    • environment:环境部分指定在安装和运行期间可用于映像的环境变量。 在这种情况下,我们使用步骤 1 中 adduser 命令的输出中提供的 UID 和 GID 为环境指定用户和组 ID。
    • restart: always:这一行指示 Docker 在容器宕机时总是重启容器,无论是因为容器本身宕机还是主机宕机; 本质上,Gitea 将在启动时启动。
    • networks:这指定 Gitea 服务将有权访问并可以在上述网络上访问。
    • ./gitea:/data/home/git/.ssh/:/data/git/.ssh:这些是 Gitea 将存储其存储库和相关数据的位置。 目前,它映射到当前目录中名为 gitea 的文件夹。 如果容器不存在,Docker 将在容器启动时创建此文件夹。 .ssh 文件夹将在后面的步骤 6 中进一步描述。
    • /etc/timezone/etc/localtime:这两个文件包含有关主机上的时区和时间的信息。 通过将这些作为只读文件直接映射到容器中(使用定义的最后 :ro 部分指定),容器将具有与主机相同的信息。
    • ports:Gitea 监听两个端口的连接。 它侦听端口 3000 上的 HTTP 连接,它为源代码存储库提供 Web 界面,并侦听端口 22 上的 SSH 连接。 在这种情况下,您通过将端口 3000 映射到相同的编号来为 HTTP 连接保留端口,并且您将 Gitea 容器上的端口从通常的 22 映射到 2222以避免端口冲突。 在第 6 步中,您将设置一个 SSH shim,以便在请求时将流量定向到 Gitea。

注意: 这是一个用于 Gitea 的 Docker Compose 文件的最小示例。 还可以包括其他几个选项,例如使用 MySQL 或 PostGreSQL 作为后备数据库或使用命名卷进行存储。 这个最小设置使用 SQLite 作为后备数据库,使用名为 gitea 的目录进行存储的卷。 您可以在 Gitea 的文档 中阅读有关这些选项的更多信息。


保存并关闭文件。 如果您使用 nano 编辑文件,您可以按 CTRL + XY,然后按 ENTER 进行编辑。

有了这个文件,您就可以使用 Docker Compose 启动容器:

docker-compose up

此命令将拉下图像,启动 Gitea 容器,并返回如下输出:

Output[+] Running 9/9
 ⠿ server Pulled                                                                                                  8.2s
   ⠿ e1096b72685a Pull complete                                                                                   1.4s
   ⠿ ac9df86bb932 Pull complete                                                                                   3.3s
   ⠿ 6d34ed99b58a Pull complete                                                                                   3.4s
   ⠿ a8913d040fab Pull complete                                                                                   3.6s
   ⠿ a5d3a72a2366 Pull complete                                                                                   5.3s
   ⠿ 1f0dcaae29cc Pull complete                                                                                   5.6s
   ⠿ f284bcea5adb Pull complete                                                                                   7.3s
   ⠿ 0f09c34c97e3 Pull complete                                                                                   7.5s
[+] Running 2/2
 ⠿ Network gitea_gitea  Created                                                                                   0.2s
 ⠿ Container gitea      Created                                                                                   0.2s
Attaching to gitea
gitea  | Generating /data/ssh/ssh_host_ed25519_key...
gitea  | Generating /data/ssh/ssh_host_rsa_key...
gitea  | Generating /data/ssh/ssh_host_dsa_key...
gitea  | Generating /data/ssh/ssh_host_ecdsa_key...
gitea  | Server listening on :: port 22.
gitea  | Server listening on 0.0.0.0 port 22.
gitea  | 2022/03/31 17:26:21 cmd/web.go:102:runWeb() [I] Starting Gitea on PID: 14
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:21:PreloadSettings() [I] AppPath: /usr/local/bin/gitea
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:22:PreloadSettings() [I] AppWorkPath: /app/gitea
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:23:PreloadSettings() [I] Custom path: /data/gitea
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:24:PreloadSettings() [I] Log path: /data/gitea/log
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:25:PreloadSettings() [I] Configuration file: /data/gitea/conf/app.ini
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:26:PreloadSettings() [I] Prepare to run install page
gitea  | 2022/03/31 17:26:21 ...s/install/setting.go:29:PreloadSettings() [I] SQLite3 is supported
gitea  | 2022/03/31 17:26:21 cmd/web.go:208:listen() [I] Listen: http://0.0.0.0:3000
gitea  | 2022/03/31 17:26:21 cmd/web.go:212:listen() [I] AppURL(ROOT_URL): http://localhost:3000/

但是,这将使容器在前台运行,并且一旦您使用 Ctrl + C 退出进程或失去连接,它将立即停止。 为了让容器作为单独的进程在后台运行,您可以将 -d 标志附加到 Compose 命令:

docker-compose up -d

当容器启动然后返回到您的 shell 时,您将收到通知。

第 3 步 — 安装 Nginx 作为反向代理

在反向代理后面运行 Web 服务(如 Gitea)是常见的做法,因为现代服务器软件(如 Apache 或 Nginx)可以更轻松地在一台机器上处理多个服务、平衡多个服务器之间的负载以及处理 SSL。 此外,这将允许您设置一个指向在标准 HTTP(S) 端口上运行的 Gitea 实例的域名。

出于本教程的目的,我们将使用 Nginx。 首先,更新主机上的软件包列表:

sudo apt update

接下来,使用 apt 安装 Nginx:

sudo apt install nginx

现在,当您使用防火墙 ufw 时,您需要允许访问这些端口:

sudo ufw allow "Nginx Full"

安装完成后,您应该可以通过访问 http://your_domain 在浏览器中访问您的服务器。 这将引导您进入一个非常简单的页面,欢迎您使用 Nginx。

此时,您需要创建一个反向代理条目,以将通过 Nginx 的传入流量引导到在 Docker 中运行的 Gitea 实例。 使用您喜欢的文本编辑器在 Nginx sites-available 目录中创建一个新文件。 以下示例使用 nano

sudo nano /etc/nginx/sites-available/gitea

在此文件中,设置一个新的服务器块,其中包含向您的 Gitea 实例代理的 / 的请求:

/etc/nginx/sites-available/gitea

server {
    # Listen for requests on your domain/IP address.
    server_name your_domain;

    root /var/www/html;

    location / {
        # Proxy all requests to Gitea running on port 3000
        proxy_pass http://localhost:3000;
        
        # Pass on information about the requests to the proxied service using headers
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

完成文件编辑后,保存并关闭它。

注意: 有关了解这些指令中发生了什么的更多信息,请参阅了解 Nginx HTTP 代理、负载平衡、缓冲和缓存 教程。


Nginx 根据这些文件是否存在于其 sites-enabled 目录中来确定它将实际服务的站点。 这是通过指向 sites-available 目录中文件的符号链接进行管理的。 您需要为 Nginx 创建其中一个符号链接以开始为 Gitea 提供服务:

sudo ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/gitea

在重新启动 Nginx 以使更改生效之前,您应该让 Nginx 本身通过测试其配置来检查这些更改是否有效。

sudo nginx -t

如果一切正常,此命令将返回如下输出:

Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

如果有任何问题,它会告诉您它们是什么以及它们在哪里。

当您准备好继续进行此更改时,请重新启动 Nginx 系统服务:

sudo systemctl restart nginx

现在,当您在浏览器中访问 http://your_domain 时,您应该会发现自己进入了 Gitea 的初始设置页面,可供您填写。

第 4 步 — 安装 Certbot 并设置 TLS 证书

感谢 Certbot 和 Let's Encrypt 免费证书颁发机构,将 TLS 加密添加到您的 Gitea 安装应用程序只需两个命令。

首先,安装 Certbot 及其 Nginx 插件:

sudo apt install certbot python3-certbot-nginx

接下来,在 --nginx 模式下运行 certbot,并指定您在 Nginx server_name 配置指令中使用的相同域:

sudo certbot --nginx -d your_domain_here

系统将提示您同意 Let's Encrypt 服务条款,并输入电子邮件地址。

之后,系统会询问您是否要将所有 HTTP 流量重定向到 HTTPS。 这取决于您,但通常建议这样做并且安全。

之后,Let's Encrypt 将确认您的请求,Certbot 将下载您的证书:

OutputCongratulations! You have successfully enabled https://your_domain

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=your_domain
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/your_domain/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/your_domain/privkey.pem
   Your cert will expire on 2022-05-09. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Certbot 将使用新的配置和证书自动重新加载 Nginx。 在浏览器中重新加载您的网站,如果您选择重定向选项,它应该会自动将您切换到 HTTPS。

您的站点现在是安全的,可以安全地继续执行基于 Web 的设置步骤。

您可以在 How to Secure Nginx with Let's Encrypt on Ubuntu 20.04 教程中找到有关使用 Let's Encrypt 保护域的更多信息。

第 5 步 — 配置 Gitea 并添加第一个用户

现在您可以继续配置 Gitea 本身并创建第一个管理员用户。 通过在浏览器中打开 https://your_domain 访问您的 Gitea 实例。 在初始 Gitea 配置屏幕上,该服务将有几个选项:

其中一些(例如站点标题)取决于您的特定用例,但出于本教程的目的,您需要更改以下内容:

  • 服务器域:第三步设置的服务器域
  • Gitea Base URL: 用于在浏览器中访问 Gitea 的完整 URL,包括协议。 例如,https://your_domain

保存配置更改后,您将被定向到 Gitea 登录页面。

注意:配置保存后,Gitea服务会重启。 由于这可能需要几秒钟,您可能会遇到 Nginx 错误,指出 502 Bad Gateway。 如果确实遇到此错误,请等待几秒钟并重新启动页面。


由于您还没有用户,因此您需要先创建一个。 点击需要一个帐户? 现在注册登录表单下方的链接以注册新用户。 作为系统上的第一个用户,该用户将被创建为管理员。 如果您在配置屏幕上设置电子邮件设置,您可能需要先验证您的帐户。

以该用户身份登录后,单击页面右上角的用户图标,然后从下拉菜单中单击 站点管理 将带您进入一个页面,您将在该页面能够运行维护作业,管理用户帐户和组织,并进一步配置 Gitea。

创建测试存储库

为了测试 Gitea,无论是在 Web 界面上还是使用 Git 本身,都需要创建一个测试存储库。 您以后可以随时删除此存储库。

点击页面右上角的【X13X】+【X18X】标志,然后在下拉菜单中点击【X86X】+新建仓库【X106X】。 在这里,您将看到一个屏幕,允许您使用诸如描述、设置(例如是否为私有)以及任何默认内容(例如 README.gitignore 文件。

一旦你点击 Create Repository,你将有一个新的存储库可以玩。

第 6 步 — 配置 SSH Shim

该过程的最后一步是使用 SSH 垫片准备主机。 因为 Gitea 在 Docker 容器中运行,所以它不能接受默认端口 22 上的 SSH 连接,因为这会与主机冲突。 在上面创建的 docker-compose.yml 文件中,指示 Docker 将主机上的端口映射到容器上的端口 22,以便它接受到端口 2222 的 SSH 连接。 此外,默认情况下,SSH authorized_keys 文件将无法被通过 SSH 连接到主机的人访问。

为了考虑到这一点,您需要创建一个 SSH 垫片,它将 SSH 连接传递给主机上的 git 用户到容器。 在 compose 文件中,您还指定容器中的 USER 的用户和组 ID 为 1000,并且在 Gitea 配置屏幕上,您告诉服务使用名为 git 的用户。

创建 Git 用户及其 SSH 密钥

接下来,您需要为用户创建一个 SSH 密钥。 这只会在下面的步骤中使用,不会与主机之外的任何人共享。

sudo -u git ssh-keygen -t rsa -b 4096 -C "Gitea Host Key"

此命令使用 sudo 作为您在上面创建的用户创建 SSH 密钥。 在这种情况下,密钥将是 4096 位 RSA 密钥。 您将被问到一系列问题,例如您希望密钥的密码以及密钥文件的名称。 为它们中的每一个点击 ENTER,将它们留空以接受默认值。

警告:如果您在密钥上设置密码,您将无法使用 shim。


您需要确保 Gitea 容器中的用户将接受此密钥。 您可以通过将其添加到 .ssh/authorized_keys 文件来执行此操作:

sudo -u git cat /home/git/.ssh/id_rsa.pub | sudo -u git tee -a /home/git/.ssh/authorized_keys
sudo -u git chmod 600 /home/git/.ssh/authorized_keys

这些命令都适用于 shim,因为主机上的目录 /home/git/.ssh 作为卷安装在容器上,这意味着内容在它们之间共享。 当收到通过 SSH 通过 git 与主机的连接时,它将使用与容器相同的 authorized_keys 文件。

创建 SSH Shim 脚本

填充程序的最后一步是在主机上创建存根 gitea 命令。 这就是允许 git 命令通过 SSH 工作的原因:当建立 SSH 连接时,将运行默认命令。 主机上的这个 gitea 命令将代理 SSH 连接到容器。

对于此脚本,使用 cat 写入文件 /usr/local/bin/gitea

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

此脚本中的命令通过 SSH 连接到 Gitea Docker 容器,传递 git 使用的原始命令的内容。

最后,确保脚本是可执行的:

sudo chmod +x /usr/local/bin/gitea

测试 Git SSH 连接

您可以通过将 SSH 密钥添加到您的 Gitea 用户来测试从您的 Gitea 实例上的 Git 存储库中拉取和推送。

您将需要 SSH 公钥的内容。 这通常存在于一个名为 ~/.ssh/id_rsa.pub 的文件中,具体取决于您在创建密钥时使用的算法:

cat ~/.ssh/id_rsa.pub

注意:如果你第一次需要创建一个SSH密钥,你可以通过这个如何在Ubuntu 20.04上设置SSH密钥来学习如何做。


复制此命令的输出。

在 Gitea 中,单击右上角的用户图标,然后选择 Settings。 在设置页面上,顶部会有一系列选项卡。 点击 SSH/GPG Keys,然后点击 Manage SSH Keys 旁边的 Add Key 按钮。 将您的密钥粘贴到表单中的大文本区域,然后单击其下方的 Add Key 按钮。

现在,导航到您在第 3 步中创建的测试存储库并复制提供的 SSH URL。 在您的本地计算机上,克隆存储库:

git clone git@your_domain:username/test

这将使用 SSH 克隆存储库。 如果您在 SSH 密钥上设置了密码,系统会要求您提供该密码。

移动到该目录,创建一个新文件:

cd test
touch just_testing

接下来,将其添加到您的阶段性更改中:

git add just_testing

最后,提交该文件:

git commit -am "Just testing pushing over SSH!"

现在,您应该能够将更改推送到远程存储库:

git push origin master

当您在浏览器中刷新页面时,您的新文件将出现在存储库中。

结论

您已经使用 Docker 设置了一个 Gitea 服务,以便自托管您的源代码存储库。 从这里开始,您将能够使用熟悉的工作流程(例如拉取请求代码审查和按组织组织的项目)处理公共和私有存储库。 Gitea 还可以很好地与各种持续集成和部署 (CI/CD) 工具配合使用,例如 Drone、Jenkins 和 GoCD。 此外,使用诸如此类的 Docker 卷允许您扩展存储以适应网络或块存储上的 Git LFS(大文件存储)内容。