Reading view

There are new articles available, click to refresh the page.

GitHub 全家桶:Actions 自动构建多架构 Docker 镜像并上传至 Packages (ghcr.io)

前段时间把 GitHub 的用户名修改成了 @prinsss,准备把其他地方的账号也修改一下的时候,却发现 Docker Hub 的 username 不能改,只能砍掉重练(npm 也是)。

想想反正我 Docker Hub 上也没上传什么东西,不如就用 GitHub 自家的 Container registry 来托管镜像吧!

这里有个小插曲:其实我挺早之前就想要改名了,但当时在忙秋招,考虑到改名后可能会有一些后续要处理(擦屁股),所以只是创建了一个 organization 把名字占住,等有时间了再正式改名。然而后来我把组织删了,想要修改 GitHub 账户的用户名时,却提示 prinsss 这个名称 unavailable(我确定它是没被占用的,因为我还能再用这个名字创建组织),不知道是不是触发了内部的什么保留机制。

最后还是发工单找客服解决了,而且等了一个多星期才回复,也是挺无语的。原来的 printempw 这个名字我也保留了,所以 printempw.github.io 这个域名还是可以访问的,目前是两边同步更新,后续再慢慢迁移。

GitHub Packages 介绍

其实最开始知道这个还是因为 Homebrew,看它每次安装软件下载 bottle 时都会从 ghcr.io 这个域名下载。好奇去查了一下,发现原来 GitHub 自己也整了一个软件包仓库,颇有一统天下的味道。

GitHub Packages 支持托管 Docker、npm、Maven、NuGet、RubyGems 等软件包,用起来比较像私有库。比起官方 registry 的好处就是其与 GitHub 完全集成,可以把源代码和软件包整合在一起,包括权限管理都可以用 GitHub 的那一套。

GitHub Packages 对于开源项目完全免费,私有仓库也有一定的免费额度

手动上传镜像

基础用法和 Docker Hub 是一样的,只是 namespace 变为了 ghcr.io。

首先创建一个 PAT (Personal Access Token) 用于后续认证:

  • 打开 https://github.com/settings/tokens/new?scopes=write:packages
  • 创建一个 PAT,勾选 write:packages 权限

注意:如果是在 GitHub Actions 中访问 GitHub Packages,则应该使用 GITHUB_TOKEN 而非 PAT 以提升安全性。后续章节会说明如何在 Actions 中使用 GITHUB_TOKEN

然后我们就可以用这个 Token 登录镜像仓库了:

export CR_PAT=YOUR_TOKENecho $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin

尝试一下推送镜像:

docker tag hello-world:latest ghcr.io/prinsss/hello-world:latestdocker push ghcr.io/prinsss/hello-world:latest

可以看到已经出现在 GitHub 上了:

packages-hello-world

刚上传的镜像默认都是 private,可以在 Package Settings 下方的 Change package visibility 处修改为公开镜像。

自动构建并上传

连镜像都放 GitHub 上了,那怎么好意思不用 GitHub Actions 呢!

下面就使用 Actions 实现代码更新后自动构建多架构 Docker 镜像,打 tag 并发布。

废话不多说,直接贴配置:

# yaml-language-server: $schema=https://json.schemastore.org/github-workflowname: Build Docker Image# 当 push 到 master 分支,或者创建以 v 开头的 tag 时触发,可根据需求修改on:  push:    branches:      - master    tags:      - v*env:  REGISTRY: ghcr.io  IMAGE: prinsss/ga-hit-counterjobs:  build-and-push:    runs-on: ubuntu-latest    # 这里用于定义 GITHUB_TOKEN 的权限    permissions:      packages: write      contents: read    steps:      - name: Checkout        uses: actions/checkout@v2      # 缓存 Docker 镜像以加速构建      - name: Cache Docker layers        uses: actions/cache@v2        with:          path: /tmp/.buildx-cache          key: ${{ runner.os }}-buildx-${{ github.sha }}          restore-keys: |            ${{ runner.os }}-buildx-      # 配置 QEMU 和 buildx 用于多架构镜像的构建      - name: Set up QEMU        uses: docker/setup-qemu-action@v1      - name: Set up Docker Buildx        id: buildx        uses: docker/setup-buildx-action@v1      - name: Inspect builder        run: |          echo "Name:      ${{ steps.buildx.outputs.name }}"          echo "Endpoint:  ${{ steps.buildx.outputs.endpoint }}"          echo "Status:    ${{ steps.buildx.outputs.status }}"          echo "Flags:     ${{ steps.buildx.outputs.flags }}"          echo "Platforms: ${{ steps.buildx.outputs.platforms }}"      # 登录到 GitHub Packages 容器仓库      # 注意 secrets.GITHUB_TOKEN 不需要手动添加,直接就可以用      - name: Log in to the Container registry        uses: docker/login-action@v1        with:          registry: ${{ env.REGISTRY }}          username: ${{ github.actor }}          password: ${{ secrets.GITHUB_TOKEN }}      # 根据输入自动生成 tag 和 label 等数据,说明见下      - name: Extract metadata for Docker        id: meta        uses: docker/metadata-action@v3        with:          images: ${{ env.REGISTRY }}/${{ env.IMAGE }}      # 构建并上传      - name: Build and push        uses: docker/build-push-action@v2        with:          context: .          file: ./Dockerfile          target: production          builder: ${{ steps.buildx.outputs.name }}          platforms: linux/amd64,linux/arm64          push: true          tags: ${{ steps.meta.outputs.tags }}          labels: ${{ steps.meta.outputs.labels }}          cache-from: type=local,src=/tmp/.buildx-cache          cache-to: type=local,dest=/tmp/.buildx-cache      - name: Inspect image        run: |          docker buildx imagetools inspect \          ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.meta.outputs.version }}

自动构建的效果可以在我的 GitHub 上查看(其实就是之前写的那个 使用 Google Analytics API 实现博客阅读量统计)。

另外有几个需要注意的点:

上传时出现 400 Bad Request

这个昨天搞得我真是一脸懵逼,报错是这样的:

#16 exporting to image#16 pushing layers 0.5s done#16 ERROR: unexpected status: 400 Bad Request------ > exporting to image:------error: failed to solve: unexpected status: 400 Bad RequestError: buildx failed with: error: failed to solve: unexpected status: 400 Bad Request

排查了好久,最后发现是我打 tag 的时候忘记加上用户名了,原本是 ghcr.io/prinsss/ga-hit-counter 的,我给打成了 ghcr.io/ga-hit-counter,难怪推不上去(也要吐槽一下这个报错,就一个 400 鬼知道是什么啊)。

上传时出现 403 Forbidden

把上面那个解决了以后,心想这次总该成了吧,结果又来了个 403,我又一脸懵逼:

#16 exporting to image#16 pushing layers 0.7s done#16 ERROR: unexpected status: 403 Forbidden------ > exporting to image:------error: failed to solve: unexpected status: 403 ForbiddenError: buildx failed with: error: failed to solve: unexpected status: 403 Forbidden

再一番排查,发现是需要在 Package Settings 中的 Manage Actions access 处指定可以访问该软件包的源码仓库(也就是 Actions 所在的仓库)。好吧……

manage-actions-access

添加了仓库,这下确实可以了。

元数据自动生成

docker/metadata-action 这是一个比较有意思的 action,它可以从源码以及触发构建的 event 中获取数据,自动生成相应的 Docker 镜像 tag 以及 label。(在 GitHub 文档官方的示例中,这是由一段脚本完成的)

比如默认的效果就是:

EventRefDocker Tags
pull_requestrefs/pull/2/mergepr-2
pushrefs/heads/mastermaster
pushrefs/heads/releases/v1releases-v1
push tagrefs/tags/v1.2.3v1.2.3, latest
push tagrefs/tags/v2.0.8-beta.67v2.0.8-beta.67, latest

也就是我现在使用的:源码推送到 master 分支则自动构建并更新 master tag 的镜像;在 git 上创建以 v 开头的 tag,Docker 那边也会自动创建相应的 tag 并且更新 latest,不错不错。(不过想想我可能保留一个 tag 触发就够了)

比如我 push 了一个 v0.2.0 的 tag 上去,自动生成的元数据就是这样的:

Run docker/metadata-action@v3Context info  eventName: push  sha: 6071f564087d49be48dc318b89fc22ff96cf6a17  ref: refs/tags/v0.2.0  workflow: Build Docker Image  action: meta  actor: prinsss  runNumber: 11  runId: 1495122573Docker tags  ghcr.io/prinsss/ga-hit-counter:v0.2.0  ghcr.io/prinsss/ga-hit-counter:latestDocker labels  org.opencontainers.image.title=google-analytics-hit-counter  org.opencontainers.image.description=Page views counter that pulls data from Google Analytics API.  org.opencontainers.image.url=prinsss/google-analytics-hit-counter  org.opencontainers.image.source=prinsss/google-analytics-hit-counter  org.opencontainers.image.version=v0.2.0  org.opencontainers.image.created=2021-11-23T14:10:35.953Z  org.opencontainers.image.revision=6071f564087d49be48dc318b89fc22ff96cf6a17  org.opencontainers.image.licenses=MIT

如果想要修改为其他方案,action 也提供了丰富的配置项,可以自行修改。

最后

用 GitHub Packages 托管 Docker 镜像,体验还是挺不错的。硬要说有什么缺点的话就是不好配置国内镜像吧,毕竟大部分国内镜像都是对应 Docker Hub 的。

另外多架构镜像的这个构建时间也是挺感人,模拟 arm64 一次要六七分钟,哈人。(所以写 Dockerfile 还是挺讲究的,怎么让缓存效率最大化,这方面还得再学习)

参考链接:

题外话,秋招后这段时间我也折腾了一些东西,有空慢慢发出来吧。

使用国内镜像加速 Laravel Sail 构建

Laravel Sail 是什么?简单来说就是一个基于 Docker 的开发环境。其核心就是一个 docker-compose.yml 配置文件和 sail 脚本,定义了 PHP、MySQL、Redis 等一系列容器,然后把程序放里面跑。

至于好处嘛,主要就是使用方便、运行环境统一、不会弄乱系统。同样是 Laravel 开发,本机安装 LNMP、Valet、Homestead 这些方法我都用过,但现在我肯定首选 Laravel Sail(容器化是真滴爽)。

不过 Laravel Sail 好是挺好,想要在墙内顺利使用还是要费点功夫的。

创建项目

以下操作均在国内网络环境下运行。其实挂个全局代理这些都不是事啦

安装 Docker 和配置 Docker Hub 国内镜像的步骤可以参考这篇文章

创建项目时,直接用 Laravel 官方的安装脚本大概率会卡在 Updating dependencies 上,为什么你懂的。不过我们还是可以借鉴下官方脚本的内容:

curl -s https://laravel.build/example-app -o install.sh

临时新建一个 composer 容器:

docker run -it --rm -v $(pwd):/opt -w /opt \  laravelsail/php80-composer:latest bash

在容器内配置 composer 镜像,创建 Laravel 项目:

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/laravel new example-app

安装 Laravel Sail 相关文件(这里可自定义需要使用的服务):

cd example-appphp ./artisan sail:install --with=mysql,redis,meilisearch,mailhog,selenium

导出底层 Dockerfile,方便后续定制:

php ./artisan sail:publish

完成后,可以看到项目下多出了一个 docker 目录和 docker-compose.yml 文件。

定制 Dockerfile

Laravel Sail 有一个主要的容器,用于运行 PHP 主程序。其他比如 composer, artisan, node, npm 命令也是在这个容器里运行的。

后续你可以通过 sail shell 来访问这个容器。

这个主容器的 Dockerfile 就是我们上面导出的那个。可以看到它主要就是在 Ubuntu 的基础上安装了一些软件包,大部分的网络问题都是这里造成的。

使用国内镜像替换之,主要需要替换的软件源有:

  • Ubuntu
  • PPA
  • Composer
  • Node.js
  • Npm

修改后的 Dockerfile 如下:

FROM ubuntu:21.04LABEL maintainer="Taylor Otwell"ARG WWWGROUPWORKDIR /var/www/htmlENV DEBIAN_FRONTEND noninteractiveENV TZ=Asia/ShanghaiENV APT_MIRROR http://mirrors.ustc.edu.cnENV NVM_DIR /usr/local/nvmENV NODE_VERSION 16.9.1ENV NVM_NODEJS_ORG_MIRROR https://mirrors.ustc.edu.cn/nodeENV NVM_SOURCE https://hub.fastgit.org/nvm-sh/nvm.gitSHELL ["/bin/bash", "-o", "pipefail", "-c"]RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneRUN echo 'APT::Acquire::Retries "5";' > /etc/apt/apt.conf.d/80-retries \  && sed -i "s|http://archive.ubuntu.com|$APT_MIRROR|g; s|http://security.ubuntu.com|$APT_MIRROR|g" /etc/apt/sources.list \  && sed -i "s|http://ports.ubuntu.com|$APT_MIRROR|g" /etc/apt/sources.list \  && apt-get update \  && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python2 \  && mkdir -p ~/.gnupg \  && chmod 600 ~/.gnupg \  && echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf \  && apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E5267A6C \  && apt-key adv --homedir ~/.gnupg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C300EE8C \  # PHP  && echo "deb https://launchpad.proxy.ustclug.org/ondrej/php/ubuntu hirsute main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \  && apt-get update \  && apt-get install -y php8.0-cli php8.0-dev \    php8.0-pgsql php8.0-sqlite3 php8.0-gd \    php8.0-curl php8.0-memcached \    php8.0-imap php8.0-mysql php8.0-mbstring \    php8.0-xml php8.0-zip php8.0-bcmath php8.0-soap \    php8.0-intl php8.0-readline php8.0-pcov \    php8.0-msgpack php8.0-igbinary php8.0-ldap \    php8.0-redis php8.0-swoole php8.0-xdebug \  # Composer  && curl -so /usr/bin/composer https://mirrors.aliyun.com/composer/composer.phar \  && chmod a+x /usr/bin/composer \  && composer --version \  && composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \  # Node.js  && mkdir -p $NVM_DIR \  && curl -so- https://raw.fastgit.org/nvm-sh/nvm/v0.38.0/install.sh | bash \  && source $NVM_DIR/nvm.sh \  && nvm install $NODE_VERSION \  && nvm use $NODE_VERSION \  && node -v && npm -v \  && npm config set registry https://registry.npm.taobao.org \  # Yarn  && npm install --global yarn \  && yarn config set registry https://registry.npm.taobao.org \  && apt-get install -y mysql-client \  && apt-get install -y postgresql-client \  && apt-get -y autoremove \  && apt-get clean \  && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modulesENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATHRUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.0RUN groupadd --force -g $WWWGROUP sailRUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sailCOPY start-container /usr/local/bin/start-containerCOPY supervisord.conf /etc/supervisor/conf.d/supervisord.confCOPY php.ini /etc/php/8.0/cli/conf.d/99-sail.iniRUN chmod +x /usr/local/bin/start-containerEXPOSE 8000ENTRYPOINT ["start-container"]

目前有个不足之处就是 Node.js 的安装,原来用的 NodeSource 现在没有可用的国内镜像源,只能改用 nvm 安装。但是 nvm 在 PATH 的处理上有些问题(它是通过一个脚本修改环境变量,把当前启用的 Node 版本添加到 PATH 里去,但是 Dockerfile 里不能动态设置 ENV),目前只能手动指定要安装的 Node 版本了。

运行容器

使用 Laravel Sail 提供的脚本运行容器:

./vendor/bin/sail up

这个脚本主要的工作就是读取 .env 里配置的环境变量,然后通过 docker-compose 在容器里执行相应命令,所以基本用法和 docker-compose 是一致的:

sail up -d  # 后台运行sail down   # 停止运行

耐心等待镜像构建完成,Laravel Sail 就可以正常运行啦。

Creating network "example-app_sail" with driver "bridge"Creating example-app_redis_1       ... doneCreating example-app_selenium_1    ... doneCreating example-app_meilisearch_1 ... doneCreating example-app_mailhog_1      ... doneCreating example-app_mysql_1       ... doneCreating example-app_laravel.test_1 ... done

laravel-sail-app

参考链接

在 M1 Mac 上构建 x86 Docker 镜像

今天闲来无事,数了一下服务器上在跑的东西,打算把它们都扔到 Docker 里面去。第一个开刀的就是之前写的 Google Analytics 博客阅读量统计,很简单的一个 Node.js + Express 程序。

写完 Dockerfile 测试好,正准备 push 上去时,我才突然想起来:

我现在用的是 M1 MacBook,丫的默认 build 出来的镜像是 arm64 架构的呀!

好在 M1 Mac 上的 Docker Tech Preview 也支持使用 buildx 构建多架构的镜像,稍微设置一下就可以了。

题外话,M1 MacBook Air 真的很好用,建议早买早享受(

启用实验性功能

Docker 的 buildx 还是实验性功能,需要在 Docker Desktop 设置中开启,具体位于 Preferences > Experimental Features > Enable CLI experimental features

新建 builder 实例

Docker 默认的 builder 不支持同时指定多个架构,所以要新建一个:

docker buildx create --use --name m1_builder

查看并启动 builder 实例:

docker buildx inspect --bootstrap
Name:   m1_builderDriver: docker-containerNodes:Name:      m1_builder0Endpoint:  unix:///var/run/docker.sockStatus:    runningPlatforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/arm/v7, linux/arm/v6

其中 platforms 就是支持的架构,跨平台构建的底层是用 QEMU 实现的。

构建多架构 Docker 镜像

使用 buildx 构建:

docker buildx build \  --platform linux/amd64,linux/arm64  --push -t prinsss/google-analytics-hit-counter .

其中 -t 参数指定远程仓库,--push 表示将构建好的镜像推送到 Docker 仓库。如果不想直接推送,也可以改成 --load,即将构建结果加载到镜像列表中。

--platform 参数就是要构建的目标平台,这里我就选了本机的 arm64 和服务器用的 amd64。最后的 .(构建路径)注意不要忘了加。

构建完 push 上去以后,可以查看远程仓库的 manifest:

docker buildx imagetools inspect prinsss/google-analytics-hit-counter
Name:      docker.io/prinsss/google-analytics-hit-counter:latestMediaType: application/vnd.docker.distribution.manifest.list.v2+jsonDigest:    sha256:a9a8d097abb4fce257ae065365be19accebce7d95df58142d6332270cb3e3478Manifests:  Name:      docker.io/prinsss/google-analytics-hit-counter:latest@sha256:bb7f3a996b66a1038de77db9289215ef01b18e685587e2ec4bb0a6403cc7ce78  MediaType: application/vnd.docker.distribution.manifest.v2+json  Platform:  linux/amd64  Name:      docker.io/prinsss/google-analytics-hit-counter:latest@sha256:94ea08ac45f38860254e5de2bae77dee6288dd7c9404d8da8a3578d6912e68e7  MediaType: application/vnd.docker.distribution.manifest.v2+json  Platform:  linux/arm64

可以看到已经是支持多架构的镜像了。

参考链接

Mastodon: 将媒体文件存放在本地(docker 版)

本攻略适用于——

  • 自建 mastodon(非大站)
  • 使用 docker compose
  • 将媒体文件直接保存在服务器上,而不使用 s3 外部存储

这个搭配虽然不多见,但其实用起来满爽的。很多人用的 s3 服务都是在薅羊毛,而 mastodon 那个变态的,把别人家的媒体文件缓存到自家的架构,流量的吞吐其实很大的(开了 relay 就更夸张),薅羊毛时很容易就超出了。反而是 vps 本身的流量上限很高。对于个人建站而言,媒体文件总量通常 <50GB,某些 vps 自带 200GB 硬盘,足够用了。

缺点是,除了数据库定期备份外,也要考虑媒体文件的异地备份问题。但其实只需要备份存储本地附件的 media_attachments,而 cache 是不需要备份的,所以工作量也不大。

两年前我把媒体文件转移到本地时,参照了 antisocial science 的设置。但因为我用 docker,官方默认的设置,docker 内外权限不一致,无法将媒体文件写到本地。于是匆匆又在本地建了个 minio s3 来中转……这样其实很浪费资源了,minio 的开销也不小。所以最近趁着搬家,又试了一下,终于把 docker + 本地存储 跑通了。


1. 在 docker-compose.yml 里,

web 和 sidekiq 容器中,已经预设了媒体文件的卷映射

volumes:
- ./public/system:/mastodon/public/system

这个不用动。——也可以改成其它的路径,但要和后面的设置一致(本文用相同的颜色标明)。

2. 修改 .env.production

S3_ENABLED=false
PAPERCLIP_ROOT_PATH=/mastodon/public/system
PAPERCLIP_ROOT_URL=/fivestone-mastodon-media

PAPERCLIP_ROOT_URL 是服务器的所有媒体文件链接的子文件夹名称,形如:

https://mastodon.fivest.one/fivestone-mastodon-media/media_attachments/.../x.jpg

默认值是 /system;但是建议改成独特一些的名字,而且建议和 S3_BUCKET 一致。以后需要在本地存储和 s3 之间转换时,可以省一点心。(所以要独特一些,防止回头在 s3 上和别人撞名)

3. 修改 nginx 的域名配置文件

参照官方的配置,把域名文件夹里的 proxy_pass ,直接改成本地的 alias

server 
{
  server_name mastodon.fivest.one;
# ......

  location /fivestone-mastodon-media/
  {
    alias /path-to...docker-compose-folder/public/system/ ;

    proxy_cache CACHE;
    proxy_cache_valid 200 48h;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_cache_lock on;

    expires 1y;
    add_header Cache-Control public;
    add_header 'Access-Control-Allow-Origin' '*';
    add_header X-Cache-Status $upstream_cache_status;
    add_header X-Content-Type-Options nosniff;
    add_header Content-Security-Policy "default-src 'none'; form-action 'none'";
  }
}

然后重启 nginx

sudo systemctl reload nginx.service

4. 通过 docker 设置媒体文件夹的权限

在 docker 内部,是以 mastodon 用户的身份,来运行程序的,所以要把媒体文件夹的所有者改成(docker 内部的)mastodon:

sudo docker-compose run --user=root --rm web chown -R mastodon /mastodon/public/system

如果是从 s3 迁移到本地,把媒体文件移入这个本地文件夹(/path-to…docker-compose-folder/public/system/)后,也要再执行一遍上面这条命令。

或者在 mastodon docker 服务已经启动的情况下,执行:

sudo docker exec -u 0 mastodon_container_web chown -R mastodon /mastodon/public/system

但在这条命令执行结束之前,mastodon 在后台写入媒体文件时,仍然可能出现文件夹权限不足,无法写入的问题。

迁移博客

目前将博客和一些附属的东西迁移到了 Azure 去了。

为什么要迁移呢,因为国内的审查制度(虽然我在博客不表达政治观点,但有一篇技术类文章还是触发了服务器提供商的舆情监控系统)其他的还有原本部署的不够优雅,现在基本把博客一些组件都容器化了,做到了能够几分钟快速从其他的服务器迁移,还有一个相对适合我的完备的备份策略。绝大部分部署都自动化了,这样做以后我需要的仅仅是写一篇文章,然后 commit 到 GitHub 的 private repo 就完事了。

在原来的博客中,图床使用的都是又拍云的存储方案,包括一些博客的缩略图,都是由它去处理的。之后发现我又拍云账户虽然有之前赞助计划给的 100 GB+ 流量,但是每天都有海外请求导致一天都会扣 0.01 元,然后我就不得不每隔一段时间去充值一次 1 元。为了避免这样我选择了自建方案。存储我选择了 MinIO,图片处理用了 thumbor。这两个上手都相当快,尤其 MinIO 还是完全兼容 Amazon S3 的方案。然后图像处理参数设计成与我在又拍云的设定一样就完事了。图片这块基本无痛迁移。

网站速度方面,我没有特别的去优化国内的用户。目前网站的所有流量都得经过 cloudflare 的 CDN。

最后就是此次迁移用到的各种东西:docker,docker-compose,nginx,thumbor,MinIO,GitHub Actions

群晖使用Docker安装MQTT服务端 mosquitto


以下方法经本人验证通过,环境如下:

群晖 DS918+ DSM 6.2.4

mosquitto version 2.0.11

MQTTBox Version 0.2.3


前言:MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅(publish/subscribe)模式的”轻量级”通讯协议。客户端的发布者不直接将消息传递给订阅者,而是服务端(MQTT Broker)进行分发,一个客户端既可以是发布者,也可以是订阅者,更多介绍请参看维基百科上的词条 。以智能家居的情形简单举例,人体感应器(发布者)感应到有人时发布主题为”有人“的消息到服务端,而由于摄像头订阅了该主题,因此收到消息,开始录像,此时摄像头角色为(接收者),同时摄像头也作为(发布者)发布”监控异动“消息到服务器,而我们手机订阅了此主题,作为(接收者)便可收到消息。

目前有很多机构提供MQTT Broker服务,有免费的也有收费的。作为个人用户用于智能家居服务,我决定用已有NAS服务器自己搭建一个。参考了网上的一些文章,但大都写得有些复杂,对一般小白不是很友好,因此我尝试自创了一个极简的方法来实现,并记录下来供由需要的朋友学习。

第一步:管理员账号登陆群晖,在Docker中选择 “注册表”,搜索 “eclipse-mosquitto”,搜索结果中选择第一个,点击下载,选择标签latest。此时系统开始下载,可在“映像”中查看下载进度

第二步:下载完毕后,在“映像”里选择已下载的 eclipse-mosquitto 映像 ,点击启动按钮打开创建容器窗口。点击高级设置按钮,打开高级设置页面。

在高级设置中,勾选“启动自动重新启动”

在卷中,点击添加文件夹,在docker目录下新建文件夹 “mosquitto”并选择该文件夹,装载路径填写”/mosquitto/config”

在网络中,勾选“使用与 Docker Host 相同的网络”

确认应用后点击下一步,取消”向导完成后运行此容器“,然后应用

第三步:新建一个mosquitto.conf文件,并将该文件上传到 docker目录的 “mosquitto” 文件夹内。文件内容如下:

persistence true
listener 18831
allow_anonymous true
  • listener 为端口号,默认是1883,我机器上该端口被占用了,所以自己改了一个
  • allow_anonymous true 表示支持匿名用户,此次为了教程简单因此开启匿名用户

文件上传后,再docker容器中启动第二步添加的 eclipse-mosquitto 容器

第四步:测试mosquitto服务

mqtt测试工具很多,我选择的是MQTTBox ,用chrome打开下列地址,添加应用后打开

https://chrome.google.com/webstore/detail/mqttbox/kaajoficamnjijhkeomgfljpicifbkaf?hl=zh-CN

点击”Create MQTT Client”,取一个名字,Protocol 选mqtt/tcp ,Host 填写你的主机地址和 mosquitto 服务端口 ,保存后可看到显示为Connected 表示已经正确连接上我们新建的mosquitto服务端

接着,添加一个订阅,主题随便写一个,我这里填FEEUS.COM,点击”Subscribe“完成订阅

在发布端发布一个订阅端一样的主题,这里也是 FEEUS.COM ,然后输入发布的消息,点击”Publish“后完成发布,该主题的订阅者即可收到该条消息


如果您喜欢这篇文章,或者它给您带来了帮助,您可以请我们喝一杯咖啡,我们将非常感谢您的支持!

软路由如何只代理网桥Docker

软路由如何只代理网桥Docker

发表于|更新于|实用教程
|字数总计:574|阅读时长:1分钟|阅读量:

说明

你购买并设置了软路由用于代理,让局域网内的其他设备也可以使用。现在所有的流量都将先经过代理程序,这不可避免地会带来损耗,尤其是使用BT时大量的流量会被规则判定以后再直连,甚至也会影响游戏的NAT类型。而且也不得不考虑一个问题:软路由本身总是需要代理吗?为了解决这个问题,我将介绍一下DAE这个代理程序的优点和配置过程。
DAE有什么优点,它的代理性能比其他的好一点点但不多,主要看中的是它的直连性能。由于直连流量并不经过代理程序,会像直连一样直连。而且它可以识别网卡流量,将其LAN接口绑定Docker0网卡可以代理Docker流量,同时将其WAN接口与ETH0解绑就可以让软路由不走代理只代理Docker。

配置

下载安装

DAE的下载安装极其简单,而且有集成了DAE的面板daed便于操控,所以我们只需要安装daed即可。安装过程可以参考Onecloud作为旁路由实现代理,注意:如果你的系统不是armbian,请跳过升级内核,重新选择下载,如x86平台daed-linux-x86_64_v3_avx2.zip

配置说明

在配置Global中找到接口及内核选项,LAN接口绑定使用代理的网卡,如果你是旁路由,绑定与WAN接口相同的网卡即可。此时如果只绑定LAN接口而留空WAN接口,那么软路由内所有流量直连,局域网内流量可以被代理。当绑定Docker0时所有的容器都可以使用代理,如果你只想让其中几个容器被代理,那么稍稍有些复杂。
创建一个网桥用于代理容器连接,此时主机网卡多出br-**,在LAN接口绑定即可代理容器流量。不需要代理的容器不必加入该网卡,流量经过Docker0。

1
2
3
docker network create 要创建的网卡名称
#务必在容器创建时添加--network参数,否则流量默认走Docker0
docker run -d --name=proxy --network=要创建的网卡名称
文章作者: wayen
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Wayen

评论
数据库加载中

❌