概要
Could not kickstart service "com.apple.audio.coreaudiod": 1: Operation not permitted
というエラーが出てアップグレードできなかったので対策方法を紹介します
環境
- macOS 14.5
- blackhole-2ch 0.6.0
対応方法
-
rm -rfi /opt/homebrew/Caskroom/blackhole-2ch/
- brew reinstall blackhole-2ch
Could not kickstart service "com.apple.audio.coreaudiod": 1: Operation not permitted
というエラーが出てアップグレードできなかったので対策方法を紹介します
docker scout はイメージの脆弱性をスキャンしてくれるツールです
docker のバージョンがある程度最新であればデフォルトで使えます
また dockerhub でもフリープランであれば3イメージまで scout スキャンを設定することができます
今回は Mac 上で動かして脆弱性に対応してみました
バージョン24であれば特にインストールは不要でいきなり使えます
結果は以下の通りです
INFO New version 1.9.3 available (installed version is 0.16.1)
✓ Pulled
✓ Image stored for indexing
✓ Indexed 630 packages
Your image ruby:3.1.2 │ 7C 69H 134M 136L 11?
Base image buildpack-deps:bullseye │ 6C 64H 132M 136L 11?
Refreshed base image buildpack-deps:bullseye │ 1C 2H 3M 157L 3?
│ -5 -62 -129 +21 -8
Updated base image buildpack-deps:stable │ 1C 2H 3M 103L 3?
│ -5 -62 -129 -33 -8
What's Next?
Learn more about vulnerabilities → docker scout cves ruby:3.1.2
Learn more about base image update recommendations → docker scout recommendations ruby:3.1.2
これを実行すると対応方法を教えてくれます
基本はベースイメージを変更することで脆弱性に対応できるので dockerhub でベースイメージの別タグを探すと良いです
https://hub.docker.com/_/ruby/tags?page=&page_size=&ordering=&name=3.1.2 例えば 3.1.2 であれば 3.1.2-alpine3.14 にするだけでかなり減ります
INFO New version 1.9.3 available (installed version is 0.16.1)
✓ Pulled
✓ Image stored for indexing
✓ Indexed 128 packages
Your image ruby:3.1.2-alpine3.14 │ 2C 8H 8M 0L
Base image alpine:3.14 │ 1C 2H 5M 0L
Updated base image alpine:3.20 │ 0C 0H 2M 0L 1?
│ -1 -2 -3 +1
What's Next?
Learn more about vulnerabilities → docker scout cves ruby:3.1.2-alpine3.14
Learn more about base image update recommendations → docker scout recommendations ruby:3.1.2-alpine3.14
ただベースイメージを変更するとイメージ内で使用するコマンドも変わってくるのでベースイメージを変更した場合は Dockerfile などを書き換える必要がでてきます
3.1.2 -> 3.2.4 にすることで更に脆弱性を減らせます
INFO New version 1.9.3 available (installed version is 0.16.1)
✓ Provenance obtained from attestation
✓ SBOM obtained from attestation, 127 packages indexed
✓ Pulled
Your image ruby:3.2.4-alpine3.20 │ 0C 0H 3M 0L 1?
Base image alpine:3.20 │ 0C 0H 2M 0L 1?
What's Next?
Learn more about vulnerabilities → docker scout cves ruby:3.2.4-alpine3.20
docker scout を試してみました
基本的に脆弱性が出たらベースイメージを変更することを検討しましょう
またイメージで使われているツールやソフトウェアの CVE もチェックできるのでソフトの脆弱性をチェックしたい場合は以下のコマンドを使いましょう
答え: Skype for cloud からダウンロードしましょう
Mac、iPhone の Skype では再生もダウンロードもできない状態です
なぜか Mac 上だと再生もダウンロードもできません
ダウンロードしようとすると「ダウンロードに失敗しました」と表示されます
ここhttps://web.skype.com/?openPstnPage=true にログインするとブラウザで Skype が使えます
ここからだとダウンロードも再生もできました
Skype for Mac だとうまくダウンロードできない場合には Skype for cloud を試してみてください
それでもダメな場合は Windows クライアントなども試す価値はありそうです
前回指定の日時にcronが実行されるかどうかチェックするスクリプトを作成しました
今回は更にそれを応用して指定の cron が一日に何回実行されるのかカウントしてみました
from datetime import datetime, timedelta
from croniter import croniter
def count_run_today(cron_expression, target_date: str):
# 指定の日付の開始、指定の日付の明日の開始時刻を取得
target_datetime = datetime.strptime(target_date, "%Y/%m/%d")
today_start = datetime(
target_datetime.year, target_datetime.month, target_datetime.day
) - timedelta(seconds=1)
tomorrow_start = today_start + timedelta(days=1) + timedelta(seconds=1)
# cron オブジェクトの作成
cron = croniter(cron_expression, today_start)
# 当日内に実行される日時の分だけカウントする
run_count = 0
while True:
# 次に実行される日時を取得
next_run = cron.get_next(datetime)
if today_start < next_run < tomorrow_start:
run_count += 1
else:
break
return run_count
# テスト正常系
print("正常系テスト")
print(count_run_today("0 12 * * *", "2024/06/24")) # => 1
print(count_run_today("0 12 24 6 *", "2024/06/24")) # => 1
print(count_run_today("*/1 * * * *", "2024/06/24")) # => 1440
print(count_run_today("*/5 * * * *", "2024/06/24")) # => 288
print(count_run_today("*/30 * * * *", "2024/06/24")) # => 48
print(count_run_today("*/30 1 * * *", "2024/06/24")) # => 2
当日分の cron が正しく全件実行されるか確認したいときに使えるスクリプトです
例えば */5 * * * *
は本日実行される cron で 30 12 22 6 *
は本日実行されない cron というのを判定することができるスクリプトを紹介します
from datetime import datetime, timedelta
from croniter import croniter
def will_run_today(cron_expression):
# 今日の日付と今日の開始、明日の開始時刻を取得
now = datetime.now()
today_start = datetime(now.year, now.month, now.day) - timedelta(seconds=1)
tomorrow_start = today_start + timedelta(days=1) + timedelta(seconds=1)
# cron オブジェクトの作成
cron = croniter(cron_expression, today_start)
# 次に実行される日時を取得
next_run = cron.get_next(datetime)
# 次に実行される日時が今日中であればTrueを返す
return today_start < next_run < tomorrow_start
# テスト正常系(2024/06/21(木)に実行した想定)
print("正常系テスト")
print(will_run_today("0 12 * * *"))
print(will_run_today("*/5 * * * *"))
print(will_run_today("*/1 * * * *"))
print(will_run_today("*/30 * * * *"))
print(will_run_today("*/30 5 * * *"))
print(will_run_today("*/30 5 * 6 *"))
print(will_run_today("*/30 5 * 6 *"))
print(will_run_today("59 23 21 6 *"))
print(will_run_today("59 23 * * 5"))
print(will_run_today("59 23 21 6 5"))
print(will_run_today("1 0 21 6 5"))
print(will_run_today("0 0 * * *"))
print(will_run_today("0 0 21 6 5"))
print(will_run_today("*/30 * * * 1-5"))
# テスト異常系
print("異常系テスト")
print(will_run_today("0 12 3 2 *"))
print(will_run_today("0 12 22 6 *"))
print(will_run_today("*/5 * 22 6 *"))
print(will_run_today("*/1 * * * 4"))
print(will_run_today("*/1 * * * 0,1,2,3,4,6"))
print(will_run_today("30 12 22 * *"))
from datetime import datetime, timedelta
from croniter import croniter
def will_run_today(cron_expression, target_date: str):
# 指定の日付の開始、指定の日付の明日の開始時刻を取得
target_datetime = datetime.strptime(target_date, "%Y/%m/%d")
today_start = datetime(
target_datetime.year, target_datetime.month, target_datetime.day
) - timedelta(seconds=1)
tomorrow_start = today_start + timedelta(days=1) + timedelta(seconds=1)
# cron オブジェクトの作成
cron = croniter(cron_expression, today_start)
# 次に実行される日時を取得
next_run = cron.get_next(datetime)
# 次に実行される日時が指定日時内であればTrueを返す
return today_start < next_run < tomorrow_start
# テスト正常系(2024/06/21(木)に実行した想定)
print("正常系テスト")
print(will_run_today("0 12 * * *", "2024/06/21"))
print(will_run_today("0 12 3 2 *", "2024/02/03"))
print(will_run_today("*/1 * * * *", "2024/01/01"))
print(will_run_today("0 0 * * *", "2024/01/01"))
# テスト異常系
print("異常系テスト")
print(will_run_today("0 12 22 6 *", "2024/06/21"))
cron が大量にありその中で本日実行されるのが何個あるのかチェックしたりするのに使えます
Slidev は markdown でスライドが作成できるツールです
今回は簡単な使い方を紹介します
適当な markdown を作成しましょう
ファイル名は slides.md
にします
# Slidevへようこそ!
開発者のためのプレゼンテーションスライド
---
# Page 2
- 📄 スライドを1つのMarkdownファイルで
- 🌈 テーマ、コードブロック、インタラクティブなコンポーネント
- 😎 詳しくはドキュメントをご覧ください!|
docker run --name slidev --rm -it \
--user node \
-v ${PWD}:/slidev \
-p 3030:3030 \
-e NPM_MIRROR="https://registry.npmmirror.com" \
tangramor/slidev:latest
マウントしているカレントに node_modules なども作成されるので注意しましょう
次回以降同じディレクトリで動作しないと再度作成されてしまいます
http://localhost:3030/ にアクセスするとスライドが確認できます
セクションが長すぎると画面をはみ出てしまうのではみ出る場合はセクション内の文章を短くしましょう
少し記法が特殊な部分があるのでそこは対応が必要です
YAML ヘッダなどは使えます
前回 dockerhub に push するアクションを作成しました
今回は rubygems に push するアクションを作成しました
name: ci
on:
workflow_dispatch:
inputs:
rubygems-otp-code:
description: RubyGems OTP code
required: true
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2.2
- run: bundle install
- name: Setup git config
run: |
git config --global user.email "your-github-email-address@xxx.com"
git config --global user.name "your-github-name"
- name: git
run: |
git status
git diff
- name: Publish to RubyGems
run: bundle exec rake release
env:
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
設定 -> API キー
で作成できます
rubygems に push できる権限を扶養しましょう
リポジトリのシークレットに登録します
自分のプロジェクト -> Settings -> Secrets and variables -> Actions -> Repository secrets -> New repository secret
ローカルの開発環境が Mac の場合 nokogiri など darwin 用のパッケージがインストールされます
nokogiri (1.16.6-x86_64-darwin)
racc (~> 1.4)
この状態の Gemfile.lock で Github Actions 上の Ubuntu で bundle install を実行すると linux 用の nokogiri がインストールされます
+ nokogiri (1.16.6-x86_64-linux)
+ racc (~> 1.4)
Github Actions では必ずこれがインストールされてしまうので事前に Mac 上で Linux 用のパッケージも追加してあげる必要があります
Rubygems で 2auth を有効にしている場合はワンタイムパスワードを入力する必要があります
env に GEM_HOST_OTP_CODE: ${{ github.event.inputs.rubygems-otp-code }}
を追加することでアクション実行時にワンタイムパスワードを入力することができるのでこれで対応します
version.rb や bundle update をして何かしら更新しましょう
そして Github に push します
今回ワークフローは手動でなので手動実行します
さらにワンタイムパスワードを入力しましょう
するとワークフローが実行されて version.rb に記載した新しいバージョンの gem が公開されていることが確認できると思います
Github Actions で rubygems に自動で push してみました
master に push されると自動で実行されます
Rubygems の API キーには有効期限があるので切れた場合は再度 Github に登録してあげましょう
RequestValidationError をハンドリングします
Request と RequestValidationError のリファレンスは参考サイトに記載しています
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from pydantic import BaseModel, Field
from starlette.requests import Request
from starlette.responses import JSONResponse
app = FastAPI()
class Item(BaseModel):
message: str = Field(max_length=10)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
# print(request)
errs = exc.errors()
print(errs)
return JSONResponse(
{"error_field": errs[0]["loc"][1], "message": errs[0]["msg"]}, status_code=400
)
@app.post("/")
async def post_msg(item: Item):
return {
"message": item.message,
}
errors で取得した情報は配列なので扱いには注意しましょう
compose.yaml と nginx.conf の設定ファイルを紹介します
ポイントは RQ_DASHBOARD_URL_PREFIX
を設定する点です
upstream rq_dashboard {
server 192.168.0.100:9181;
}
server {
listen 80;
server_name host01;
location = /rq_dashboard {
return 302 /rq_dashboard/;
}
location /rq_dashboard/ {
proxy_set_header Host $host;
proxy_pass http://rq_dashboard;
}
}
services:
rq_dashboard:
image: eoranged/rq-dashboard
environment:
RQ_DASHBOARD_REDIS_URL: redis://192.168.0.101:6379
RQ_DASHBOARD_USERNAME: user01
RQ_DASHBOARD_PASSWORD: xxx
RQ_DASHBOARD_URL_PREFIX: /rq_dashboard
ports:
- 9181:9181
スラッシュなしをリダイレクトしているのはなぜかうまく Chrome がリダイレクトしてくれないので明示的にリダイレクトルールを記載しています
rootURI を編集します
設定ファイルを置くパスがポイントです
/opt/cloudbeaver/conf/cloudbeaver.conf に設定ファイルを配置します
dbeaver は 192.168.0.100:8978 で動作します
services:
dbeaver:
image: dbeaver/cloudbeaver:24.1.0
volumes:
- type: volume
source: dbeaver
target: /opt/cloudbeaver/workspace
- type: bind
source: /home/user01/work/cloudbeaver.conf
target: /opt/cloudbeaver/conf/cloudbeaver.conf
ports:
- 8978:8978
restart: always
volumes:
dbeaver:
少し長いですがすべて掲載しています
変更するのは冒頭の rootURI の部分だけです
それ以外はすべてデフォルトの設定です
今回は /dbeaver
で受けます
{
server: {
serverPort: 8978,
workspaceLocation: "workspace",
contentRoot: "web",
driversLocation: "drivers",
sslConfigurationPath:"${CLOUDBEAVER_SSL_CONF_PATH:workspace/.data/ssl-config.xml}",
rootURI: "/dbeaver",
serviceURI: "/api/",
productSettings: {
# Global properties
core.theming.theme: 'light',
core.localization.localization: 'en',
plugin.sql-editor.autoSave: true,
plugin.sql-editor.disabled: false,
# max size of the file that can be uploaded to the editor (in kilobytes)
plugin.sql-editor.maxFileSize: 10240,
plugin.log-viewer.disabled: false,
plugin.log-viewer.logBatchSize: 1000,
plugin.log-viewer.maxFailedRequests: 3,
plugin.log-viewer.maxLogRecords: 2000,
plugin.log-viewer.refreshTimeout: 3000,
sql.proposals.insert.table.alias: PLAIN
},
expireSessionAfterPeriod: 1800000,
develMode: false,
enableSecurityManager: false,
sm: {
enableBruteForceProtection: "${CLOUDBEAVER_BRUTE_FORCE_PROTECTION_ENABLED:true}",
maxFailedLogin: "${CLOUDBEAVER_MAX_FAILED_LOGINS:10}",
minimumLoginTimeout: "${CLOUDBEAVER_MINIMUM_LOGIN_TIMEOUT:1}",
blockLoginPeriod: "${CLOUDBEAVER_BLOCK_PERIOD:300}",
passwordPolicy: {
minLength: "${CLOUDBEAVER_POLICY_MIN_LENGTH:8}",
requireMixedCase: "${CLOUDBEAVER_POLICY_REQUIRE_MIXED_CASE:true}",
minNumberCount: "${CLOUDBEAVER_POLICY_MIN_NUMBER_COUNT:1}",
minSymbolCount: "${CLOUDBEAVER_POLICY_MIN_SYMBOL_COUNT:0}"
}
},
database: {
driver: "h2_embedded_v2",
url: "jdbc:h2:${workspace}/.data/cb.h2v2.dat",
initialDataConfiguration: "conf/initial-data.conf",
pool: {
minIdleConnections: 4,
maxIdleConnections: 10,
maxConnections: 100,
validationQuery: "SELECT 1"
},
backupEnabled: "${CLOUDBEAVER_DB_BACKUP_ENABLED:true}"
}
},
app: {
anonymousAccessEnabled: true,
anonymousUserRole: "user",
defaultUserTeam: "user",
grantConnectionsAccessToAnonymousTeam: false,
supportsCustomConnections: false,
showReadOnlyConnectionInfo: false,
systemVariablesResolvingEnabled: "${CLOUDBEAVER_SYSTEM_VARIABLES_RESOLVING_ENABLED:false}",
forwardProxy: false,
publicCredentialsSaveEnabled: true,
adminCredentialsSaveEnabled: true,
resourceManagerEnabled: true,
resourceQuotas: {
dataExportFileSizeLimit: 10000000,
resourceManagerFileSizeLimit: 500000,
sqlMaxRunningQueries: 100,
sqlResultSetRowsLimit: 100000,
sqlResultSetMemoryLimit: 2000000,
sqlTextPreviewMaxLength: 4096,
sqlBinaryPreviewMaxLength: 261120
},
enabledAuthProviders: [
"local"
],
disabledDrivers: [
"sqlite:sqlite_jdbc",
"h2:h2_embedded",
"h2:h2_embedded_v2",
"clickhouse:yandex_clickhouse"
],
disabledBetaFeatures: [
]
}
}
location /dbeaver/ を定義します
proxy_set_header 系はそのままコピペで OK です
location = /dbeaver はリダイレクト用でなぜか自動でブラウザがリダイレクトしてくれないケースがあるので明示しておきます
末尾のスラッシュがない場合にスラッシュのある URI に移動させます
upstream dbeaver {
server 192.168.0.100:8978;
}
server {
listen 80;
server_name my_nginx;
location = /dbeaver {
return 302 /dbeaver/;
}
location /dbeaver/ {
proxy_pass http://dbeaver;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
これで nginx と dbeaver を起動させ nginxのアドレス/dbeaver にアクセスすると画面が表示されます
DBeaver を nginx 配下で動作させる方法を紹介しました
サブディレクトリを指定する場合は dbeaver 側の rootURI も変更する必要があります
cd /
find . -name ".*" -type f | xargs grep -i "hoge"
前回 oauth2-proxy を構築しました
今回はその構築したプロキシを使って nginx と組み合わせてみます
最低限設定が必要な箇所だけ紹介します
server ディレクティブを編集します
location /oauth2/
と location = /oauth2/auth
は必須です
そして認証をかけたい部分 (今回だと location /
) に auth_request と error_page お記載します
こうすることで / にアクセスされた際に oauth2-proxy に認証させることができます
server {
listen 80 default_server;
listen [::]:80 default_server;
location /oauth2/ {
proxy_pass http://localhost:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Auth-Request-Redirect $request_uri;
# or, if you are handling multiple domains:
# proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
}
location = /oauth2/auth {
proxy_pass http://localhost:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Uri $request_uri;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
auth_request /oauth2/auth;
error_page 401 =403 /oauth2/sign_in;
try_files $uri $uri/ =404;
}
}
前回の設定のままで OK です
で再起動し localhost にアクセスすると認証ページに移動することを確認します
nginx は当然アクセスできる必要があるのですが auth2-proxy にもクライアントからアクセスできる必要があります
これはリダイレクト先が auth2-proxy になっているためで auth2-proxy のリダイレクト URL にブラウザからアクセスできないと認証情報が受け取れないためです
なのでクライアントには 80 と 4180 の auth2-proxy のポートも開放する必要があります
oauth2-proxy と nginx を組み合わせてみました
認証後の情報がバックエンド側のアプリでほしい場合には nginx 側でスルーするヘッダなどを設定しましょう
oauth2-proxy は nginx や traefik などでホスティングした静的ページに対して認証をつけることができるツールです
今回はとりあえず単体で動かしてみました
また今回紹介する設定は localhost で動作させる設定になります
こちらの記事を参考に取得します
provider = "oidc"
redirect_url = "http://localhost:4180/oauth2/callback"
oidc_issuer_url = "https://xxxxx.onelogin.com/oidc/2"
upstreams = [
"http://0.0.0.0"
]
email_domains = [
"*"
]
client_id = "xxx"
client_secret = "xxx"
pass_access_token = true
cookie_secret = "hTsaC2-8_RVIU4VmTRsC_A=="
cookie_secure = false
skip_provider_button = true
# Note: use the following for testing within a container
http_address = "0.0.0.0:4180"
設定するべき項目は以下です
cookie_secret は以下のようなコマンドで推測されにくいランダムな文字列を設定することをオススメします
python -c 'import os,base64; print(base64.urlsafe_b64encode(os.urandom(16)))'
認証後は upstreams に指定している URL の情報が表示されます
これで localhost:4180 にアクセスすると Onelogin の認証画面になります
認証が成功すると upstreams に設定した URL のコンテンツ情報が表示されます
OAuth2 Proxy を単体で動作させてみました
まずは単体で動作させてどういう挙動になるのか確認したほうが良いかなと思います
次回は nginx と連携してみます
cronv は crontab の情報から html ファイルを生成してくれるツールです
基本は6時間分しか出力しないので24時間を指定します
-d
オプションを使います
--from-date
オプションを使います
パイプで文字列を渡せば良いだけなので crontab -l でなくても OK です
生成される html の先頭のタイトルを変更します
バーの数が実行される数になります
横軸は1時間になるので1時間で何回実行されるのか確認できます
cronv で crontab 情報を可視化してみました
html を生成してくるだけなので動的に変更したい場合は何かしらの仕掛けが必要になりそうです
-d
を使えば表示する間隔は変更できますが例えば毎月2日に実行するようなルールでもプロットはしてしまうので毎日実行するような cron 情報しかプロットできません
dbeaver はいろいろなデータベースに対応したクライアントツールでテーブルの一覧や好きな SQL を発行することができます
phpMyAdmin の代替として使えます
基本はマシン上で動作するクライアントアプリですが今回は docker 上で動かしてみました
以下のコマンド一発です
起動すると 8080 ポートで起動します
エンタープライズエディションもありますがアクティベーションキーが必要になるのでコミュニティエディションを使います
起動するとまず初期設定をします
必ず設定しなければいけないのは管理者のパスワードです
パスワードにはポリシーがあるのでそれに沿ったパスワードにしましょう
管理者のパスワードを設定すると次にコネクションテンプレートというテンプレートを作成する画面になりますがそこはスルーして一度トップ画面に戻ります
そして上部のプラスボタンからコネクションを作成します
テンプレートを作成しない理由としては本当はテンプレートからコネクションを作成できるボタンがあるのですがコミュニティエディションだとそれがなかったのでテンプレートを作成する意味がないからです
いろいろなデータベースコネクタがあるので MySQL を選択します
次に接続先のデータベースの情報を入力します
今回は docker 上で動作させているので localhost だとコンテナにアクセスしに行ってしまうので基本は IP や FQDN を入力することになります
MySQL はデフォルトだと localhost からのみアクセスできるようになっています
今回は docker 上のコンテナの IP (ex 172.17.0.2) からのアクセスになるのでその IP からのアクセスを許可します
こちらを参考に特定の IP からでもアクセスできるユーザを作成します
接続テストをした際に「Public Key Retrieval is not allowed」エラーが出る場合にはドライバの設定を変更します
DRIVER PROPERTIES タブを選択し「allowPublicKeyRetrieval」を TRUE に設定します
これで再度右上の「Test」をクリックして接続テストしてください
コネクションが作成できたらデータベースやテーブルの一覧が表示できることを確認しましょう
よくわからないのですがコネクション作成時にデータベースを指定してもすべてのデータベース情報を取得するようです
Dbeaver を docker で動かしてみました
コミュニティエディションなので一部機能が使えなかったりするようです
閲覧するだけならこれで十分かなと思います
またダークモードや好きな SQL を発行する機能もあるので便利です
MySQL の Web クライアントで phpMyAdmin の代替になりそうなツールとして他にも ILLA Builder というツールを紹介しています
Dbeaver 自体は Java で書かれています
前回 kohya_ss webui を使って sd-scripts が実行できる環境を用意しました
今回は kohya_ss webui を使って LoRA 学習してみたいと思います
今回は 512x512 画像を 4 枚用意しました
枚数は多ければ多いほど良いですが画像が多いとそれだけ学習時間もかかります
また M2 mac mini のスペックにも影響しており画像が多いとメモリを多大に消費するため可能な限り少なく効率の良い画像を学習させるのが良いかなと思います
作成した画像は今回は ~/Downloads/data/5_hawksnowlog
というディレクトリ配下に配置します
ポイントはディレクトリ名で 学習回数_識別名
という感じで指定しないと sd-scripts が画像を発見できません
学習回数は学習させる枚数をかけた分影響するので学習回数が多いと学習にかかる時間も線形的に増えるので注意しましょう
なくても OK ですがあったほうがいいと思います
こちらを参考に抽出/付与しましょう
また何か独自のタグをいれるとより LoRA で学習させたモデルを強調することができます
まずは LoRA タブに移動します
そして各種パラメータを設定していきます
WebUI 上でも OK です
M2 上で動作させるには以下の設定が必須です
デフォルトでは見えない設定もあるのですべての項目を一度開いて設定項目名で研削すれば見つかるはずです
sd-scripts の実行には設定ファイルが必要ですが kohya_ss は webui で設定した値から自動で toml 設定ファイルを作成してくれます
最終的には実行後に以下の設定ファイルが model 配下にあれば OK です
bucket_no_upscale = true
bucket_reso_steps = 64
cache_latents = true
caption_extension = ".txt"
clip_skip = 1
dynamo_backend = "no"
enable_bucket = true
epoch = 1
gradient_accumulation_steps = 1
huber_c = 0.1
huber_schedule = "snr"
learning_rate = 0.0001
logging_dir = "log"
loss_type = "l2"
lr_scheduler = "cosine"
lr_scheduler_args = []
lr_scheduler_num_cycles = 1
lr_scheduler_power = 1
lr_warmup_steps = 160
max_bucket_reso = 2048
max_data_loader_n_workers = 0
max_grad_norm = 1
max_timestep = 1000
max_token_length = 75
max_train_steps = 200
min_bucket_reso = 256
mixed_precision = "no"
multires_noise_discount = 0.3
network_alpha = 1
network_args = []
network_dim = 8
network_module = "networks.lora"
noise_offset_type = "Original"
optimizer_args = []
optimizer_type = "AdamW"
output_dir = "model"
output_name = "5_hawksnowlog"
pretrained_model_name_or_path = "runwayml/stable-diffusion-v1-5"
prior_loss_weight = 1
resolution = "512,512"
sample_prompts = "model/prompt.txt"
sample_sampler = "euler_a"
save_every_n_epochs = 1
save_model_as = "safetensors"
save_precision = "float"
text_encoder_lr = 0.0001
train_batch_size = 1
train_data_dir = "/Users/hawksnowlog/Downloads/data"
unet_lr = 0.0001
xformers = false
WebUI で実行する場合は「Start training」で OK です
安定しない場合はコマンドでも OK です
toml ファイルは webui が生成したもので大丈夫ですが値が間違っている場合は手動で toml ファイルを変更して学習を開始しましょう
4 ファイルで 5 回の学習回数でステップ数 200 にしてだいたい 30 分ほどで完了しました
かなり少なめで学習させたのでもう少し画像を増やしたり学習回数を増やしてもいいかもしれません
学習が完了すると model/5_hawksnowlog.safetensors
ができています
M2 mac mini 上で Stable Diffusion のモデルを LoRA で Fine-Tuning してみました
内部的には sd-scripts という学習ツールを webui で叩いているだけなので直接 sd-scripts を触ってしまっても OK です
次回は作成した LoRA を使って sd-webui 上で LoRA の動作確認をしてみたいと思います
libc++abi: terminating due to uncaught exception of type NSException
なぜか webui から学習が開始できなくなってしまう状況が発生しました
バックグラウンドで何か動いてしまっているのでマシンを再起動してあげれば解消しました
output_name で指定したモデルがすでにあると発生するようです、名前を変更してあげましょう
AttributeError: module 'torch' has no attribute 'compiler'
なぜか xformers ディレクトリが作成されており参照してしまっているので削除しましょう
stable-diffusion-webui-wd14-tagger を使います
例のごとく Extensions から URL を指定すれば OK です
インストールとは Apply and restart UI しましょう
Tagger タグが webui 上に追加されているのでそこから行います
今回は一枚の画像ではなく複数の画像に対して行うので「Batch from directory」に切り替えます
最低限入力する箇所は以下です
であとは「Interrogate」をクリックすればタグの抽出が行われます
画面真ん中くらいにある保存ボタンを押せば OK です
あとは Output directory 配下に「画像ファイル名.txt」の形式でタグ情報が画像ごとに保存されます
sd-webui で画像からタグ情報を抽出してみました
タグを抽出する目的は大きく2つです
bmaltais/kohya_ss は sd-scripts という StableDiffusion の LoRA モデルや DreamBooth トレーニングを行うためのスクリプト郡を WebUI で実行できるようにしたツールです
今回は M2 mac mini 上で動作させてみました
必要なパッケージなどはすべて自動でインストールしてくれます
これで localhost:7860 で起動します
sd-scripts 専用の webui ツール kohya_ss を M2 mac mini 上で動作させてみました
次回はこれを使って LoRA モデルを作成してみたいと思います