Skopeo: ‘Pull’不要でレジストリ間を高速にDockerイメージをコピーする方法

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

まずは試してみましょう

3GBのイメージをローカルにプルして、タグを付け直して、別のレジストリにプッシュするためだけに15分も待たされ、イライラしたことはありませんか?もしそうなら、Skopeoこそがあなたの救世主です。

Ubuntu/DebianへのSkopeoのインストールは数秒で完了します:

sudo apt-get update
sudo apt-get install -y skopeo

例えば、nginx:latestイメージをDocker Hub from プライベートレジストリに移行したいけれど、ローカルマシンにはダウンロードしたくない場合、次のコマンドを使用します:

skopeo copy \
    docker://docker.io/library/nginx:latest \
    docker://registry.mycompany.com/production/nginx:latest

この時、SkopeoはAPIを通じて2つのレジストリ間でデータを直接調整する「仲介者」の役割を果たします。Docker Engineのインストールもsudo権限も不要で、何より重要なのはマシンのディスク容量を全く消費しないことです。

なぜPull -> Tag -> Pushのワークフローを捨てるべきなのか?

従来の方法は、DevOpsエンジニアにとって非常にストレスの溜まる3つの問題を引き起こします:

  • 帯域幅の浪費: 2GBのデータをダウンロードして別のサーバーにアップロードし直すのは、リソースの膨大な無駄遣いです。ネットワークが遅い場合、数個のイメージをコピーするだけで午前中が潰れてしまいます。
  • ディスク容量の圧迫: Dockerの中間レイヤーは通常、多くの容量を占有します。ディスク容量が20GB程度に制限されているCI/CDランナーでは、重いイメージをプルすると即座にパイプラインがクラッシュしてしまいます。
  • Dockerデーモンへの依存: すべての環境にDockerがインストールされているわけではありません。Kubernetesのような現代的なシステムでは、Docker-inside-Dockerを実行することはセキュリティ上のリスクを伴うことが多いです。

Skopeoはこれらの問題を根本的に解決します。HTTP APIを介してレジストリと直接通信し、マシンに何も解凍することなくマニフェストやレイヤーを操作します。

最も実用的な機能

1. Inspect:1秒でイメージの内容を確認する

ダウンロードする前に、そのイメージがarm64またはamd64をサポートしているか知りたいですか?プルしてから確認する代わりに、inspectコマンドを使いましょう:

skopeo inspect docker://docker.io/library/ubuntu:22.04

返される結果は、タグ、レイヤー、アーキテクチャに関する詳細なJSONデータです。ちょっとしたヒント: ターミナル上のJSON結果は読みにくいことが多いです。私はいつも内容をコピーして、toolcraft.app/ja/tools/developer/json-formatterのJSONフォーマッターに貼り付けています。この方法なら、拡張機能をインストールする手間をかけずに、イメージの構造をはるかに素早く把握できます。

2. Copy:イメージを自由自在に移動させる

このコマンドを使用すると、さまざまなフォーマット間でイメージを柔軟に移動できます:

  • docker://:標準的なレジストリ間での転送。
  • oci://:Open Container Initiative (OCI)フォーマットの使用。
  • dir://:イメージをディレクトリに保存(バックアップに最適)。

例えば、インターネットに接続されていないサーバー(エアギャップ環境)にイメージをバックアップするには、ディレクトリに保存するだけです:

skopeo copy docker://alpine:latest dir:/home/dev/backup-alpine

3. Delete:リモートレジストリをクリーンアップする

Docker CLIは本来、レジストリ上のイメージを直接削除することを許可していません。Skopeoを使用すれば、管理者権限がある場合、古いビルドのクリーンアップが非常に簡単になります:

skopeo delete docker://registry.mycompany.com/old-app:v1

認証 and プライベートレジストリの処理

AWS ECRやGitLabのようにパスワードが必要なシステムを扱う場合、ログイン情報を直接渡すことができます:

skopeo copy \
    --src-creds user_nguon:pass_nguon \
    --dest-creds user_dich:pass_dich \
    docker://docker.io/myrepo/private-image:latest \
    docker://quay.io/another-repo/image:latest

すでにdocker loginを行っている場合、Skopeoは自動的に~/.docker/config.jsonファイルを探してトークンを取得します。パスワードを再度入力する必要はありません。

‘sync’コマンドによる一括同期

あるプロジェクトの50個のタグをDocker HubからGoogle Cloudに移行しなければならない場面を想像してみてください。手動で50回コマンドを打つ代わりに、sync.yamlファイルを作成するだけで済みます:

'docker.io/itfromzero':
    images:
        nginx: ['1.21', '1.22', 'latest']
        redis: ['6.2', '7.0']

その後、syncコマンド skopeo sync --src yaml --dest docker sync.yaml gcr.io/my-project を実行します。わずか数分で、イメージリポジトリ全体が新しい場所に「複製」されます。

導入における実戦経験

内部レジストリ使用時のSSLエラーの処理

正式なSSL証明書がないセルフホスト(self-hosted)レジストリを使用している場合、Skopeoは証明書エラーを報告します。心配はいりません。--dest-tls-verify=falseフラグを追加して、セキュリティチェックをスキップするだけで解決します。

CI/CDパイプラインの最適化

JenkinsやGitLab Runnerでは、私は常にDockerよりもSkopeoを優先して使用しています。これにより、実行後のランナー仮想マシンを完全にクリーンに保つことができます。長期間蓄積されたイメージのゴミによる「No space left on device(ディスク容量不足)」エラーでパイプラインが停止することに悩まされることはもうありません。

結論として、頻繁にイメージを管理したり、クラウドプロバイダー間を移行したりする場合、Skopeoは欠かせないツールです。軽量で高速であり、ワークフローをよりプロフェッショナルなものにしてくれます。

Share: