Cloudflare Tunnel + apisix + halo + docker折腾小记

52

目的

目标是将家中小型主机上运行的服务容器化,并通过内网穿透使其可以从公网访问。

技术选型

  • halo
    Halo [ˈheɪloʊ],强大易用的开源建站工具。是时候给hexo加个后台了。
  • apisix
    Apache APISIX 是一个高性能、可扩展的开源 API 网关。这里用来管理和控制容器化后的服务。
  • cloudflare tunnel
    cloudflare的内网穿透工具,免费!

目录结构

.
├── apisix-docker
│   ├── apisix_conf
│   ├── dashboard_conf
│   ├── docker-compose.yml
│   ├── etcd_conf
│   ├── grafana_conf
│   ├── mkcert
│   ├── .env
│   ├── prometheus_conf
│   └── upstream
├── blog
│   ├── docker-compose.yml
│   ├── halo2
│   ├── mysql
│   └── mysqlBackup
└── container-cloudflare-tunnel
    ├── config
    └── docker-compose.yml


apisix

参考 apisix-docker

  • 这里去掉了grafana和普罗米修斯

  • 将apisix的默认9080映射到宿主机的80端口,顺眼

  • 给network改了个名字,方便其他的docker加入

  • 增加.env,规范network的生成

    COMPOSE_PROJECT_NAME=b1ank
    
    ➜  app docker network ls     
      NETWORK ID     NAME                DRIVER    SCOPE
      40fe9edd7249   b1ank_home          bridge    local
    
  • 注意修改默认的admin_key和用户名密码
    apisix-docker/apisix_conf/config.yaml
    apisix-docker/dashboard_conf/conf.yaml

version: "3"

services:
  apisix-dashboard:
    image: apache/apisix-dashboard:3.0.1-alpine
    restart: always
    volumes:
    - ./dashboard_conf/conf.yaml:/usr/local/apisix-dashboard/conf/conf.yaml
    ports:
    - "9000:9000"
    networks:
      home:

  apisix:
    image: apache/apisix:${APISIX_IMAGE_TAG:-3.5.0-debian}
    restart: always
    volumes:
      - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro
    depends_on:
      - etcd
    ports:
      - "9180:9180/tcp"
      - "80:9080/tcp"
      - "9091:9091/tcp"
      - "9443:9443/tcp"
      - "9092:9092/tcp"
    networks:
      home:

  etcd:
    image: bitnami/etcd:3.4.15
    restart: always
    volumes:
      - etcd_data:/bitnami/etcd
    environment:
      ETCD_ENABLE_V2: "true"
      ALLOW_NONE_AUTHENTICATION: "yes"
      ETCD_ADVERTISE_CLIENT_URLS: "http://etcd:2379"
      ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
    ports:
      - "2379:2379/tcp"
    networks:
      home:

networks:
  home:
    driver: bridge
    ipam:
      config:
        - subnet: 172.128.2.0/24        

volumes:
  etcd_data:
    driver: local

halo

参考官方文档

  • 先改掉默认的数据库密码
  • 修改halo.external-url
  • 注释掉mysql映射出来的3306,因为不需要外部连接,容器间互相本身是连通的
version: "3"

services:
  halo:
    image: halohub/halo:2.10
    container_name: halo
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./halo2:/root/.halo2
    ports:
      - "8080:8090"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
      - --spring.r2dbc.username=root
      # MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
      - --spring.r2dbc.password=changeme
      - --spring.sql.init.platform=mysql
      # 外部访问地址,请根据实际需要修改
      - --halo.external-url=http://192.168.0.114:8080/

  halodb:
    image: mysql:8.1.0
    container_name: halodb
    restart: on-failure:3
    networks:
      halo_network:
    command: 
      - --default-authentication-plugin=caching_sha2_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --explicit_defaults_for_timestamp=true
    volumes:
      - ./mysql:/var/lib/mysql
      - ./mysqlBackup:/data/mysqlBackup
    #ports:
    #  - "3306:3306"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    environment:
      # 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
      - MYSQL_ROOT_PASSWORD=changeme
      - MYSQL_DATABASE=halo

networks:
  halo_network:

Cloudflare Tunnel

创建tunnel参考CloudFlare Tunnel 免费内网穿透的简明教程

  • 设置付款方式的时候直接关掉页面重新进似乎可以绕过
  • 将此处的token保存好,后面要用
    image-20231125220251699.png

容器化参考container-cloudflare-tunnel

  • 改成从远程仓库拉,不自己build了
  • network连的apisix的,取消了原来的host,收敛暴露面
    networks:
    b1ank_home:
      external: true
    
  • token在.env里面配置
version: '3'

# service description
services:
  # cloudflare tunnel
  cloudflare-tunnel:
    image: cloudflare/cloudflared
    #build:
    #  context: ./src
    #  dockerfile: ./Dockerfile
    container_name: cloudflare-tunnel
    hostname: cloudflare-tunnel
    restart: unless-stopped
    networks:
      b1ank_home:
    command: tunnel run
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./config/hosts:/etc/hosts
    environment:
      - "TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}"
    labels:
      # enbale watchtower updates
      - "com.centurylinklabs.watchtower.enable=true"

networks:
  b1ank_home:
    external: true

服务配置

  1. 配置上游
    iShot_2023-11-25_22.04.48.png

  2. 配置路由,并且启用插件配置如下,目的是限制外部访问管理后台

{
  "_meta": {
    "disable": false
  },
  "block_rules": [
    "/console"
  ],
  "rejected_code": 404,
  "rejected_msg": "404 page not found"
}

iShot_2023-11-25_22.07.28.png

iShot_2023-11-25_22.08.02.png

  1. cloudflare处配置服务,统一配apisix,由apisix来做反向代理

iShot_2023-11-25_22.10.27.png