Skip to content
Go back

Trojan-Go 服务 Docker 镜像制作

| 0 Views Edit page

前言

将 Trojan-Go 服务制作成 Docker 镜像,方便快速部署和迁移。

实测将 Trojan-Go 容器化不会对速度造成影响,该跑满速的还是跑满速:
Speedtest 测试结果


方案概述

目标是将 Trojan-Go 服务和伪装用的页面封装在镜像中,而证书申请和 Nginx 外置在宿主机上。
最终的启动命令类似:

docker run -d \
  --name trojan-go \
  --restart=unless-stopped \
  # 映射到宿主机的 8443 端口,之后通过 Nginx 分流
  # 客户端侧依然配置为 443 端口
  -p 8443:443 \
  # Trojan-Go 的配置文件、证书和密钥存放的目录
  -v /rab/docker/trojan-go/:/etc/trojan-go/ \
  -e TROJAN_GO_SERVICE_PASSWORD="yourTrojanPassword" \
  -e TROJAN_GO_SERVICE_DOMAIN="trojan.example.com" \
  rabbir/trojan-go:latest

实际启动命令请参考:Trojan-Go-Docker/README.md

  1. 确认下 Trojan-Go 作者提供的镜像
  2. 编辑 Dockerfile 构建镜像
  3. 实际部署

操作步骤

一、确认下 Trojan-Go 作者提供的镜像

Dockerfile:trojan-go/Dockerfile
镜像:p4gefau1t/trojan-go

FROM golang:alpine AS builder
WORKDIR /
ARG REF
RUN apk add git make &&\
    git clone https://github.com/p4gefau1t/trojan-go.git
RUN if [[ -z "${REF}" ]]; then \
        echo "No specific commit provided, use the latest one." \
    ;else \
        echo "Use commit ${REF}" &&\
        cd trojan-go &&\
        git checkout ${REF} \
    ;fi
RUN cd trojan-go &&\
    make &&\
    wget https://github.com/v2fly/domain-list-community/raw/release/dlc.dat -O build/geosite.dat &&\
    wget https://github.com/v2fly/geoip/raw/release/geoip.dat -O build/geoip.dat &&\
    wget https://github.com/v2fly/geoip/raw/release/geoip-only-cn-private.dat -O build/geoip-only-cn-private.dat

FROM alpine
WORKDIR /
RUN apk add --no-cache tzdata ca-certificates
COPY --from=builder /trojan-go/build /usr/local/bin/
COPY --from=builder /trojan-go/example/server.json /etc/trojan-go/config.json

ENTRYPOINT ["/usr/local/bin/trojan-go", "-config"]
CMD ["/etc/trojan-go/config.json"]
  • 系统镜像使用 alpine

  • 可执行文件位于 /usr/local/bin/trojan-go

  • 配置文件位于 /etc/trojan-go/config.json

  • 配置文件内容:

    {
        "run_type": "server",
        "local_addr": "0.0.0.0",
        "local_port": 443,
        "remote_addr": "127.0.0.1",
        "remote_port": 80,
        "password": [
            "your_password"
        ],
        "ssl": {
            "cert": "your_cert.crt",
            "key": "your_key.key",
            "sni": "your-domain-name.com"
        },
        "router": {
            "enabled": true,
            "block": [
                "geoip:private"
            ],
            "geoip": "/usr/share/trojan-go/geoip.dat",
            "geosite": "/usr/share/trojan-go/geosite.dat"
        }
    }
  • 配置文件中的 passwordcertkeysni 需要替换。

  • 后续可以将证书和配置文件放在一起,映射给容器。

二、编辑 Dockerfile 构建镜像

1、Trojan-Go 服务相关

这里直接使用作者构建的 Docker 镜像作为基础镜像,因此不做配置。

# 镜像选择 p4gefau1t/trojan-go
FROM p4gefau1t/trojan-go:latest

2、伪装页面相关

Web 服务器使用更轻量化的 Caddy
单页项目在 GitHub 搜一下就行,有一大堆。我这里挑了 YaninaTrekhleb/restaurant-website 这个项目,上完 AWS 的课程之后对咖啡店这个主题还蛮有好感的。

# 1. 安装 Caddy
WORKDIR /root/
RUN wget https://github.com/caddyserver/caddy/releases/download/v2.8.4/caddy_2.8.4_linux_amd64.tar.gz
RUN tar zxvf caddy_2.8.4_linux_amd64.tar.gz
RUN mv caddy /usr/local/bin/

# 2. 下载伪装页面
RUN mkdir -vp /var/www/html/
WORKDIR /var/www/html/
RUN wget https://github.com/YaninaTrekhleb/restaurant-website/archive/refs/heads/master.zip
RUN unzip master.zip
RUN mv /var/www/html/restaurant-website-master/* /var/www/html/

# 3. 编辑 Caddy 的配置文件
RUN mkdir -vp /etc/caddy/
RUN echo ":80 {" > /etc/caddy/Caddyfile
RUN echo "  root * /var/www/html" >> /etc/caddy/Caddyfile
RUN echo "  file_server browse" >> /etc/caddy/Caddyfile
RUN echo "  try_files {path} /index.html" >> /etc/caddy/Caddyfile
RUN echo "}" >> /etc/caddy/Caddyfile

Caddy 启动相关:

# 前台运行
caddy run --config /etc/caddy/Caddyfile
# 后台运行
caddy start --config /etc/caddy/Caddyfile

3、entrypoint.sh 启动脚本

entrypoint.sh 脚本核心内容:

# 3. 启动 Caddy
caddy start --config /etc/caddy/Caddyfile

# 4. 替换 Trojan-Go 配置文件内容
# 替换域名和密码
sed -i "s/your_password/$TROJAN_GO_SERVICE_PASSWORD/" /etc/trojan-go/config.json
sed -i "s/your-domain-name.com/$TROJAN_GO_SERVICE_DOMAIN/" /etc/trojan-go/config.json
# 将 your_cert.crt 替换为 /etc/trojan-go/certificate.crt
sed -i "s/your_cert.crt/\/etc\/trojan-go\/certificate.crt/" /etc/trojan-go/config.json
# 将 your_key.key 替换为 /etc/trojan-go/private.key
sed -i "s/your_key.key/\/etc\/trojan-go\/private.key/" /etc/trojan-go/config.json

# 5. 启动 Trojan-Go
/usr/local/bin/trojan-go -config /etc/trojan-go/config.json

4、托管 GitHub 并使用 GitHub Action 自动构建镜像

GitHub 仓库:senjianlu/Trojan-Go-Docker
Docker Hub:rabbir/trojan-go

三、实际部署

只记命令,详细的过程和解析我其他博文里都有。

1、安装 Docker 环境

参考:Ubuntu 20.04 从官方源安装最新的 Docker

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) 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-compose-plugin
docker -v

2、安装最新的 Nginx

参考:Installing Prebuilt Ubuntu Packages

sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
  http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
  | sudo tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
  | sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install nginx
service nginx status

之后修改下默认的配置,使 acme.sh 能够通过 80 端口验证域名所有权:

mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
vi /etc/nginx/conf.d/default.conf
# 非域名访问返回 500 错误
server {
    listen      80;
    listen      [::]:80;
    server_name _;

    location / {
        return      500;
    }

    # 特殊的证书认证用的路径
    location /.well-known/acme-challenge/ {
        # acme.sh --webroot 模式,认证文件生成后放置的路径
        root /var/acme/webroot/;
    }
}
nginx -s reload
service nginx restart

3、创建证书申请用目录和临时容器

mkdir -vp /rab/docker/trojan-go/
docker run -d --name trojan-go alpine /bin/sh

4、安装 acme.sh 并申请证书

# 安装所需软件
apt-get install curl
apt-get install socat
# 安装 acme
cd /root
curl https://get.acme.sh | sh
# 添加软链接
ln -s  /root/.acme.sh/acme.sh /usr/local/bin/acme.sh
# 切换 CA 机构
acme.sh --set-default-ca --server letsencrypt
# 申请证书
acme.sh --issue -d trojan.example.com --webroot /var/acme/webroot/ --force
# 安装证书
acme.sh --install-cert -d trojan.example.com \
  --fullchain-file /rab/docker/trojan-go/certificate.crt \
  --key-file /rab/docker/trojan-go/private.key  \
  --reloadcmd "docker restart trojan-go"

5、启动 Trojan-Go 容器

# 删除临时容器
docker stop trojan-go && docker rm trojan-go
# 启动 Trojan-Go 容器
docker run -d \
  --name trojan-go \
  --restart=unless-stopped \
  -p 8443:443 \
  -v /rab/docker/trojan-go/:/etc/trojan-go/ \
  -e TROJAN_GO_SERVICE_PASSWORD="yourTrojanPassword" \
  -e TROJAN_GO_SERVICE_DOMAIN="trojan.example.com" \
  rabbir/trojan-go:latest

6、配置 Nginx 根据域名分流到 Trojan-Go 容器

vi /etc/nginx/nginx.conf

添加以下内容:

stream {
    # SNI 识别,将一个个域名映射成一个配置名
    map $ssl_preread_server_name $stream_map {
        trojan.example.com trojan;
    }

    upstream trojan {
        server 127.0.0.1:8443;
    }
    
    # 端口复用
    server {
        listen 443 reuseport;
        proxy_pass $stream_map;
        ssl_preread on;
    }
}
nginx -s reload
service nginx restart

7、连接测试

Surge 下可以连接:
Trojan 节点连接成功
伪装页面也可以正常访问:
伪装页面

8、BBR 加速

确保内核版本大于 4.9

uname -r

我这边是 5.13,直接开启 BBR 加速:

echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.conf 
echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf

使其生效:

sysctl -p

确认是否开启成功:

sysctl net.ipv4.tcp_congestion_control

BBR 开启成功
保险起见可以 reboot 重启一下,顺便测试 Nginx 和 Docker 的 trojan-go 容器在开机时是否自启。
结束。


参考资料:


Edit page