re:annkara

日々学んだことを書き留めておく。

日本語文書内の不自然なアルファベットを検出する

Kibana 7.2.0から日本語に対応している。
使っているとちょいちょい不自然なアルファベットが紛れ込んでいることに気づいて、2度ほどissueを挙げた経緯がある。

目視で検出するのも良いが、機械的に検出できないかと思ってGoで実装した。

GitHub - annkara/Unnatural-Alphabet: 日本語文書内の不自然なアルファベットを検出する。

単純に正規表現で 日本語1文字 + アルファベット1文字 + 日本語1文字 のパターンにマッチするものを出力するだけ。

試しにv7.4.0のja-JP.jsonファイルを対象に使ってみるとissueとして挙げた二か所が検出できたので、ある程度の精度は保てていそう。

というか、他にもあることに気づいたので最新のバージョンで直ってなかったらissueあげておこう。

"kbn.management.objects.objectsTable.howToDeleteSavedObjectsDescription": "ここから保存された検索などの保存されたオブジェクトを削除できます。保存されたオブジェクトの生データを編集することもできます。通常、オブジェクトは関連アプリケーションでのみ編集され、こn画面で編集するよりもそちらのほうが賢明です。",

"timelion.topNavMenu.save.saveAsDashboardPanelDescription": "Kibana ダッシュボードにチャートの追加が必要ですか?できます!このオプションは、現在選択されている式を、他のオブジェクトの追加と同じように Kibana ダッシュボードに追加可能なパネルとして保存します。他のパネルへのリファレンスが使用されている場合、リファレンスの表現を直接保存する表現にコピーして、リファレンスを削除する必要があります。他の表現式を保存するよう選択すrには、チャートをクリックします。",

"xpack.monitoring.metrics.beats.failRates.droppedInPipelineDescription": "N 回の試行後ドロップされたtイベントです (N = max_retries 設定)",
"xpack.monitoring.metrics.beatsInstance.failRates.droppedInPipelineDescription": "N 回の試行後ドロップされたtイベントです (N = max_retries 設定)",
"xpack.security.loginPage.welcomeDescription": "Elastic Stack へのi入口",

参考

不自然なアルファベットを見つけるtextlintルール | Web Scratch

CiNii 論文 -  日本語文章校正ツール"Chanterelle" : 入力ミス及び表記揺らぎについて

2019年を振り返る

 

reannkara.hatenablog.com

 

2019年を振り返る。

 

2019年の目標に関して

2019年の年初にあげた目標を達成することはできなかったが、Elastic StackやRedisなどのミドルに関しては、実運用に足る知識と実践を積むことはできたと思う。

 

Goに本格入門した

縁あってGoper道場の第六期生として参加させて頂いた。

 独学で学んでいたGoだったけど、改めて体系的に学ぶ場を提供していただいて本当に良い経験となった。

人生初のライトニングトークもさせていただいて、アウトプットする大切さを改めて痛感した。

docs.google.com

 

仕事について

 テックリードみたいな役割をやっていた。

役職にあるわけじゃないのだけど、そういう役割を持った人が存在することで上手く回るんじゃないかと思って意識的にやっていた。

技術的な意思決定を行うこと、チーム員が課題に直面した際の助言を行うこと、コードレビューを行うこと、課題に対してあらかじめ技術的な調査を行うことなど、様々な面で気を配ることが多かった。

その反面、色々と得られるものも多かったと思う。この辺の経験をうまくアウトプットしたいなと思っている。

 

総じて

2019年、当初思っていたようなことはできなかったけど、それでも様々な面で色んな経験とインプットをすることができていて非常に実りある一年だったと思う。

来年以降はもっとアウトプットすることを意識していきたい。

優れたアウトプットは人を動かす

12月8日(日)に開催されたJuly Tech Festa 2019に参加してきました。

2019.techfesta.jp

最近の自分の傾向として技術的な領域への関心と共に、チームビルディングやアウトプット、エンジニアとしてのマインドなど非技術的な側面にも興味が出てきました。なので、今回はそのような領域のセッションを中心に参加してきました。

参加してきたのは以下の4つのセッションです。

  1. Design Proposal は文化を創る
  2. 「極める、伝える、教える」の調和
  3. 「エンジニア像」を言語化し文化の礎を築く
  4. エンジニアはアウトプットによって成長できるのか?

ただ、今回はGMOペパボ社のP山さんによる基調講演中のhsbt文書が非常に良いなと思ったのでそのことについて書きたいと思います。

「ペパボっぽい」 エンジニアカルチャーを創る 言葉と仕組み - Speaker Deck

hsbt文書とは

基調講演の資料の中では以下のスライドに記載されている文章です。

https://speakerdeck.com/pyama86/pepabotupoi-enziniakarutiyawochuang-ru-yan-xie-toshi-zu-mi?slide=84

別のイベントでP山さんが登壇されたセッションの記事を見ると、@hsbtさんが記述したことからhsbt文書と呼ばれてるそうです。

エンジニアが「優れたアウトプット」をするために必要なこと - ログミーTech

何が自分に刺さったのか

この文書を読んだときにどんな点が自分に刺さったのか考えてみると大きく2つの要因があると思います。

  1. 評価基準を明確にしている点
  2. 優れたアウトプットを定義している点
評価基準を明確にしている点

GMOペパボ社が重要視している価値観として「みんなと仲良くすること」というものがある。

この理念に沿った社員の評価を行う際には、他者と協力して何かを成し遂げたということに留まらず、その結果がまた別の良いコミュニケーションを生み出すことでその結果を優れたものとして評価できると明文化している。

つまり、被評価者が通常であれば取りうるコミュニケーションのスコープを大幅に超えて新たなコミュニケーションの連鎖を生み出し、アウトプットを生み出すことができればそれは優れた業績として評価ができると自分は解釈した。

良いなと思ったのがこういった評価基準を明文化し、共有できること自体が非常に価値あるものだと思ったので刺さったのだと思う。

優れたアウトプットを定義している点

hsbt文書の中では

優れたアウトプットというのは「アウトプットによって人に行動を引き起こさせたかどうか」

というように、明文化している。

自分がアウトプットに対して明確な考えを持っていないことにモヤモヤとしたものを感じており、この文章により新しい視点を得たことによってアウトプットに対する認識が明確になったと思う。

振り返って

hsbt文書は優れたアウトプットの大枠を明文化していると思うのだけど、個別具体的な部分までは記述されていない。
これはアウトプットというものが非常にスコープの広い概念であるので仕方のないことだと思う。

ただ、優れたアウトプットというものは人を動かすものであるという認識を常に持ちながら、自身が何かアウトプットする際には、これは人を動かし得るものなのか自問自答しながら行うことでより良いものが生み出されるのではないかと思う。

最初はJTF2019の感想をただ書こうと思ったのだけど、優れたアウトプットに突き動かされた一人として自身のアウトプットとして残してみました。

この文書がまた他の誰かの目に留まってまた別のアクションが生み出されると、この文書を書いた自分としても嬉しい限りです。

最後にJTF2019に関わった全ての人に感謝します。とても楽しい時間でした。ありがとうございます。

LINE DEVELOPER DAY 2019 DAY2 参加メモ

DAY2の参加メモです。

Armeria:どこでも役立つマイクロサービスフレームワーク

ArmeriaというLINE社が開発しているOSSのマイクロサービスフレームワークについてのセッション。

line.github.io

nettyプロジェクトの創設者が開発に携わっていることもあり、nettyベースのフレームワークとなっている。
ドキュメント見る限りではシンプルだけどもマイクロサービスに必要な機能をフレームワークとして提供している。

フレームワークの機能としてクライアントロードバランサの機能を実装していたり、SSL/TLS終端ができたりするのでリバースプロキシレスを謳っているのも特徴的。

ドキュメントもしっかりしているので、入門してみたいと思う。

LINE Loginで始めるAuth0の使い方 - 認証基盤をかんたんに構築する方法

LINE LOGIN + Auth0の紹介セッション。

LINE LOGIN

LINE LOGIN は様々なチャネルにLINEアカウントでログインできるようになるサービス。
自社サービスのログインにLINEアカウントでログインできるようになったりする。

Auth0

Auth0は認証・認可のIDaaS。
LINE LOGINもAuth0で利用できるようになっている。

認証・認可の機能はアプリケーションを提供するうえで必須の機能ではあるものの、サービスのコア機能ではない。

また仕組みや実装自体が難しいので他のサービスを利用するというのは十分ありだと感じた。

LINE Pay かんたん本人確認の仕組みとLINEの金融関連サービスとのシナジー効果

LINE上で本人確認できる仕組みに関するセッション。

本人確認(KYC)とは何か

KYC(Know Your Customer )とは、企業がクライアントに対して安全で問題のない人だと確認するプロセスのこと。

銀行口座を開設する際にIDなどを提出して、その人が問題ないか確認するプロセスのこと。

LINEにおけるKYC

今まで物理的なIDなどを提出し人手による本人確認を行っていたものを、スマホで顔写真+身分証明書の写真・動画を送付し、確認プロセスを自動化する仕組みを構築。

金融業を営む上では本人確認プロセスというのは避けられない業務プロセスであるらしく、その業務プロセスを技術で改善していくのは流石だと思いました。

既存の企業が営む業務領域を、技術で再実装していくのは面白いプロセスだろうなとも感じました。

まとめ

全体を通して非常に刺激あるカンファレンスでした。

運営の方をはじめ、本カンファレンスに関わったすべての人に感謝します。

LINE DEVELOPER DAY 2019 DAY1 参加メモ

LINE DEVELOPER DAY 2019 DAY1に参加してきました。
DAY2も参加したので、分けて書こうと思います。

スライドは以下のリンク先に公開されています。

Presentations by LINE DevDay 2019 - Speaker Deck

Keynote

LIFE with LINE

私のLINEの利用経験としては単にメッセージサービスくらいにしか利用していないのですが、提供しているサービスの幅広さに驚きました。

金融分野からeコマース、エンターテイメントなど人が生活する上で必要になる領域において、LINEというプラットフォームをベースに様々な分野でサービスを提供していることを改めて気づきました。

Natural Experience with AI

様々なサービスを提供しているLINEですが、そのサービスの中心になりつつあるのがAI技術である印象を強く持ちました。

AI技術を活用することでユーザ体験を向上させることに繋げ、サービスをより利用してもらうようにする。

そのためには必要なデータを必要な時に扱えるようにデータプラットフォームの整備や、サービスの開発ライフサイクルに合わせたインフラ基盤の提供、データに対するセキュリティやプライバシー保護などの仕組みを整えている。

ビジネスとテクノロジが上手く融合していて、こういう企業で働けると楽しそうだなという印象を持ちました。

特に、データプラットフォームの構築や柔軟なインフラ構築を実現するためにプライベートクラウドを自前で構築することでビジネスや開発者に貢献していくという点が非常に良いなと思いました。

プライベート Kubernetes クラスタにおける gRPC サービス開発

LINE LIVEという動画配信サービスの開発にプライベートクラウド上のKubernetesを導入した話。

Kubernetesを利用する理由

Kubernetesが必要になった理由として、サービスのトラフィックが増加した際に容易にシステムをスケールアウトできることが必要であった。 手動によるスケールアウト/スケールインを行っていたが運用負荷が高くなってしまっていた。

LINE内ではKubernetes Clusterの提供までがインフラ側の役割であり、アプリケーション側ではNamespaceの作成からPodのデプロイ、ロギング・メトリクスを収集する環境までを行う。

アーキテクチャ

サービスとしては、Envoy + SpringBoot + gRPC を組み合わせたマイクロサービスアーキテクチャで構成されている。

EnvoyはL7ロードバランサとしての役割 + プロトコルコンバータとして外部からのリクエストをgRPCプロトコルへと変換する役割を果たしている。

Istioの導入を避けた理由として、メトリクスの収集や分散トレーシング、サーキットブレーカやリトライパターンの実装などはSpringが提供する機能で賄うことができたり、レイテンシの低下を懸念して避けたとのこと。

Istioのパフォーマンスに関しては以下を参照。
Istio / Performance and Scalability

DBはプライベートクラウド内でマネージドなDBサービスを利用しているが、このDBにアクセスするためには接続元サーバのIPアドレスACLに登録する必要がある。

Kubernetesのノードスケールと相性が悪かったため、スケール時にフックしてACLにスケールしたサーバのIPアドレスを追加する仕組みを実装している。

メトリクス・ロギング・アラート

メトリクスの収集にはPrometheusを利用しており、収集したメトリクスは自社内で開発しているTSDBに格納している。

ログ収集には Fluentd + Elasticsearch + Kibana を利用しており、アラートなどは IMON と呼ばれる自社で開発しているツールを利用して検知・通知を行っている。

気になる技術

  • HTTP/2
  • gRPC
  • Envoy
  • Spring Boot Actuator
  • OpenCensus

どれも言葉としては知っているけど、深く調べたり実際に触ってみたわけではないので学習したい。

LINEが開発した時系列データベース‘Flash’の紹介

前のセッションで触れられていた時系列データベースに関するセッション。

Observabilityとは何か

システムの出力からそのシステムの内部状態がどれほど健全か推測できるよう計測を行うこと。
LINEのObservability Teamの役割はサービスが健全であるように手助けをすること。

そのためにメトリクス・ログ・分散トレーシングの集約を実現するインフラ基盤を提供している。

時系列データベースを実装するモチベーション

この数年で収集するメトリクスが劇的に増加した。
メトリクスの保存するストレージは当初はMySQLやOpenTSDBを利用していたが、障害が発生するたびに運用でカバーしていた。

OSSや商用製品の利用も検討したが、以下に述べる要件やコスト、カスタマイズ性の欠如のなどもあり自前で実装することにした。

時系列データベースにおけるLINE社の要件

  • 様々なプロトコルに対応していること
    • HTTP
    • UDP
    • Prometheus Protocol
  • Read/Writeの両方でスケールアウトできること
    • 10xのメトリクスをサポートできること
    • 低レイテンシの実現(Read/Write < 100msを99パーセントタイルで実現)
  • 低コストかつ容易にメンテナンスできること

実現したこと

  • 400万件/秒の書き込みを実現
  • 1000クエリ/秒を捌く
  • Read/Writeのレイテンシを100ms以内に(99パーセントタイル)

アーキテクチャ

  • 開発言語はGo言語を採用
  • 全てのコンポーネントを自前で実装することは避けた
    • バックエンドのストレージにはCassandraを採用
    • ラベルストレージにはElasticsearchを採用
    • Walログ??RaftログにはRocksDBを採用
  • マイクロサービスアーキテクチャを採用
    • 送信元を判別する情報と実際のデータを保管するストレージを分離
    • 分離したことでデータの保持方法を最適化できた
  • 直近28Hのデータをインメモリに保持する
    • 直近のデータはインメモリに保持
      • メモリ効率のために Delta-Delta XOR algorithmを採用
      • 水平スケールのためハッシュ値を元にデータを分散
        • RocksDBはここで利用されている??
    • それ以降のデータは永続化ストレージに保管(上記のCassandra)

プロトタイプ開発は2ヶ月ほどで終えたが、プロダクションレディにするためには1年ほどかかったそうだけど、それでも1年で実装したのは凄い。

@yuuk1tさんと登壇者の@dxhuyさんの以下のやりとりも非常に面白い。

LINE NEWSの記事配信を支える技術

LINE NEWSは2013年にローンチされたサービスであり、当初はネイティブアプリとしてリリースされていたが、2017年にLINEアプリに統合された。
ピーク時には秒間375Kのリクエストを受け付けるため、相当なトラフィックが発生していると思われるサービス。

アーキテクチャ

PerlJavaが併用されているらしく、Javaへ移行しつつあるそう。

Personalized Recomendation

LINE NEWSは各ユーザの特性に応じたニュースをお勧め記事として配信している。

機械学習によって作成されたお勧めニュースの配信をする場合と、人手によるお勧めニュースの配信をする場合の二通りがある。

機械学習によって作成される配信記事は、機械学習チームによって全ユーザ(1億人)毎に200記事を作成しファイル形式で提供され、1時間ごとに更新される。
人手による配信の場合、特定のクラスタごとに配信するニュースを決定する。

機械学習によるお勧めニュース配信においては、記事のリストを保持するストレージにRedisを利用している。 ニュース記事本体のデータはMySQLに保持しているが、キャッシュサーバとしてRedisを利用している。

人手による配信の場合、お勧め記事のリストのストレージには機械学習の場合と同様、 Redisを利用しているがニュース記事の本体のストレージにはCentral Dogmaを利用している。

Central Dogma

line.github.io

LINE社が開発しているOSSで、バージョン管理 + 設定ファイル管理&通知システムみたいなもの。
アプリケーションの設定ファイルを管理し、変更があった場合にはその設定を利用しているアプリケーションに通知を行い、アプリケーションの再起動をせずに設定を変更することができる。

Central Dogmaの利用

この仕組みを利用してニュース記事をCentral Dogmaに格納し、アプリケーションはCentral Dogmaから記事が更新されたことを受けアプリケーション内にキャッシュすることで、ストレージにアクセスすることなく記事を配信することが可能となる。

一時間ごとの更新頻度をリアルタイムに近づける試みなども行っており、課題に対して積極的にシステムを変更したり、改善したりしていたことが印象的でした。

気になる技術

  • Central Dogma

Kubernetesの利用・普及、その先は何か?

ゼットラボ株式会社の代表取締役である河宜成さんのセッション。

設立当初のミッションとして「イケてるモダンなインフラを構築する」ということもあり、DockerやKubernetesなどの技術がリリースされてから直ぐに取り組んできた。

Yahoo!社向けにKaaS(Kubernetes as a Service)を提供しており、Yahoo!社のエンジニアに対して積極的なサポートを行っていることもあり、2017年では5クラスタであったが2019年になると400クラスタまで増え、今後も増え続ける想定とのこと。

今後どんなことをやっていくかということを考えるためには、今何が起きているかを知る必要があると仰っていたことが非常に印象的でした。

気になる技術

今後の展望で述べられていた技術・用語。

  • NoOps
  • サーバレス
  • ゼロトラストネットワーク
  • ステートフルなアプリケーションをK8s上で実行する

Reliability Engineering Behind The Most Trusted Kafka Platform

LINE社のKafkaプラットフォームにおける信頼性エンジニアリングに関するセッションでした。

LINEにおけるKafka

LINE社ではKafkaをサービス間のPub/Subであったり、メッセージキューとして利用している。
以下の指標が指し示している通り、莫大なメッセージ・データ量を捌いていることがわかる。

  • Daily Inflow Messages
    • 360Billion
  • Daily In+Out Data
    • 550TB

SLO(Service Level Objective)

SLOとしては以下の通り。

莫大なメッセージを取り扱うプラットフォームにおいて、以下のSLOを達成することは非常にチャレンジングであると同時に卓越したエンジニアリングがなければ実現し得ないと思う。ただ単に凄い。

  • 可用性
    • 99.999%(年間で許容されるダウンタイムが約5.26分)
  • 応答性能
    • < 40ms(99%のメッセージ)

SLOを実現するためにとりくんでいること

SLOの可視化

SLOを可視化するために、SLI(Service Level Indicator)を定めている。
SLIはサービスの可用性・応答性能を数値として計測できなければならない。

  • API Response Time
    • レイテンシの測定(応答性能)
  • API Error Rate
    • 可用性の測定

たいていこれらのメトリクスはサーバサイドで取得されることが多いが、それだけでは不十分である。

SLIの精緻化

  • クライアントライブラリは信頼性向上の機能を備えているため、以下を考慮する必要がある。
    • リトライした場合
    • フェールオーバした場合
  • Kafkaにおけるメッセージ配信のレイテンシは以下を含む
    • メッセージリクエストのレスポンスタイム
    • リクエスト時のフェールオーバ・リトライ・メタデータの更新に要した時間
    • メッセージを利用する側のリクエストタイム
    • メッセージを利用する側のcoordinationに要した時間(ちょっとここが理解できないけど、分散システムならではの調整時間が要するのだと理解)

Kafkaやライブラリの仕組みを理解したうえで、SLIを精緻化する必要がある。
こういった仕組みを理解し、SLIを詳細に定めたうえで、測定可能なクライアントライブラリを開発し、SLIのダッシュボードを作成している。

Troubleshooting

トラブルシューティングに関しては根本的な原因を究明し、解決することを信条としている。
原因の究明・解決の過程で身につくスキルは、他の同様の障害に応用可能であるし、深い知見を身に着けることができるからとのこと。

障害解析の具体的な例も説明されていたけど、ここでは割愛するけど、JVMシステムコールファイルシステムブロックストレージデバイスまで降りていって障害解析する過程は非常に興味深かった。

SREとしての矜持といったものを感じられて非常に刺激を受けたセッションでした。

【読書メモ】食べる!SSL!

SSL/TLS周りのことをちゃんと理解したくて、積読してあった「食べる!SSL! ―HTTPS環境構築から始めるSSL入門」を読んだ。 セキュリティの考え方や、SSL/TLSの全体像を把握するには非常に良い入門書だったと思う。

以下メモ書き。

セキュリティの考え方に共通する3つの要素

  1. 機密性(Confidentiality)
     情報が意図した相手以外に漏れていないこと
  2. 完全性(Integrity)
     情報が誰にも改ざんされていないこと
  3. 可用性(Availability)
     使用可能であると想定されている状況において使用したいときに使用できること

セキュリティの脅威モデル

情報を何から守るべきか、攻撃者がどのような攻撃を仕掛けてくるかを理解しやすいようにモデル化する考え方。 各脅威の頭文字をとった "STRIDE" という脅威モデルがある。

  1. なりすまし(Spoofing)
  2. データの改ざん(Tempering)
  3. 否認(Repudiation)
  4. 情報漏洩(Information Disclosure)
  5. サービス不能(Denial of Service)
  6. 権限の昇格(Elevation of Privilege)

セキュアな通信を実現するために必要なこと

  1. 「盗聴」されてもデータを第三者に読めないようにする
  2. 「改ざん」されても検知できるようにする
  3. 「なりすまし」されても気づけるようにする
  4. 「否認」できないように、本人しか送付できない情報形式にする

各脅威への対応

  • 「盗聴」への対策
    共通鍵暗号化方式・公開鍵暗号化方式による暗号化により、情報を盗み見られても解読できないようにする。
  • 「改ざん」への対策
    メッセージ認証符号 MAC(Message Authentification Code)の利用し、情報が改ざんされていないか検証を行う。
  • 「なりすまし」や「否認」への対策
    秘密鍵を利用したデジタル署名によって「本人」を特定する。
    サーバ証明書は証明書内に含まれる公開鍵が被証明者のものであることを証明するものである。 この証明にはドメイン証明・法的な実在証明・物理的な実在証明というように証明の信頼度合いが異なる証明方法がある。

SSL/TLSによって保護されているとは

クライアントとサーバ間の通信が暗号化されており、相手のサーバが認証されていて、通信内容が改ざんされた際に、その内容が改ざんされた内容だと受け手が気づくことができるということ。

通信経路上の情報を安全に相手方のサーバへと送信することを目的としており、実際に相手方のアプリケーションが本当に「信頼できる」のか、サーバ側に到達し復号化された情報の安全性などは、SSL/TLSでは保護されない。

SSL/TLSの通信フロー

大きく分けて2段階のフローとなっている。
1. ハンドシェイクフェーズ
2. データ転送フェーズ

ハンドシェイクフェーズ

公開鍵暗号化方式を利用して実際の情報をやりとりするまでの準備を整えるフェーズ。

ハンドシェイクフェーズの目的としては以下の3つ。
1. 暗号化アルゴリズムの合意
2. 認証
3. 暗号化に利用する「鍵の確立」

以下のアルゴリズムについてクライアント側とサーバ側で合意をとる。

  1. SSL/TLSのバージョン
  2. サーバー認証アルゴリズム
  3. 鍵交換アルゴリズム
  4. データ転送で使用するデータ保護用の共通鍵暗号方式アルゴリズム
  5. データ転送で使用するデータの完全性を確認するためのMACアルゴリズム
  6. 圧縮アルゴリズム

アルゴリズムの合意形成後にクライアント側はサーバ側から送られてきたサーバ証明書の検証を行う。
信頼に足る証明書の場合にデータ転送時に利用する共通鍵・MAC鍵を生成し、クライアント・サーバの両方で生成した鍵の妥当性を検証しハンドシェイクフェーズを終了する。

SSL/TLSを構成するコンポーネント

  1. 証明書
  2. 公開鍵・秘密鍵
  3. 暗号化アルゴリズム
  4. SSL/TLSライブラリ

以上、ざっくりとしたメモ書きなので、個々の詳細に別途書くかも。

食べる!SSL! ―HTTPS環境構築から始めるSSL入門

食べる!SSL! ―HTTPS環境構築から始めるSSL入門

振る舞いから見る Docker プライベートレジストリ のイメージ削除について

オンプレミス上で Docker の プライベートレジストリ を運用している際に、不要な Docker イメージが蓄積されディスクスペースをひっ迫することが目に見えたので、どのように削除するのかを検証してみた。

今回は内部実装の面からではなく、ツールを利用してのイメージ削除後、レジストリ の garbage-collect コマンドを利用した際にイメージを格納しているディレクトリにどのような変化が生じるのかという面から記述していく。

記述中の詳細には深く言及しないので、別の記事で再度まとめたい。

検証環境について

自宅の Ubuntu サーバ上に以下のビルド手順を参考に実行バイナリを生成し、環境構築を実施。
Docker イメージを利用しても良かったのだけど、後々ソースコードを弄りたいと思ったときに面倒だなと思ったのでソースコードからビルドする。

distribution/BUILDING.md at master · docker/distribution · GitHub

初期のディレクトリ構造

バックエンドのストレージにローカルファイルシステムを選んだ場合、設定ファイルにイメージを格納するディレクトリを指定することができる。

指定しなければデフォルトは、/var/lib/registry 領域に格納される。

レジストリの詳しい設定は以下の公式ドキュメントに記載されている。

docs.docker.com

nginx:1.17.3 のイメージを Docker Hub から取得後、ローカルにイメージをプッシュすると以下のディレクトリとファイルが生成される。

annkara@annkara:~/registry/docker/registry$ tree -L 10
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       │   └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
    │       │       └── data
    │       ├── 55
    │       │   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
    │       │       └── data
    │       ├── a6
    │       │   └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
    │       │       └── data
    │       ├── ab
    │       │   └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
    │       │       └── data
    │       └── b8
    │           └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
    │               └── data
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │           └── link
            │   └── tags
            │       └── 1.17.3
            │           ├── current
            │           │   └── link
            │           └── index
            │               └── sha256
            │                   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │                       └── link
            └── _uploads

v2 ディレクトリ配下に大きく二つのディレクトリが生成される。

イメージの追加

先ほどプッシュした同一のイメージID で別のタグ名を持つ nginx:1.17.13_2 をプッシュし、ディレクトリ構造にどう影響を与えるか見てみる。

annkara@annkara:~/registry/docker/registry$ tree -L 10
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       │   └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
    │       │       └── data
    │       ├── 55
    │       │   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
    │       │       └── data
    │       ├── a6
    │       │   └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
    │       │       └── data
    │       ├── ab
    │       │   └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
    │       │       └── data
    │       └── b8
    │           └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
    │               └── data
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │           └── link
            │   └── tags
            │       ├── 1.17.3
            │       │   ├── current
            │       │   │   └── link
            │       │   └── index
            │       │       └── sha256
            │       │           └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │       │               └── link
            │       └── 1.17.3_2
            │           ├── current
            │           │   └── link
            │           └── index
            │               └── sha256
            │                   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │                       └── link
            └── _uploads

repositories/nginx/_manifests/tags 配下に 1.17.3_2 のディレクトリ・ファイルが生成されたほかは何も変化がないように見られる。

また、同一のイメージを別のタグ名でプッシュしたせいか、index 配下の sha256 のハッシュ値も 1.17.3 のタグと同一の値となっている。

nginx/1.17.3_2 のマニフェストを削除する

プライベートレジストリからイメージを削除するといった場合、2つの解釈が生じうる。

一つ目はソフト削除といって、指定されたイメージ:タグまたはダイジェストのマニフェストを削除するというもの。
この削除ではストレージ上から実際のデータを削除までは実行しないが、メタ情報が存在しないので docker image pull コマンドでイメージを取得することができない。

二つ目はストレージから不要なイメージの実データを削除するというもの。
ストレージ上からデータを削除するには、後述する プライベートレジストリに実装されている garbage-collect サブコマンドを実行する必要がある。

ここでは一つ目のマニフェストを削除することで、ディレクトにどのように影響を与えるか見てみる。

Docker のレジストリDocker Registry HTTP API V2 を通じて処理をリクエストするが、curl コマンド等を利用するのは面倒なのでgenuinetools/regを利用して、マニフェストを削除する。

github.com docs.docker.com

# reg を利用して 1.17.3_2 を削除
annkara@annkara:~/registry/docker/registry$ reg rm -k 192.168.1.209:5000/nginx:1.17.3_2
INFO[0000] domain: 192.168.1.209:5000
INFO[0000] server address: 192.168.1.209:5000
Deleted 192.168.1.209:5000/nginx:1.17.3_2@sha256:55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20

削除後のディレクトリは以下の通り。

annkara@annkara:~/registry/docker/registry$ tree -L 10
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       │   └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
    │       │       └── data
    │       ├── 55
    │       │   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
    │       │       └── data
    │       ├── a6
    │       │   └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
    │       │       └── data
    │       ├── ab
    │       │   └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
    │       │       └── data
    │       └── b8
    │           └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
    │               └── data
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   └── tags
            └── _uploads

tags 配下の1.17.31.17.3_2ディレクトリの両方が削除されてしまったため、docker image pull コマンドでイメージを取得できない。

annkara@annkara:~/registry/docker/registry$ docker image pull 192.168.1.209:5000/nginx:1.17.3
Error response from daemon: manifest for 192.168.1.209:5000/nginx:1.17.3 not found
annkara@annkara:~/registry/docker/registry$ docker image pull 192.168.1.209:5000/nginx:1.17.3_2
Error response from daemon: manifest for 192.168.1.209:5000/nginx:1.17.3_2 not found

この振る舞いから、同一リポジトリ名で別のタグを指定したとしても、同一のイメージIDに基いたイメージ情報は削除されうる。
しかし、別のリポジトリ名でそれらが同一のイメージIDに基づいていた場合、指定されたイメージの情報のみが削除される。

先ほどのreg rm コマンドは内部では以下の API リクエストを発行している。

DELETE /v2/<name>/manifests/<reference>

つまり、<reference> の値が同一であろうと、<name> の部分が異なれば指定されたもの以外は削除されないということ。

同一イメージID で別のリポジトリを削除した場合

上記で述べた場合を検証してみる。
192.168.1.209:5000/nginx/test:1.17.3192.168.1.209:5000/nginx:1.17.3 のイメージをプッシュし、192.168.1.209:5000/nginx:1.17.3 を削除した場合にどうなるかを見てみる。

annkara@annkara:~/registry/docker/registry$ docker image ls
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
192.168.1.209:5000/nginx/test        1.17.3              ab56bba91343        10 days ago         126MB
192.168.1.209:5000/nginx             1.17.3              ab56bba91343        10 days ago         126MB

2つのイメージをプッシュした際のディレクトリは以下の通り、repositories 配下のディレクトリ構成が異なっている。

annkara@annkara:~/registry/docker/registry$ tree -L 11
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       │   └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
    │       │       └── data
    │       ├── 55
    │       │   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
    │       │       └── data
    │       ├── a6
    │       │   └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
    │       │       └── data
    │       ├── ab
    │       │   └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
    │       │       └── data
    │       └── b8
    │           └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
    │               └── data
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │           └── link
            │   └── tags
            │       └── 1.17.3
            │           ├── current
            │           │   └── link
            │           └── index
            │               └── sha256
            │                   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │                       └── link
            ├── test
            │   ├── _layers
            │   │   └── sha256
            │   │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │   │       │   └── link
            │   │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │   │       │   └── link
            │   │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │   │       │   └── link
            │   │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │   │           └── link
            │   ├── _manifests
            │   │   ├── revisions
            │   │   │   └── sha256
            │   │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │   │           └── link
            │   │   └── tags
            │   │       └── 1.17.3
            │   │           ├── current
            │   │           │   └── link
            │   │           └── index
            │   │               └── sha256
            │   │                   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │                       └── link
            │   └── _uploads
            └── _uploads

ここで、reg を利用して、nginx:1.17.3 のマニフェストを削除する。

annkara@annkara:~/registry/docker/registry$ tree -L 11
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       │   └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
    │       │       └── data
    │       ├── 55
    │       │   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
    │       │       └── data
    │       ├── a6
    │       │   └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
    │       │       └── data
    │       ├── ab
    │       │   └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
    │       │       └── data
    │       └── b8
    │           └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
    │               └── data
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   └── tags
            ├── test
            │   ├── _layers
            │   │   └── sha256
            │   │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │   │       │   └── link
            │   │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │   │       │   └── link
            │   │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │   │       │   └── link
            │   │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │   │           └── link
            │   ├── _manifests
            │   │   ├── revisions
            │   │   │   └── sha256
            │   │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │   │           └── link
            │   │   └── tags
            │   │       └── 1.17.3
            │   │           ├── current
            │   │           │   └── link
            │   │           └── index
            │   │               └── sha256
            │   │                   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │                       └── link
            │   └── _uploads
            └── _uploads

改めてディレクトリ構成をみるとtest/nginx:1.17.3ディレクトリは削除されていないため、リポジトリ名が別の場合には削除されないことがわかる。

garbage-collect の実行

今まではマニフェストの削除のみを扱ってきたが、ストレージ上からの削除を実行してみる。
ストレージ上から実データを削除するには以下のように、garbage-collect というサブコマンドを実行する。

#!/bin/sh

annkara@annkara:~/bin$ export REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/home/annkara/registry
annkara@annkara:~/bin$ export REGISTRY_STORAGE_DELETE_ENABLED=True
annkara@annkara:~/bin$ /home/annkara/go/bin/registry garbage-collect /home/annkara/go/src/github.com/docker/distribution/cmd/registry/config-example.yml
nginx
nginx/test
nginx/test: marking manifest sha256:55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
nginx/test: marking blob sha256:ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
nginx/test: marking blob sha256:b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
nginx/test: marking blob sha256:a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
nginx/test: marking blob sha256:22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d

5 blobs marked, 0 blobs and 0 manifests eligible for deletion

上記の実行後のディレクトリの状態は以下の通り。

annkara@annkara:~/registry/docker/registry$ tree -L 11
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       │   └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
    │       │       └── data
    │       ├── 55
    │       │   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
    │       │       └── data
    │       ├── a6
    │       │   └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
    │       │       └── data
    │       ├── ab
    │       │   └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
    │       │       └── data
    │       └── b8
    │           └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
    │               └── data
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   └── tags
            ├── test
            │   ├── _layers
            │   │   └── sha256
            │   │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │   │       │   └── link
            │   │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │   │       │   └── link
            │   │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │   │       │   └── link
            │   │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │   │           └── link
            │   ├── _manifests
            │   │   ├── revisions
            │   │   │   └── sha256
            │   │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │   │           └── link
            │   │   └── tags
            │   │       └── 1.17.3
            │   │           ├── current
            │   │           │   └── link
            │   │           └── index
            │   │               └── sha256
            │   │                   └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │                       └── link
            │   └── _uploads
            └── _uploads

test/nginx:1.17.3 が存在するため、実データは削除されずまだ存在している。
次に、test/nginx:1.17.3 を削除し、gabage-collect を実行する。

annkara@annkara:~/bin$ /home/annkara/go/bin/registry garbage-collect /home/annkara/go/src/github.com/docker/distribution/cmd/registry/config-example.yml
nginx
nginx/test

0 blobs marked, 5 blobs and 0 manifests eligible for deletion
blob eligible for deletion: sha256:22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/22/22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d  go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry
blob eligible for deletion: sha256:55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/55/55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20  go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry
blob eligible for deletion: sha256:a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a6/a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053  go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry
blob eligible for deletion: sha256:ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/ab/ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3  go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry
blob eligible for deletion: sha256:b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/b8/b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d  go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry

実行後のディレクトリの状態。
blobs 配下のディレクトリは残っているものの、実データが削除されていることがわかる。

annkara@annkara:~/registry/docker/registry$ tree -L 11
.
└── v2
    ├── blobs
    │   └── sha256
    │       ├── 22
    │       ├── 55
    │       ├── a6
    │       ├── ab
    │       └── b8
    └── repositories
        └── nginx
            ├── _layers
            │   └── sha256
            │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │       │   └── link
            │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │       │   └── link
            │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │       │   └── link
            │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │           └── link
            ├── _manifests
            │   ├── revisions
            │   │   └── sha256
            │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   └── tags
            ├── test
            │   ├── _layers
            │   │   └── sha256
            │   │       ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d
            │   │       │   └── link
            │   │       ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053
            │   │       │   └── link
            │   │       ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3
            │   │       │   └── link
            │   │       └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
            │   │           └── link
            │   ├── _manifests
            │   │   ├── revisions
            │   │   │   └── sha256
            │   │   │       └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
            │   │   └── tags
            │   └── _uploads
            └── _uploads

まとめ

  • イメージの実データを削除するには、マニフェストを削除してから garbage-collect を実行する
  • 同一リポジトリで別タグであったとしても、同一イメージIDの場合にはマニフェストは削除されてしまう
  • リポジトリ名が別名であれば、同一イメージIDの場合でも両方とも削除されることはない
  • プライベートレジストリのクライアントライブラリ・CLIツールが少ない
    heroku/docker-registry-clientがあったけど、今はメンテナンスされていなさそう。
  • 実装にふみこんで、ハッシュ値など詳細についてまとめていきたい