---
title: "Docker 安装 Shlink 自建短网址"
tags: ['Debian', 'Ubuntu', 'Shlink', 'Docker', 'Docker Compose']
published: 2022-04-27 03:51:25
updated: 2026-01-18 00:00:00
excerpt: "本文将指导使用 Docker 安装 Shlink 搭建自建短网址服务。"
---
> 本文件是烧饼博客文章的 Markdown 原文，正式版本见 https://u.sb/docker-shlink/
> 全站文章与页面索引见 https://u.sb/llms.txt，建议先读索引再继续抓取。

本文将指导使用 Docker 安装 Shlink 搭建自建短网址服务。

以下操作需要 root 权限，本文命令均已带上 `sudo` 前缀，请确保当前用户拥有 `sudo` 权限；或者直接使用 root 用户操作并省略命令中的 `sudo`。其中 `docker` 命令未加 `sudo`：建议把当前用户加入 `docker` 用户组（`sudo usermod -aG docker $USER`，重新登录生效），或自行为 `docker` 命令加上 `sudo`。

*PS：本文同时适用于任何可安装 Docker 的 Linux 发行版。*

## 什么是短网址？

短网址，即 URL Shortener (缩略网址服务)，一般我们使用 `HTTP 协议` 的 `301` 或 `302` 响应码，现在也有使用 `307` 或 `308` 来跳转一个长网址，简单的区别：

| 状态码 | 名称 | 是否永久 | 是否保留请求方法 | 浏览器缓存 |
|:---:|:---|:---:|:---:|:---:|
| 301 | Moved Permanently | ✅ 永久 | ❌ 可能改为 GET | 会缓存 |
| 302 | Found | ❌ 临时 | ❌ 可能改为 GET | 不缓存 |
| 307 | Temporary Redirect | ❌ 临时 | ✅ 保留 | 不缓存 |
| 308 | Permanent Redirect | ✅ 永久 | ✅ 保留 | 会缓存 |

MDN 上有对这几个状态码的详细介绍：

- [301 Moved Permanently](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/301)
- [302 Found](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/302)
- [307 Temporary Redirect](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/307)
- [308 Permanent Redirect](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/308)

`301` 和 `302` 有一个最重要的区别，前者会在浏览器留下缓存，后者不会，导致如果你需要精确的统计访客，尤其是有一些使用一个浏览器的重复访客会不准确，但是影响不大，而使用 `302` 每次都会请求服务器造成服务器资源紧张，所以一般没有特殊需求的话，使用 `301` 就行。

举一个典型的 `301` 跳转的例子：

```bash
root@debian ~ # curl -I http://u.sb/ -A Mozilla
HTTP/1.1 301 Moved Permanently
Date: Tue, 26 Apr 2022 18:28:14 GMT
Content-Type: text/html
Content-Length: 162
Location: https://u.sb/
```

我们可以看到，使用浏览器访问 `http://u.sb/` 的时候，会返回 `HTTP/1.1 301 Moved Permanently` 状态，对应跳转到 Location `https://u.sb/`。

## 市面上开源和收费的短网址源码

众所周知，本人的短域名贼多，对各种短网址程序都有所研究，市面上主要有这几款免费的短网址程序：

- [Blink](https://docs.blink.rest) - Easy-to-host，SSO-integrated，CDN-powered link shortener (+decoupled analytics) for teams。([Source Code](https://github.com/JaneJeon/blink)) `AGPL-3.0` `Nodejs`
- [Kutt](https://kutt.it) - A modern URL shortener with support for custom domains。([Source Code](https://github.com/thedevs-network/kutt)) `MIT` `Nodejs`
- [Polr](https://project.polr.me/) - Modern，minimalist，modular，and lightweight URL shortener。([Source Code](https://github.com/Cydrobolt/polr)) `GPL-2.0` `PHP`
- [Shlink](https://shlink.io) - URL shortener with REST API and command line interface。Includes official progressive web application and docker images。([Source Code](https://github.com/shlinkio/shlink)，[Clients](https://shlink.io/apps)) `MIT` `PHP`
- [YOURLS](https://yourls.org/) - YOURLS is a set of PHP scripts that will allow you to run Your Own URL Shortener。Features include password protection，URL customization，bookmarklets，statistics，API，plugins，jsonp。([Source Code](https://github.com/YOURLS/YOURLS)) `MIT` `PHP`

我基本上都安装使用过，数据量大了以后性能基本惨不忍睹，对比以后还是使用 [PHP Swoole](https://www.php.net/manual/en/intro.swoole.php) 写的 [Shlink](https://shlink.io) 稍微占优，所以本文推荐安装 Shlink。

~~至于收费的？呵呵，没一个好用的，建议别去踩坑，我都帮你们踩过了。。。~~

广告：因为市面上没有好用的收费短网址，所以我们做了一个 [S.EE](https://s.ee/) 欢迎购买使用~

## 安装 Docker 和 Docker Compose

Debian 和 Ubuntu 系统请参考[本站教程](/debian-install-docker/)。

其他 Linux 系统可以使用 Docker 官方的脚本安装 Docker 和 Docker Compose：

```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```

## 安装 Shlink Server 和 Web Client

参考官网的[安装教程](https://shlink.io/documentation/install-docker-image/)，我们可以把 Server 和 Web Client 装在一个地方方便管理。

首先我们新建 `/opt/shlink` 和 `/opt/shlink/data` 目录：

```bash
sudo mkdir -p /opt/shlink
sudo mkdir -p /opt/shlink/data
```

然后我们新建一个 `compose.yaml` 文件，假设你的域名是 `example.com`，放在 `/opt/shlink/compose.yaml`：

```bash
sudo bash -c 'cat > /opt/shlink/compose.yaml << EOF
services:
    shlink:
      image: shlinkio/shlink:stable
      container_name: shlink
      ports:
        - 127.0.0.1:8080:8080
      environment:
        - DEFAULT_DOMAIN=example.com
        - IS_HTTPS_ENABLED=true
        - GEOLITE_LICENSE_KEY=
        - DB_DRIVER=maria
        - DB_NAME=shlink
        - DB_USER=shlink
        - DB_PASSWORD=随机密码1
        - DB_HOST=db
        - DB_PORT=3306
        - TIMEZONE=UTC
        - REDIRECT_STATUS_CODE=301
      depends_on:
        db:
          condition: service_healthy
      restart: always

    db:
      image: mariadb:lts
      container_name: db
      ports:
        - 127.0.0.1:3306:3306
      environment:
        - MYSQL_ROOT_PASSWORD=随机密码2
        - MYSQL_DATABASE=shlink
        - MYSQL_USER=shlink
        - MYSQL_PASSWORD=随机密码1
      volumes:
        - /opt/shlink/data:/var/lib/mysql
      healthcheck:
        test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
        interval: 10s
        timeout: 5s
        retries: 3
        start_period: 30s
      restart: always

    shlink-web-client:
        image: shlinkio/shlink-web-client:stable
        container_name: shlink-web-client
        ports:
          - 127.0.0.1:8081:8080
        restart: always
EOF'
```

如果希望有用户登录等功能，则可以用官方的下一代面板 [shlink-dashboard](https://github.com/shlinkio/shlink-dashboard)，这里我们可以让 `shlink-dashboard` 容器和 `shlink` 容器共用一个 MariaDB 容器和用户，首先还是一样建立 docker compose 文件：

```bash
sudo bash -c 'cat > /opt/shlink/compose.yaml << EOF
services:
    shlink:
      image: shlinkio/shlink:stable
      container_name: shlink
      ports:
        - 127.0.0.1:8080:8080
      environment:
        - DEFAULT_DOMAIN=example.com
        - IS_HTTPS_ENABLED=true
        - GEOLITE_LICENSE_KEY=
        - DB_DRIVER=maria
        - DB_NAME=shlink
        - DB_USER=shlink
        - DB_PASSWORD=随机密码1
        - DB_HOST=db
        - DB_PORT=3306
        - TIMEZONE=UTC
        - REDIRECT_STATUS_CODE=301
      depends_on:
        db:
          condition: service_healthy
      restart: always

    db:
      image: mariadb:lts
      container_name: db
      ports:
        - 127.0.0.1:3306:3306
      environment:
        - MYSQL_ROOT_PASSWORD=随机密码2
        - MYSQL_DATABASE=shlink
        - MYSQL_USER=shlink
        - MYSQL_PASSWORD=随机密码1
      volumes:
        - /opt/shlink/data:/var/lib/mysql
        - /opt/shlink/mariadb-init:/docker-entrypoint-initdb.d
      healthcheck:
        test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
        interval: 10s
        timeout: 5s
        retries: 3
        start_period: 30s
      restart: always

    shlink-dashboard:
      image: shlinkio/shlink-dashboard:stable
      container_name: shlink-dashboard
      ports:
        - '127.0.0.1:8081:8080'
      environment:
        - SHLINK_DASHBOARD_DB_DRIVER=mariadb
        - SHLINK_DASHBOARD_DB_HOST=db
        - SHLINK_DASHBOARD_DB_PORT=3306
        - SHLINK_DASHBOARD_DB_USER=shlink
        - SHLINK_DASHBOARD_DB_PASSWORD=随机密码1
        - SHLINK_DASHBOARD_DB_NAME=shlink-dashboard
        - SHLINK_DASHBOARD_SESSION_SECRETS=secret1,secret2  # 设置会话加密，需要设置多个高强度随机值，用半角逗号隔开
      depends_on:
        db:
          condition: service_healthy
      restart: always
EOF'
```

然后创建一个 `/opt/shlink/mariadb-init/01-create-databases.sql` 文件

```bash
sudo mkdir -p /opt/shlink/mariadb-init

sudo tee /opt/shlink/mariadb-init/01-create-databases.sql > /dev/null << 'EOF'
CREATE DATABASE IF NOT EXISTS `shlink-dashboard`;
GRANT ALL PRIVILEGES ON `shlink-dashboard`.* TO 'shlink'@'%';
FLUSH PRIVILEGES;
EOF
```

然后我们可以先启动 MariaDB 容器创建用户和数据库：

```bash
cd /opt/shlink
docker compose up db -d
```

验证下是否成功：

```bash
docker exec -it db mariadb -u root -p'随机密码2' -e "SHOW DATABASES;"
```

看到有 `shlink` 和 `shlink-dashboard` 两个数据库就成功了：

```bash
# docker exec -it db mariadb -u root -p'随机密码2' -e "SHOW DATABASES;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| shlink             |
| shlink-dashboard   |
| sys                |
+--------------------+
```

注意：

`GEOLITE_LICENSE_KEY` 需要在 [Maxmind](https://www.maxmind.com/) 注册帐号获取，可以参考《[使用 Docker 安装 Plausible Analytics 自建网站统计](/docker-plausible/#%E5%AE%89%E8%A3%85-plausible-analytics-t2)》

`MYSQL_ROOT_PASSWORD` 和 `MYSQL_PASSWORD` 记得设置两个随机的密码，同时 `MYSQL_PASSWORD` 需要和 `DB_PASSWORD` 一致。

更多的环境变量参数可以参考[这里](https://shlink.io/documentation/environment-variables/)。

然后拉取所有的 Docker 镜像并运行：

```bash
docker compose pull
docker compose up -d
```

然后获取一个 API Key：

```bash
docker exec -it shlink shlink api-key:generate
```

![shlink api-key:generate 生成 API Key 的终端输出](https://s.bh.sb/uploads/2022/04/27/F3ehKWInwVkqQdD.png)

注意第一个 `shlink` 是 Docker 容器名字，第二个 `shlink` 是命令名称。

所有 API 命令如下：

```bash
docker exec -it shlink shlink
```

记得保存你的 API Key，下面会要用到。

## 安装配置 Nginx 反代

我们的 Docker Compose 配置文件中，Shlink Server 服务监听在 `127.0.0.1:8080` 端口，Shlink Web Client 监听在 `127.0.0.1:8081` 端口，所以我们需要配置 Nginx 反代来访问，假设你短网址是 `https://example.com/` Web 客户端是 `https://app.example.com/`

`example.com` 段配置：

```nginx
	location / {
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_redirect off;
		proxy_set_header        X-Forwarded-Proto $scheme;
		proxy_connect_timeout       300;
		proxy_send_timeout          300;
		proxy_read_timeout          300;
		send_timeout                300;
		proxy_pass http://127.0.0.1:8080;
	}
```

`app.example.com` 段配置：

```nginx
	location / {
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_redirect off;
		proxy_set_header        X-Forwarded-Proto $scheme;
		proxy_connect_timeout       300;
		proxy_send_timeout          300;
		proxy_read_timeout          300;
		send_timeout                300;
		proxy_pass http://127.0.0.1:8081;
	}
```

最后记得参考本站 [Nginx SSL 配置教程](/nginx-ssl/)加上 SSL 证书后，即可访问 `https://app.example.com/`：

点击 `+ Add a server` 添加你的 Shlink 服务：

![Shlink Web Client 的 + Add a server 界面](https://s.bh.sb/uploads/2022/04/27/MqzdHDPh6F9AvWu.png)

输入名称，URL 和 API Key 以后点击 `Create server` 即可使用：

![填写名称、URL 和 API Key 的 Create server 表单](https://s.bh.sb/uploads/2022/04/27/4RmMsk3VCUHDjhf.png)

如果你懒得搭建 Web Client，也可以使用官方现成的服务：

[Shlink Web Client](https://app.shlink.io/)

数据都是储存在浏览器本地的，可放心使用。

如果搭建的 Shlink Dashboard，则默认账号密码都是 `admin`， 登录以后记得修改哦！

## 升级 Shlink

直接使用 Docker Compose 升级并删除旧的镜像文件：

```bash
cd /opt/shlink
docker compose pull
docker compose up -d
docker system prune -f
```

切记不要跨多个版本升级，最好按照每个小版本的最新补丁顺序更新 Shlink。

比如，要从 `3.2.1` 版本升级到 `3.4.0`，先更新到 `3.3.2`，然后再升级到 `3.4.0`，可以自行替换 Docker 镜像里的 `stable` 标签为具体版本号来更新升级。

## 迁移 Shlink

可以参考《[使用 Docker 安装 Mailcow 自建域名邮箱](/docker-mailcow/#mailcow-的迁移-t2)》。

## 备份 Shlink

我们可以定期备份数据库，导出命令如下：

```bash
docker exec db mariadb-dump -u root --password='随机密码2' --databases shlink > shlink-all-$(date +"%Y_%m_%d_%I_%M_%p").sql
```

如果装了 `shlink-dashboard`：

```bash
docker exec db mariadb-dump -u root --password='随机密码2' --databases shlink shlink-dashboard > shlink-all-$(date +"%Y_%m_%d_%I_%M_%p").sql
```

请替换 `随机密码2` 为你的数据库 `root` 密码。