更新の余地が多すぎてpublishできなくなったのでwikiに置く。
途中まで記事だったやつは https://diary.akane.blue/2021/09/23/github-actions/ にある。
タイトルの通りで、 GitHub Actions を用いて docker build
を自動化する回。
前回 はデータベースサーバーを分離することで、Webサーバー側を身軽にすることに成功しました。
しかしまだ無駄な部分が残っていました。mstdn.maud.io には公開サービスを提供している本番環境のほかに、アップデート前の人柱を担うステージング環境[1] が存在しています。
今までのアップデートの際には、まずステージング環境で docker-compose build
を実行し、サービスを再起動し、動作に問題ないことを確認したのちに本番環境でも同様に docker-compose build
し…という手順を踏んでいました。毎回ビルドに時間がかかっており、アップデート開始からデプロイまでの所要時間が読めないのが悩みでした。
独自のカスタムを加えていないプレーンな Mastodon を動かす場合、tootsuite/mastodon - Docker Hub を利用することができますが、弊サーバーではそこそこ独自の改変が加わっているので自前でやる必要がありました。
せっかくなので自分たち用の docker image を置いて docker-compose pull だけで済むようにしたいなあと思い始めました。
特に自分たち以外で使うこともないだろう[2] ということでプライベートリポジトリにしようと思っていたのですが、これだけのために自前でサーバーを立てようとはあんまり思えず、今流行りの GitHub Packages は Free だとプライベートリポジトリで利用可能なストレージが 500MB まで で、前述の tootsuite/mastodon を見る限り無理そうだったので流れに逆行して Docker Hub になりました。
やるなら akane-blue/mastodon にpushされたら自動でビルドして Docker Hub に上げてくれると便利ですよね。今なら GitHub Actions を使うのが簡単そうなので試してみました。
以下をリポジトリに .github/workflows/push_docker_image.yml
みたいな名前で作ります。
name: Push our docker image
on:
push:
branches: [ hota/master ]
pull_request:
branches: [ hota/master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
push_to_hub:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_TOKEN }}
-
name: Checkout Git repository
uses: actions/checkout@v2
with:
repository: akane-blue/mastodon
path: mastodon
-
name: Build and push to Docker Hub
uses: docker/build-push-action@v2
with:
context: mastodon
push: true
tags: ${{ secrets.REGISTRY_USERNAME }}/${{ secrets.REGISTRY_REPO }}:${{ secrets.REGISTRY_TAG }}
わたしの場合は hota/master
ブランチだったのでこんな感じですが、適宜読み替えてください。
あとは GitHub リポジトリ上で Settings -> Secrets から Repository Secrets
に以下の内容を設定する必要があります。
secret | 中身 |
---|---|
REGISTRY_USERNAME |
Docker Hub のユーザー名 |
REGISTRY_TOKEN |
Docker Hub のトークン |
REGISTRY_REPO |
Docker Hub のリポジトリ名 |
REGISTRY_TAG |
Docker イメージのタグ名 |
actions/checkout@v2
の中でリポジトリがわざわざ指定されてたり、ここの path
と docker/build-push-action@v2
の context
を揃えてるのは最初この Actions を別のリポジトリで管理しようとした名残です。結局、別リポジトリのpushをトリガーにするのがまあまあ面倒臭いことが判明したので akane-blue/mastodon 自身になりましたが…。
無事に docker image のビルドが自動化され、サーバー側はそれらを pull するだけでよくなり、ソースコードをcloneしておく必要がなくなりました。
結果として、現在は以下のファイルだけで構成されています:
mastodon/
├ .env.production
├ docker-compose.yml
├ public/
│ ├ announcements.json
│ └ system/
└ redis/
└ dump.rdb
public/system/
以下もメディアを外部に置いていれば特に増えないはず(まだ空)なので、すごくスッキリしましたね!
hota/testing/fix-featurename
みたいなブランチ切るのでそういうのもビルドしてタグ分けたいhota/**
ブランチがpushされたときをトリガーとして
hota/master
のほかに前述の hota/testing/*
があるのでon:
push:
- branches: [ hota/master ]
+ - hota/**
- pull_request:
- branches: [ hota/master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
+ -
+ name: Get latest branch name
+ id: set_tag
+ run: |
+ cd mastodon
+ CURRENT_BRANCH="$(git branch --sort=-committerdate | sed -n 1p | sed 's/* //g')"
+ git switch ${CURRENT_BRANCH}
+ DOCKER_TAG="$(echo ${CURRENT_BRANCH} | sed 's/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
+ echo "::set-output name=docker_tag::${DOCKER_TAG}"
-
name: Build and push to Docker Registry
uses: docker/build-push-action@v2
with:
context: mastodon
push: true
- tags: ${{ secrets.REGISTRY_USERNAME }}/${{ secrets.REGISTRY_REPO }}:${{ secrets.REGISTRY_TAG }}
+ tags: ${{ secrets.REGISTRY_USERNAME }}/${{ secrets.REGISTRY_REPO }}:${{steps.set_tag.outputs.docker_tag}}
ようになりました。
ブランチ名を取るときのまあまあアホポイントみて…
run: |
cd mastodon
- CURRENT_BRANCH="$(git branch --sort=-committerdate | sed -n 1p | sed 's/* //g')"
+ CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
- git switch ${CURRENT_BRANCH}
DOCKER_TAG="$(echo ${CURRENT_BRANCH} | sed 's/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
git branch
だと * hota/master
みたいになるので *
を取り除こうとした
$ git branch --sort=committerdate
* hota/master
hota/testing/fix-hogehoge
hota/testing/add-fugafuga
actions/checkout@v2
、そもそもトリガーになったブランチをcheckoutするので git switch
する必要なかったgit rev-parse
使えば一発書いてて思い出したけどじゃあもう CURRENT_BRANCH
自体要らなくない???
- CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
- DOCKER_TAG="$(echo ${CURRENT_BRANCH} | sed 's/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
+ DOCKER_TAG="$(git rev-parse --abbrev-ref HEAD | sed 's/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
終わり!!!!!
GITHUB_REF
でトリガーしたブランチ名が取れると教えてもらった。refs/heads/<branch_name>
で返ってくるのでまた削ることになるつまりこうで
- DOCKER_TAG="$(git rev-parse --abbrev-ref HEAD | sed 's/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
+ DOCKER_TAG="$(echo ${GITHUB_REF} | sed 's/refs\/heads\/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
なんと1文字も減ってなくてちょっと笑った。
sed
、複数同時にやりたきゃそのまま列挙してよかったのね/
より前が消えればなんでもええという気づき
hota/master
のタグを latest
にするのはありだなと思ったので入れた- DOCKER_TAG="$(echo ${GITHUB_REF} | sed 's/refs\/heads\/hota\///g' | sed 's/testing\///g' | sed 's/-/_/g')"
+ DOCKER_TAG="$(echo ${GITHUB_REF} | sed -e 's/.*\///g' -e 's/-/_/g')"
+ [ "$DOCKER_TAG" == "master" ] && DOCKER_TAG=latest
記事を読んだ @sksat からいくらかのPull Requestsをもらいました。
おかげで早くなりました。
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
metadata-action
でタグをいい感じにする泥臭いシェル芸なんかやめたらええ.
name: Push Docker image to Docker Registry
runs-on: ubuntu-latest
steps:
+ -
+ name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v3
+ with:
+ images: ${{ secrets.REGISTRY_SERVER }}/${{ secrets.REGISTRY_REPO }}
+ tags: |
+ type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
+ type=ref,event=branch
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
repository: akane-blue/mastodon
path: mastodon
- -
- name: Get latest branch name
- id: set_tag
- run: |
- cd mastodon
- DOCKER_TAG="$(echo ${GITHUB_REF} | sed -e 's/.*\///g' -e 's/-/_/g')"
- # Use Docker `latest` tag convention
- [ "$DOCKER_TAG" == "master" ] && DOCKER_TAG=latest
- echo "::set-output name=docker_tag::${DOCKER_TAG}"
-
name: Build and push to Docker Registry
uses: docker/build-push-action@v2
with:
context: mastodon
push: true
- tags: ${{ secrets.REGISTRY_SERVER }}/${{ secrets.REGISTRY_REPO }}:${{steps.set_tag.outputs.docker_tag}}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
staging.mstdn.maud.io というのですが、登録は受け付けていないほか、特にフォローもおすすめしません ↩︎
favicon や apple-touch-icon など弊サーバーに特有のアセットが含まれるため他所で使われることがない ↩︎