# Docker部署Gitea服务器完整过程

> wandoubaba / 2024-10-29

## 介绍

下面引用 [gitea官方文档](https://docs.gitea.cn/) 中的一段描述：

```
Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期，他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来，几乎所有代码都已更改。
```

## 本文目标

- 仓库、数据库等用户产生数据保存在数据盘中
- 使用postgresql数据库
- 数据库和gitea服务以docker方式启动
- 主机和容器使用22端口实现SSH直通
- 使用域名访问，通过nginx反向代理实现通过80端口访问web UI

> 为了方便，文档中的操作都是在root用户下执行，建议在生产环境中使用普通用户执行操作，在命令前加`sudo`。

## 准备域名

提前准备一个公网域名，指向到下面即将要操作的服务器IP上，后面的操作完成了，域名解析也差不多该生效了。

> 假设我们用的是`gitea.wukezhenzhu.com`，后面配置是用以它为例。

## 准备服务器

本文中我使用了Debian 11，既然是用docker方式部署的，所以几乎不受操作系统限制。

> 接下来的操作是本人一步一步边操作加记录的。

### 挂载数据盘

通过`df -h`、`lsblk`、`fdisk -l`等命令确认当前磁盘和分区状态，下面是结果示例：

```sh
root@debian:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G     0  2.0G   0% /dev
tmpfs           394M  560K  393M   1% /run
/dev/sda1       491G  1.4G  464G   1% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           394M     0  394M   0% /run/user/0
root@debian:~# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  500G  0 disk
├─sda1   8:1    0  499G  0 part /
├─sda2   8:2    0    1K  0 part
└─sda5   8:5    0  975M  0 part [SWAP]
sdb      8:16   0    4T  0 disk
sr0     11:0    1 1024M  0 rom
root@debian:~# fdisk -l
Disk /dev/sdb: 4 TiB, 4398046511104 bytes, 8589934592 sectors
Disk model: Virtual disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sda: 500 GiB, 536870912000 bytes, 1048576000 sectors
Disk model: Virtual disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xac8bf5c9

Device     Boot      Start        End    Sectors  Size Id Type
/dev/sda1  *          2048 1046575103 1046573056  499G 83 Linux
/dev/sda2       1046577150 1048573951    1996802  975M  5 Extended
/dev/sda5       1046577152 1048573951    1996800  975M 82 Linux swa
```

从上面的结果可以看到，系统中有一个名为`/dev/sdb`的4TB硬盘是空闲的，下面我们要把它整个挂载到`/data`目录下：

```sh
root@debian:~# mkfs.ext4 /dev/sdb
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 1073741824 4k blocks and 134217728 inodes
Filesystem UUID: f081b706-f637-4b84-b70b-5521b7ad5b6b
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
	4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
	102400000, 214990848, 512000000, 550731776, 644972544

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

root@debian:~# mkdir /data
root@debian:~# mount -t ext4 /dev/sdb /data
root@debian:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            2.0G     0  2.0G   0% /dev
tmpfs           394M  560K  393M   1% /run
/dev/sda1       491G  1.4G  464G   1% /
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           394M     0  394M   0% /run/user/0
/dev/sdb        4.0T   28K  3.8T   1% /data
```

经过上面的操作，已经把磁盘`/dev/sdb`格式化为ext4文件系统，并成功挂载下`/data`目录下，但是如果现在重启系统后，数据盘还不能自动完成挂载，需要执行下面的操作：

```sh
root@debian:~# ll /dev/disk/by-uuid/
total 0
lrwxrwxrwx 1 root root 10 Apr 21 14:22 0bc1a76e-3457-4e2c-b708-a201e510f343 -> ../../sda1
lrwxrwxrwx 1 root root  9 Apr 21 14:30 f081b706-f637-4b84-b70b-5521b7ad5b6b -> ../../sdb
lrwxrwxrwx 1 root root 10 Apr 21 14:22 ff162b2a-5e9e-4661-854a-64ad11f22fa5 -> ../../sda5

root@debian:~# echo "UUID=f081b706-f637-4b84-b70b-5521b7ad5b6b /data ext4 defaults 0 0" >> /etc/fstab
```

> 上面写入`/etc/fstab`文件中的UUID是在`/dev/disk/by-uuid/`中查到的`sdb`对应的UUID。

可以试着`reboot`一下，重启后数据盘会自动完成挂载。

> 操作系统的准备工作已经完成，但是我们建议中国大陆用户要为系统配置一组高速的软件源，配置文件位置`/etc/apt/sources.list`，本文不对展开讲解。

### 准备docker环境

> 按照docker官方文档安装[Docker Engine](https://docs.docker.com/engine/install/debian/)和[Docker Compose](https://docs.docker.com/compose/install/other/)。

```sh
# 卸载原有旧版本的docker（新系统可以跳过）
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
# 安装ca支持
sudo apt-get update && sudo apt-get install ca-certificates curl gnupg
# 配置docker官方GPG密钥
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 配置docker官方软件源
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装docker engine
sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 单独安装docker-compose（不执行后面这步，使用docker compose [command]也是可以的）
curl -SL https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# 查看docker版本
docker version
# 查看docker-compose版本
docker-compose version
```

对于国内服务器，给docker hub配置几个加速源是必要的操作，[阿里云容器镜像服务-镜像加速器](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)。

除了阿里云，也可以试试下面的加速源：

- https://registry.docker-cn.com
- https://hub-mirror.c.163.com

### 部署gitea和postgresql服务

#### 配置nginx实现反向代理

我们希望实现的是通过网址http://gitea.wukezhenzhu.com直接访问gitea的web UI，而gitea服务默认使用的http端口是3000，为了不过多更改服务配置，我们只要用nginx做一层指向127.0.0.1:3000端口的反向代理即可，具体如何操作本文不展开。

#### 创建git专用的系统账号和分组

```sh
# 创建git分组和git用户
adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git

# 记录下返回结果中的UID和GID，如：
Adding system user `git' (UID 112) ...
Adding new group `git' (GID 117) ...
Adding new user `git' (UID 112) with group `git' ...

# 为git用户生成ssh-key
sudo -u git ssh-keygen -t rsa -b 4096 -C "Gitea Host Key"
```

#### 为主机和容器建立SSH直通

创建名为`/usr/local/bin/gitea`的可执行文件，文件内容：

```shell
ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
```

为`/usr/local/bin/gitea`文件添加可执行权限：

```sh
chmod +x /usr/local/bin/gitea
```

把git用户的ssh公钥添加到`/home/git/.ssh/authorized_keys`中（因为主机的`/home/git/.ssh/`会映射到容器中）

```sh
echo "$(cat /home/git/.ssh/id_rsa.pub)" >> /home/git/.ssh/authorized_keys
```

#### 准备docker-compose.yml文件

创建`/data/docker-compose.yml`文件，内容如下（随着时间推移，可以试着改变镜像的版本），注意修改`USER_UID`和`USER_GID`为实际值：

```yml
version: "3"

networks:
  gitea:
    external: false

services:
  gitea:
    image: gitea/gitea:1.19
    container_name: gitea
    environment:
      - USER_UID=112
      - USER_GID=117
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=gitea_db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=gitea
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - /home/git/.ssh/:/data/git/.ssh
    ports:
      - "3000:3000"
      - "127.0.0.1:2222:22"
    depends_on:
      - gitea_db
  gitea_db:
    image: postgres:14
    container_name: gitea_db
    restart: always
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=gitea
      - POSTGRES_DB=gitea
    networks:
      - gitea
    volumes:
      - ./postgres:/var/lib/postgresql/data
```

在/data目录下执行：

```sh
docker compose up
```

如果在编排期间没有提示错误的话，说明我们在服务器端的部署工作基本完成了，下面进入web安装与配置阶段。

#### 通过Web UI完成服务安装与配置

假设最开始做的域名解析已经生效了，接下来打开浏览器访问gitea.wukezhenzhu.com（如果打不开页面，检查检查域名解析、服务器防火墙、nginx代理）：

```
http://gitea.wukezhenzhu.com
```

- 数据库设置：都使用默认值就行（因为我们没有把pg的5432端口映射给主机，所以基本也不需要给数据库设置强口令）。
- 站点名称：会显示在Web首页和浏览器标题栏
- 仓库根目录：默认
- LFS根目录：默认
- 以用户名运行：默认（git）
- 服务器域名：就是刚才解析的域名，文本中是gitea.wukezhenzhu.com
- SSH服务端口：22
- HTTP服务端口：3000
- 基础URL：如果这里是带:3000端口号的url，我们就把端口号去掉，就是http://gitea.wukezhenzhu.com/。
- 日志路径：默认
- 启用更新检查：不勾选，因为我们用的是docker，即使在线更新了，容器重启后也会把程序重置。
- 电子邮箱设置：建议配置并开启邮件确认注册和邮件通知提醒
- 第三方服务设置：根据情况
- 管理账号设置：根据情况

完成以上配置后，直接点“立即安装”，然后等待一小会，页面会自动以管理员登录（如果创建了管理员），或者进入到gitea的登录页。

#### 以daemon方式重新启动服务

在服务器上按ctrl+c停止docker服务，再重启执行一遍docker-compose命令，这次后面加上-d。

```sh
docker compose up -d
```

好了，大功告成！
