20200115のdockerに関する記事は12件です。

Azure 上の Minecraft マルチサーバを IFTTT でいい感じに起動・終了制御する

GnhyNVj.png

はじめに

Azure の仮想マシンを使って、 Minecraft (Spigot) マルチサーバを立ち上げて運用しています。

参加メンバーは全員会社勤めなので、平日の日中はサーバを停止して、「平日の夜・土日の終日」の間だけ自動でサーバが立ち上がるようにしています。

今回は、サーバの開始・起動スケジュールを IFTTT の DateTime トリガーと連動して行うために、 Azure Automation を使い、更に仮想マシンの起動・終了に連動した Minecraft サーバを構築しました。

また、サーバの起動や終了は最終的に Discord に通知ようにしています。

この記事では、以下の手順で解説しています(基礎知識的な部分は省略しています)。

  • 仮想マシンの構築
    • VM の起動と終了に連動した Minecraft サーバを構築します
  • Azure Automation で Webhook を作成する
    • VM の起動と終了を行い、Discord に Webhook で通知する Runbook を構築します
  • IFTTT で Webhook のトリガーを作成する

仮想マシンの構築

今回作成した VM は以下のようなスペックでした。

  • SKU: Standard D2s v3 (2 vcpu 数、8 GiB メモリ)
  • Region: 東日本
  • Image: Ubuntu Server 18.04 LTS

D2s v3 で ¥9,166/月 ですが、平日は 6h 程しか稼働しないため、大体 300h/月 となり、現在はこの半額程度で運用しています(価格だけで見たらやっぱりちょっと高い気もする)。

Spigot サーバの構築

今回は Docker を使って構築しました。
nimmis/docker-spigot を Clone して docker-compose.yml の値を変更するだけで終わりです。

VM上にCloneする
$ sudo mkdir -p /minecraft
$ sudo chown -R mcserver:mcserver /minecraft
$ git clone --depth=1 https://github.com/nimmis/docker-spigot /minecraft
docker-compose.yml
version: "2"
services:
  spigot-main:
    container_name: "spigot-main"
    build: "."
    ports:
      - 80:8123
      - 25565:25565
    environment:
      - MC_MAXMEM=8g
      - MC_MINMEM=1g
      - SPIGOT_AUTORESTART=yes
      - SPIGOT_VER=1.14.4
      - SPIGOT_UID=1000
    volumes:
      - "./server:/minecraft"
    restart: "always"

これで docker-compose up すれば spigot.jar のビルドが走り、以降はサーバが自動で立ち上がるようになっています。

終了時スクリプト

仮想マシンが停止しようとする時に、Minecraft サーバのワールドデータを /save-all した上で終了する必要がありますが、今回利用したイメージは、コンテナが Stop する際にそのあたりを自動でやってくれています。

なので終了時スクリプトを書いてシャットダウン時にコンテナを停止するようにします。

終了時スクリプトの作成

$ sudo vim       /etc/init.d/stop-mcserver.sh
$ sudo chmod a+x /etc/init.d/stop-mcserver.sh 
$ sudo ln -s     /etc/init.d/stop-mcserver.sh /etc/rc6.d/K99stop-mcserver
/etc/init.d/stop-mcserver.sh
#!/bin/bash

cd /minecraft

/usr/local/bin/docker-compose stop

また、 restart: "always" なので次回起動時に自動的にコンテナが立ち上がって Minecraft サーバが復帰するため、これで自動起動・終了の仕組みが完成します!!!

しなかった

原因が未だに分からないんですが、Azure の仮想マシンが再起動した後に何故かコンテナが自動で立ち上がりません。

ですが、SSH して docker ps などを叩くと 微妙なラグの後にコンテナが起動 したため、おそらく Docker daemon のプロセスが正しく起動していないのではと考えられます。

起動時スクリプト

なので、起動時に Docker API を叩く無害なコマンドを実行させることで無理やり Docker daemon を起動させています。

これで、仮想マシンが再起動した後もコンテナが自動で立ち上がるようになりました。

起動時スクリプト

$ crontab -e

crontab の中身:

# m h  dom mon dow   command
@reboot /usr/bin/docker --version > dev/null 2>&1

Azure Automation で仮想マシンを起動・終了させる

Azure Automation の Runbook でこれらの内容を実装します。

  • サーバを起動させる
  • サーバを停止させる
  • 起動・停止したら Discord の Webhook で通知する
  • Automation 開始トリガーを Incoming Webhook にする

サーバを起動・停止させる

これは、 Runbook ギャラリーの人気上位にある 2つのスクリプトをインポートすれば終わりです。

KENh7Yw.png

ですが、インポートしてきた Runbook は Azure の仕様変更に合わせて更新されておらず、正しく起動・停止できたのにも関わらず Automation ジョブが Error で終わるようになっています。

NZjTQR0.png

原因は Notify VM Started/Stopped ノードの実行条件式が古いためで、これを現在の ActivityOutput のプロパティに合わせることで解決します(あと Notify Failed To Start/Stop ノードあたりのエラー内容の取得方法も古かったため直しました)。

Discord の Webhook で通知する

※ Webhook は作成済みです

以下のような感じでそれぞれの出力メッセージを IDictionary -> JSON に変換して、その内容を Webhook で Discord に通知しています。

RbvYPhT.png

Format message

Write-Output ノードを使い、Discord の Webhook の仕様に合わせてコンテンツを作成。

PowerShell式
@{
  content = $_
}

ConvertTo-Json

Format message からアクティビティの出力を受け取る

Notify to webhook

Invoke-WebRequest ノードを使い、ConvertTo-Json のアクティビティの出力を POST で送信。
Content-Type に application/json; charset=utf-8 を指定しないと日本語が文字化けする。
あと UseBasicParsing フラグも True にしないとジョブが正しく終わらなかった(はず)。

開始トリガーの Incoming-Webhook を作成する

それぞれの Runbook で Webhook を作成して動くかどうか確認する。
LvlPIZ2.png

$ curl -X POST -H "Content-Type: application/json" https://WEBHOOK

このように通知されて仮想マシンが起動・終了すれば OK(Runbook 上のメッセージを日本語に変えています)。
pI3rVqX.png

それぞれの Webhook URL を控えておきます。

IFTTT のトリガーを作成する

IFTTT の DateTime トリガーから Every day of the week at を選択します。

スクリーンショット 2020-01-15 15.49.56.png

曜日と時間が選択出来るので、例えば 平日の19時に実行するようなトリガー を作成します。
スクリーンショット 2020-01-15 15.51.05.png

次に実行するアクションで Webhook を選択し、先程の Webhook URL を設定します。
スクリーンショット 2020-01-15 15.52.39.png

これを複数個作成し、1週間分の起動・停止スケジュールを作成すれば完成です。
GnhyNVj.png

ちなみに

Azure Automation 自体にもスケジュール実行機能が備わっていますが、正直使い勝手が良くないのとスマートフォン上から編集しづらいので IFTTT 経由でスケジュールを編集出来る方がより簡単です。

完全に蛇足ですが仮に祝日判定などの機能追加をする場合も、Runbook 上で構築するよりも Discord の Bot を別途ホストして独自でスケジューリングを実装するのが良いと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure 上の Minecraft マルチサーバを IFTTT でいい感じに制御して節約する

GnhyNVj.png

はじめに

Azure の仮想マシンを使って、 Minecraft (Spigot) マルチサーバを立ち上げて運用しています。

参加メンバーは全員会社勤めなので、平日の日中はサーバを停止して、「平日の夜・土日の終日」の間だけ自動でサーバが立ち上がるようにしています。

今回は、サーバの開始・起動スケジュールを IFTTT の DateTime トリガーと連動するため Azure Automation を使い、更に 仮想マシンの起動と終了に連動する Minecraft サーバ を構築しました。

最終的にはサーバの起動通知を Discord に送るようにしてメンバーが確認できるようにしています。

この記事では、以下の手順で解説しています(基礎知識的な部分は省略しています)。

  • 仮想マシンの構築
    • VM の起動と終了に連動した Minecraft サーバを構築します
  • Azure Automation で Webhook を作成する
    • VM の起動と終了を行い、Discord に Webhook で通知する Runbook を構築します
  • IFTTT で Webhook のトリガーを作成する

仮想マシンの構築

今回作成した VM は以下のようなスペックでした。

  • SKU: Standard D2s v3 (2 vcpu 数、8 GiB メモリ)
  • Region: 東日本
  • Image: Ubuntu Server 18.04 LTS

D2s v3 で ¥9,166/月 ですが、平日は 6h 程しか稼働しないため大体 300h/月 となり、月額のおよそ 1/2 程度で運用しています(価格だけ見たらやっぱりちょっと高い気もする)。

Spigot サーバの構築

今回は Docker を使って構築しました。
nimmis/docker-spigot を Clone して docker-compose.yml の値を変更するだけで終わりです。

VM上にCloneする
$ sudo mkdir -p /minecraft
$ sudo chown -R mcserver:mcserver /minecraft
$ git clone --depth=1 https://github.com/nimmis/docker-spigot /minecraft
docker-compose.yml
version: "2"
services:
  spigot-main:
    container_name: "spigot-main"
    build: "."
    ports:
      - 80:8123
      - 25565:25565
    environment:
      - MC_MAXMEM=8g
      - MC_MINMEM=1g
      - SPIGOT_AUTORESTART=yes
      - SPIGOT_VER=1.14.4
      - SPIGOT_UID=1000
    volumes:
      - "./server:/minecraft"
    restart: "always"

これで docker-compose up すれば spigot.jar のビルドが走り、以降はサーバが自動で立ち上がるようになっています。

終了時スクリプト

仮想マシンが停止しようとする時に、Minecraft サーバのワールドデータを /save-all した上で終了する必要がありますが、今回利用したイメージは、コンテナが Stop する際にそのあたりを自動でやってくれています。

なので終了時スクリプトを書いてシャットダウン時にコンテナを停止するようにします。

終了時スクリプトの作成

$ sudo vim       /etc/init.d/stop-mcserver.sh
$ sudo chmod a+x /etc/init.d/stop-mcserver.sh 
$ sudo ln -s     /etc/init.d/stop-mcserver.sh /etc/rc6.d/K99stop-mcserver
/etc/init.d/stop-mcserver.sh
#!/bin/bash

cd /minecraft

/usr/local/bin/docker-compose stop

また、 restart: "always" なので次回起動時に自動的にコンテナが立ち上がって Minecraft サーバが復帰するため、これで自動起動・終了の仕組みが完成します!!!

しなかった

原因が未だに分からないんですが、Azure の仮想マシンが再起動した後に何故かコンテナが自動で立ち上がりません。

ですが、SSH して docker ps などを叩くと 微妙なラグの後にコンテナが起動 したため、おそらく Docker daemon のプロセスが正しく起動していないのではと考えられます。

起動時スクリプト

なので、起動時に Docker API を叩く無害なコマンドを実行させることで無理やり Docker daemon を起動させています。

これで、仮想マシンが再起動した後もコンテナが自動で立ち上がるようになりました。

起動時スクリプト

$ crontab -e

crontab の中身:

# m h  dom mon dow   command
@reboot /usr/bin/docker --version > dev/null 2>&1

Azure Automation で仮想マシンを起動・終了させる

Azure Automation の Runbook でこれらの内容を実装します。

  • サーバを起動させる
  • サーバを停止させる
  • 起動・停止したら Discord の Webhook で通知する
  • Automation 開始トリガーを Incoming Webhook にする

サーバを起動・停止させる

これは、 Runbook ギャラリーの人気上位にある 2つのスクリプトをインポートすれば終わりです。

KENh7Yw.png

ですが、インポートしてきた Runbook は Azure の仕様変更に合わせて更新されておらず、正しく起動・停止できたのにも関わらず Automation ジョブが Error で終わるようになっています。

NZjTQR0.png

原因は Notify VM Started/Stopped ノードの実行条件式が古いためで、これを現在の ActivityOutput のプロパティに合わせることで解決します(あと Notify Failed To Start/Stop ノードあたりのエラー内容の取得方法も古かったため直しました)。

Discord の Webhook で通知する

※ Webhook は作成済みです

以下のような感じでそれぞれの出力メッセージを IDictionary -> JSON に変換して、その内容を Webhook で Discord に通知しています。

RbvYPhT.png

Format message

Write-Output ノードを使い、Discord の Webhook の仕様に合わせてコンテンツを作成。

PowerShell式
@{
  content = $_
}

ConvertTo-Json

Format message からアクティビティの出力を受け取る

Notify to webhook

Invoke-WebRequest ノードを使い、ConvertTo-Json のアクティビティの出力を POST で送信。
Content-Type に application/json; charset=utf-8 を指定しないと日本語が文字化けする。
あと UseBasicParsing フラグも True にしないとジョブが正しく終わらなかった(はず)。

開始トリガーの Incoming-Webhook を作成する

それぞれの Runbook で Webhook を作成して動くかどうか確認する。
LvlPIZ2.png

$ curl -X POST -H "Content-Type: application/json" https://WEBHOOK

このように通知されて仮想マシンが起動・終了すれば OK(Runbook 上のメッセージを日本語に変えています)。
pI3rVqX.png

それぞれの Webhook URL を控えておきます。

IFTTT のトリガーを作成する

IFTTT の DateTime トリガーから Every day of the week at を選択します。

スクリーンショット 2020-01-15 15.49.56.png

曜日と時間が選択出来るので、例えば 平日の19時に実行するようなトリガー を作成します。
スクリーンショット 2020-01-15 15.51.05.png

次に実行するアクションで Webhook を選択し、先程の Webhook URL を設定します。
スクリーンショット 2020-01-15 15.52.39.png

これを複数個作成し、1週間分の起動・停止スケジュールを作成すれば完成です。
GnhyNVj.png

ちなみに

Azure Automation 自体にもスケジュール実行機能が備わっていますが、正直使い勝手が良くないのと スマートフォン上から編集しづらいので IFTTT 経由でスケジュールを編集出来る方がより簡単です。

完全に蛇足ですが仮に祝日判定などの機能追加をする場合も、Runbook 上で構築するよりも Discord の Bot を別途ホストして独自でスケジューリングを実装するのが良いと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

とりあえずのDockerfileを作成したい。

応用範囲が広いDockerfileのテンプレートを書いた。

僕はArchliluxが好きだ。つまりpacmanとaurが好きだ。archwikiとpkgbuildが好きだ。
それをそのままDockerに応用したい。そしてserverでもそのまま使いたいし、開発にも応用したい。

FROM archlinux/base
ARG PKG="yay"
RUN curl https://www.archlinux.org/mirrorlist/\?country\=JP\&protocol\=https\&ip_version\=4\&ip_version\=6 > /tmp/mirrorlist && sed -e "s/^#//g" /tmp/mirrorlist > /etc/pacman.d/mirrorlist && yes "" | pacman -Syy git base-devel
RUN useradd -m -s /bin/bash docker
RUN echo 'Defaults visiblepw'            >> /etc/sudoers
RUN echo 'docker ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

USER docker
WORKDIR /home/docker

##RUN sudo pacman -S $PKG
RUN git clone https://aur.archlinux.org/$PKG.git && cd $PKG && yes "" | makepkg -si && rm -r ~/$PKG

ENTRYPOINT ["bash", "-c", "echo editThisCommand."]

使い方

2行目を編集するだけ!AURじゃない場合普通にpacmanでインストールできます。コメントアウト等は適当に。
ARG PKG="samba"と書けばファイルサーバーになるし、ARG PKG="dnsmasq"と書けばDNSサーバーになります。

例えば

FROM archlinux/base
ARG PKG="samba"
RUN curl https://www.archlinux.org/mirrorlist/\?country\=JP\&protocol\=https\&ip_version\=4\&ip_version\=6 > /tmp/mirrorlist && sed -e "s/^#//g" /tmp/mirrorlist > /etc/pacman.d/mirrorlist && yes "" | pacman -Syy git base-devel
RUN useradd -m -s /bin/bash docker
RUN echo 'Defaults visiblepw'            >> /etc/sudoers
RUN echo 'docker ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

#USER docker
#WORKDIR /home/docker

RUN pacman -S $PKG
##RUN git clone https://aur.archlinux.org/$PKG.git && cd $PKG && yes "" | makepkg -si && rm -r ~/$PKG

##https://wiki.archlinux.jp/index.php/Samba を参考に
RUN  curl "https://git.samba.org/samba.git/?p=samba.git;a=blob_plain;f=examples/smb.conf.default;hb=HEAD" > /etc/samba/smb.conf
RUN  yes "password" | pdbedit -a docker -t
RUN chmod 0777 /home/docker
ENTRYPOINT [ "bash", "-c", "nmbd -D && smbd -F </dev/null" ] ]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerの中にPostgres+Sequelize+Express+Next.JSの構築

はじめに

この記事は、Dockerの中のExpressにSequelizeを使ってPostgresを接続する記事である。
調べても、記事ごとに構築の仕方の差が激しかったので、自分にとってやりやすいやり方を編み出し、まとめる。

注意

これはメモ
基本的な解説はしない。DBとExpressのコネクションについてがメイン
Dockerについて全く理解していないので、ディレクトリ構造やDockerfileの書き方がよくないかもしれない。

環境

  • Docker
  • Node.js
  • Express
  • PostgreSQL
  • Next.js(APIでやり取りするのでサーバー立てて終わり)

ディレクトリ構造

product-docker-express-Dockerfile//マウント用
              -next-Dockerfile//マウント用
       -express //expressを直接インストール
       -next //Nextを直接インストール
       -docker-compose

product/expressにsequelizeをインストール

npm install --save sequelize pg sequelize-cli

Docker-composeでの設定

docker-compose
version: '3'
services:

  backend:
    build:
      context: ./docker/express
      dockerfile: Dockerfile
    image: back
    container_name: back
    ports:
      - 3000:3000
    environment:
      DATABASE_URL: postgres://postgres:postgres@db:5432/postgres 
    volumes:
      - ./express:/src
    command: [sh, -c, npm install && npm start]

  frontend:
    build: 
      context: ./docker/next 
      dockerfile: Dockerfile
    image: front
    container_name: front
    ports:
      - 3001:3000
    volumes: 
      - ./next:/src
    command: [sh, -c, npm install && npm run dev]

  db:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - "5432:5432"

ここで重要なのは、DATABASE_URLである。
のちに、sequelizeのconfig.jsonにて環境変数として使用するため設定している。
postgres://postgres:postgres@db:5432/postgres
このURLは、
postgres://username:password@host:port/dbname
となっており、docker-composeで設定した通りに当てはめていく。
dbnameは、postgres-Docker Hubによると、POSTGRES_DBの記述がなければ、POSTGRES_USERの値が代わりに使用される。

Sequelize

cliをインストールしたことによって、RailsのActiveRecordのように、modelやmigrationを生成することができる。

$ sequelize init
//modelやmigration、configなどのフォルダーを生成。

やりたいひとはやろうなテスト

$ docker-compose up -d
$ docker-compose run backend npx sequelize model:create --name Test //モデルとマイグレーションファイルを生成
$ docker-compose run backend npx sequelize db:migrate --env development 

まだ、エラーがでるはず...

config/config.jsonの設定

 "development": {
    "dialect": "postgres",
    "use_env_variable":"DATABASE_URL"
  }

dialectはDBの種類
use_env_variableは環境変数を参照する。つまり、dockercomposeで設定したURLが参照されている。

そして記事内の「やりたいひとはやろうなテスト」を行うと...
スクリーンショット 2020-01-15 14.19.22.png
マイグレーションが反映される。

まとめ

なにが正解かわからないが、他の記事などを見るとSQLスクリプトを書いていたり、自分でmodelを書いていたりしていたので調べるのが大変だった。
一番最初の環境構築でつまづいた初心者がまとめたものなので参考にならないかも。
なにかあれば...twitter@izszzz_

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

作業環境を改善(10年計画)

docker(19) 言語処理100本ノックをdockerで。python覚えるのに最適。
https://qiita.com/kaizen_nagoya/items/7e7eb7c543e0c18438c4

作業で、PC(mac OS)3台使い、ディスプレイ3台で作業した状況を、研究環境だけではなく、量産の開発・運用へ展開するための方策を検討する。

PC 3台

Windows, Linux, macOSの3つのOSを1台づつを想定。

github/gitlab/bitbacket利用

顧客指向の土台
https://qiita.com/kaizen_nagoya/items/3ff2b93acef88e17fce8

docker, docker hub(privateを含む)利用

docker(0) 資料集
https://qiita.com/kaizen_nagoya/items/45699eefd62677f69c1d

vs code 利用

UML利用

xtUMLを導入する(linux編)
https://qiita.com/kaizen_nagoya/items/297097cc47a6487d9f20

空間

廊下、会議室、研修室、倉庫など、電源さえあればどこでも暮らせる。

keyboard

Note PCのキーボードは、Typewriterを叩いていた身としては深さが足りない。
指が疲れてきてしまう。

mouse

Note PCのパッドは、まだ慣れない。
iPad, android PADなども利用したことがあり、体がまだ馴染んでいない。
tablet用のpenは、それなりに利用経験があり、まだ馴染む。

無線

通信が専門で媒体は無線のはず。資料がまだ道半ば。

無線網(Wi-Fi)空中線(antenna)(0) 記事一覧(118/300目標)
https://qiita.com/kaizen_nagoya/items/5e5464ac2b24bd4cd001

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerイメージを格納するため、HelmでHarborをデプロイしてみた

はじめに

これまでDockerHubの有料プランを利用してきましたが、さすがに開発用のイメージまで置く余裕はないので、Harborをデプロイして試すことにしました。今回はHelmを利用しています。

環境

  • Harbor-Helmを利用してk8s環境にデプロイ
  • ユーザー認証はLDAPを利用
  • HarborへのアクセスにはLoadBalancerを利用
  • Rook/Cephを利用しているためBlock Storageの利用にStorageClassの指定が必要
  • Private LAN内部では、利用している192.168.x.xのIPについて、DNSのホスト名⇔IPの解決が可能 (dnsmasqを利用)

今回はIntranetからアクセスできるようReverse-Proxy サーバーとしてnginxを経由してHarborにアクセスするケースと、外部からアクセスできないようPrivate LAN内からのみアクセスできるよう設定する2つのケースを利用しました。

ケース1 - NginxをFrontend Reverse-Proxy Serverとして利用する

このケースでは、docker login/push を実行する時に通信に、正規のTLS証明書を利用する点が特徴になります。自己証明TLS鍵を利用するのであれば、Private Network内で利用する方法と同じです。ただ第三者が接続できる可能性があるので、adminパスワードの管理には注意が必要です。

ケース2 - Private Netowrk内でのみ利用する

このケースでは、KubernetesとHarborを同一の独自ネットワークに構築します。dockerコマンドからHarborに接続するためTLS証明書について、独自CAが発行する自己認証鍵になる点が特徴的です。そのためCA鍵をdocker(サーバーの場合)やシステム(クライアントの場合)に登録する必要があります。

TLS鍵の準備には次の2つのシナリオがあります。

  1. TLS鍵はharborに自動生成させることができ、生成されたCA局の証明書をdockerに登録します
  2. Private LAN内部で利用するDomain用にeasy-rsa3を利用してCA局を構築する場合は、easy-rsa3が作成するCA局の証明書をdockerに登録します

導入までの流れ

kubectlコマンドが実行できる場所でgit clone

基本的なセットアップ
$ git clone https://github.com/goharbor/harbor-helm.git
$ cd harbor-helm
## git tag で最新版を確認し、checkoutします。
$ git checkout refs/tags/v1.3.0 -b my_v1.3.0

繰り返し作業をいろいろするので、作業用にMakefileを準備しておきます。

git-cloneを実行したディレクトリがCWD
$ cd ..   ## from harbor-helm
$ cat > Makefile
Makefile
NAMESPACE = harbor
HELM_RELEASE = my-harbor

.PHONY: init install delete delete-ns check create-tls-secret

init:
        kubectl create ns $(NAMESPACE)

install:
        (cd harbor-helm; helm install --name $(HELM_RELEASE) --namespace $(NAMESPACE) .)

delete:
        (cd harbor-helm; helm delete --purge $(HELM_RELEASE))

delete-ns:
        kubectl delete ns $(NAMESPACE)

check:
        helm list

create-tls-secret:
        kubectl -n $(NAMESPACE) create secret generic nginx-tls-keys --from-file pki/ca.crt --from-file pki/tls.crt --from-file pki/tls.key

この部分をCopy&Pasteするとインデントはスペース8個になってしまいますが、タブ文字である点に注意してください。

TLS鍵の配置

values.yamlのsecretName:を空にしたままにすると、TLS鍵が自動的に生成され、secret/helm_release-namespace-nginxに設定されます。今回はca.crt, tls.crt, tls.keyファイルをpki/ディレクトリに準備し、secret/nginx-tls-keysに格納します。

$ make init
$ mkdir pki
$ cp .../ca.crt .../harbor.example.com.crt .../harbor.example.com.key pki/
$ openssl rsa -in pki/harbor.example.com.key -out pki/harbor.example.com.nopass.key
$ ln -s harbor.example.com.crt pki/tls.crt
$ ln -s harbor.example.com.nopass.key pki/tls.key
$ make create-tls-secret

values.yamlの編集

git cloneしているので、git diffの結果を添付します。これはProxy(proxy.example.com)を経由せずに、直接Private LAN内部でアクセスする場合のものです。

Proxy Serverを経由する場合には、externalURL:に外部に公開するProxy ServerのURLを指定します。commonNameにはPrivate LAN内部でDNS名前解決できるホスト名を指定しています。

harbor-helm/values.yaml
diff --git a/values.yaml b/values.yaml
index 474ffdb..74f9fa5 100644
--- a/values.yaml
+++ b/values.yaml
@@ -2,7 +2,7 @@ expose:
   # Set the way how to expose the service. Set the type as "ingress",
   # "clusterIP", "nodePort" or "loadBalancer" and fill the information
   # in the corresponding section
-  type: ingress
+  type: loadBalancer
   tls:
     # Enable the tls or not. Note: if the type is "ingress" and the tls
     # is disabled, the port must be included in the command when pull/push
@@ -16,14 +16,14 @@ expose:
     # "ca.crt" - the certificate of CA (optional), this enables the download
     # link on portal to download the certificate of CA
     # These files will be generated automatically if the "secretName" is not set
-    secretName: ""
+    secretName: "nginx-tls-keys"
     # By default, the Notary service will use the same cert and key as
     # described above. Fill the name of secret if you want to use a
     # separated one. Only needed when the type is "ingress".
     notarySecretName: ""
     # The common name used to generate the certificate, it's necessary
     # when the type isn't "ingress" and "secretName" is null
-    commonName: ""
+    commonName: "harbor.example.com"
   ingress:
     hosts:
       core: core.harbor.domain
@@ -73,7 +73,7 @@ expose:
     # The name of LoadBalancer service
     name: harbor
     # Set the IP if the LoadBalancer supports assigning IP
-    IP: ""
+    IP: "192.168.1.43"
     ports:
       # The service port Harbor listens on when serving with HTTP
       httpPort: 80
@@ -98,7 +98,7 @@ expose:
 # the IP address of k8s node
 #
 # If Harbor is deployed behind the proxy, set it as the URL of proxy
-externalURL: https://core.harbor.domain
+externalURL: https://harbor.example.com

 # The persistence is enabled by default and a default StorageClass
 # is needed in the k8s cluster to provision volumes dynamicly.
@@ -120,19 +120,19 @@ persistence:
       # Specify the "storageClass" used to provision the volume. Or the default
       # StorageClass will be used(the default).
       # Set it to "-" to disable dynamic provisioning
-      storageClass: ""
+      storageClass: "rook-ceph-block"
       subPath: ""
       accessMode: ReadWriteOnce
-      size: 5Gi
+      size: 20Gi
     chartmuseum:
       existingClaim: ""
-      storageClass: ""
+      storageClass: "rook-ceph-block"
       subPath: ""
       accessMode: ReadWriteOnce
       size: 5Gi
     jobservice:
       existingClaim: ""
-      storageClass: ""
+      storageClass: "rook-ceph-block"
       subPath: ""
       accessMode: ReadWriteOnce
       size: 1Gi
@@ -140,7 +140,7 @@ persistence:
     # be ignored
     database:
       existingClaim: ""
-      storageClass: ""
+      storageClass: "rook-ceph-block"
       subPath: ""
       accessMode: ReadWriteOnce
       size: 1Gi
@@ -148,7 +148,7 @@ persistence:
     # be ignored
     redis:
       existingClaim: ""
-      storageClass: ""
+      storageClass: "rook-ceph-block"
       subPath: ""
       accessMode: ReadWriteOnce
       size: 1Gi

Harborのデプロイなどの一連の作業

Makefileを配置したディレクトリは次のようになっています。

$ ls -l
total 32
-rw-rw-r-- 1 yasu yasu   219 Jan  9 12:33 Makefile
drwxrwxr-x 8 yasu yasu  4096 Jan  9 14:10 harbor-helm

namespaceは既に存在する(make initした)ものとして、helm installを実行します。

$ make install
$ make check
NAME            REVISION        UPDATED                         STATUS          CHART           APP VERSION  NAMESPACE
my-harbor       1               Thu Jan  9 21:37:55 2020        DEPLOYED        harbor-1.3.0    1.10.0       harbor 

もしharborを削除したい場合には、make delete, make delete-nsを実行します。delete-nsを実行しない場合には、PVCはnamespace内に残ります。

削除する場合
$ make delete
$ make check
## my-harborが削除されていれば、delete-nsを実行
$ make delete-ns

正常に稼動すればWeb UIなどでログインすることができるようになります。Namespaceのsecretにca.crt,tls.crt,tls.keyを登録済みであれば不要ですが、secretName:を空("")にしてhelmが自動生成する証明書を利用する場合には、ca.crtファイルを抽出して、docker push, kubectl を実行するホスト上に登録する必要があります。

TLS接続時の検証エラーの回避

docker・kubectlコマンドから直接、Harborに接続する場合には、https://docs.docker.com/registry/insecure/ に記述があるように、自己署名CAをそのコマンドを実行するマシンの /etc/docker/certs.d/hostname/ca.crt に配置する方法がお勧めです。

WebブラウザからHarborのWeb UIにアクセスする場合には、そのシステム(Ubuntuであればca-certificatesの管理下)に自己署名CAを登録する方法がお勧めです。

自分が管理していない自己署名CAをシステムに登録する方法はお勧めしませんが、TLS鍵の検証を無視する設定は安直ですができるだけ避けるべきだと思います。自分の管理下にある自己署名CAを登録する方が、対象を限定できるので、お勧めです。

実際に鍵を配布する方法には、ansibleを利用して、全マシンに配布しています。

自己署名CAの抽出

kubectlが実行できるマシンでsecretに登録されているca.tlsの内容を取得します。1行で実行すると次のようになりますが、単純に$ kubectl get secret my-harbor-harbor-nginx -o yamlの出力からca.crt部分をコピーして、base64 -dの入力に与える方法もあります。

$ kubectl get secret my-harbor-harbor-nginx -o jsonpath='{.data.ca\.crt}' | base64 -d
-----BEGIN CERTIFICATE-----
.....
-----END CERTIFICATE-----

ここで画面に出力された内容を、ca.crtとして保存し、docker pushを実行するホスト、kubernetesの各ノードに登録(/etc/docker/certs.d/harbor.example.com/ca.crtへの配置)をします。

Harborの稼動確認

ca.crtの内容がシステムに登録された後は、Web UIからログインします。

$ firefox https://harbor.example.com/

自己署名CAを利用している場合には警告がでますが、Acceptして次に進みます。

  • ID: admin
  • Password: Harbor12345

パスワードはログインした後の左上にあるAdminユーザーのメニューから、必ず変更するようにしましょう。LDAPを利用したいので、Configurationに進んで情報を登録しますが、今回は省略します。

Projects "library" へのユーザーの登録

LDAPとの接続ができるようになったところで、自分のIDをProjects"libarary"のMembersタブに進み、"+ USER"ボタンからMasterとして登録しています。

libraryプロジェクトに一般ユーザーを登録したところで、イメージを登録します。

Dockerでのイメージの作成と登録

ネーミングルールは、ホスト名/プロジェクト名/image[:TAG] となっているので、docker buildする場合には適切なtagをつけるか、手元でのテストでも利用すると思うので、次のような方法で、既存のイメージにHarbor登録用の名称を設定するという事になると思います。

実行例
$ docker login harbor.example.com
Username: user01
Password:

$ docker pull nginx:latest
$ docker tag nginx:latest harbor.example.com/library/mynginx:1.0
$ docker push harbor.example.com/library/mynginx:1.0
The push refers to repository [harbor.example.com/library/mynginx]
918efb8f161b: Pushed 
27dd43ea46a8: Pushed 
9f3bfcc4a1a8: Pushed 
2dc9f76fb25b: Pushed 
1.0: digest: sha256:2695d3e10e69cc500a16eae6d6629c803c43ab075fa5ce60813a0fc49c47e859 size: 1152

独自にProjectを登録している場合には、"library"の部分を適宜変更します。

最後にWeb UIから自分のIDでログインし、イメージが登録されていることを確認しておきます。

Kubernetesでのデプロイメントのテスト

次の2つのYAMLファイルを準備します。

deploy-mynginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      imagePullSecrets:
      - name: selfreg
      containers:
      - name: nginx
        image: harbor.example.com/library/mynginx:1.0
        ports:
        - containerPort: 80
svc-mynginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  type: LoadBalancer
  ports:
     -  port: 80
        protocol: TCP
        targetPort: 80
  selector:
    app: nginx

deploymentの中で参照(.spec.template.spec.imagePullSecrets.name)している、selfregを作成します。

LDAPに登録しているパスワードを$regpasswd変数に格納
$ read -s regpasswd 
## 入力しているパスワードは非表示な点に注意
$ kubectl -n default create secret docker-registry selfreg --docker-username=user01 --docker-email=user01@example.com --docker-password="${regpasswd}"

これで作成した2つのYAMLファイルを登録します。

$ kubectl -n default apply -f deploy-mynginx.yaml
$ kubectl -n default apply -f svc-mynginx.yaml

## 状況の確認
$ kubectl -n default get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-55d5f94b5-nbw4v   1/1     Running   0          43m
pod/nginx-deployment-55d5f94b5-wkwb4   1/1     Running   0          43m


NAME                 TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)        AGE
service/kubernetes   ClusterIP      10.233.0.1    <none>         443/TCP        75d
service/nginx        LoadBalancer   10.233.7.30   192.168.1.24   80:30243/TCP   59m


NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           59m

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-55d5f94b5   2         2         2       43m

正常にCAファイルが登録されていない場合には、次のようにエラーになります。

LDAP設定時に注意する点

HarborのLDAP設定は複雑なことができないようになっていて柔軟性には欠けますが、反面、設定自体に困る事はあまりないと思います。

ただ、LDAPサーバーのURLを指定する部分では、次のように設定するとエラーになります。

エラーとなるURL指定
ldaps://ldap.example.com:636

末尾の :636 の部分は間違いではないはずですが、エラーとなるため ldaps://ldap.example.com のように指定する必要がありました。

Kubernetesにca.crtが登録されていない場合のエラー

ファイルが正常に配置されていれば再起動は不要ですが、内容が正しくない場合には、次ようなエラーとなります。

$ kubectl -n default describe pod -l app=nginx
...
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  51s                default-scheduler  Successfully assigned default/nginx-deployment-55d5f94b5-km9ms to ibox01a2
  Normal   BackOff    18s (x2 over 43s)  kubelet, ibox01a2  Back-off pulling image "harbor.example.com/library/mynginx:1.0"
  Warning  Failed     18s (x2 over 43s)  kubelet, ibox01a2  Error: ImagePullBackOff
  Normal   Pulling    4s (x3 over 49s)   kubelet, ibox01a2  Pulling image "harbor.example.com/library/mynginx:1.0"
  Warning  Failed     4s (x3 over 44s)   kubelet, ibox01a2  Failed to pull image "harbor.example.com/library/mynginx:1.0": rpc error: code = Unknown desc = Error response from daemon: Get https://harbor.example.com/v2/: x509: certificate signed by unknown authority
  Warning  Failed     4s (x3 over 44s)   kubelet, ibox01a2  Error: ErrImagePull

およそ、ここまでで一般的なユースケースは満たせるのかなと思います。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでローカルのLambda実行環境を用意する。

はじめに

ファイルの中身のみ記載します。

ディレクトリ構造

.
├── docker-compose.yml
├── lambda
    ├── sample
        └── index.js

docker-compose.ymlの内容

version: '3'

services:
  addData:
    container_name: sample-lambda
    image: lambci/lambda:nodejs12.x
    volumes:
      - ./lambda/sample:/var/task
    ports:
      - 9001:9001
    environment:
      AWS_DEFAULT_REGION: XXXXXXXX
      AWS_ACCOUNT_ID: YYYYYYYY
      DOCKER_LAMBDA_WATCH: 1
      DOCKER_LAMBDA_STAY_OPEN: 1
    command: index.handler

index.jsの内容

const aws = require("aws-sdk");

exports.handler = async (event, context) => {
    context.succeed({
        statusCode: 200,
        body      : JSON.stringify('hallo sample!'),
    });
};

いざ実行!

dockerの起動

docker-compose up

レスポンス確認

別タブで実行

curl -d '{}' http://localhost:9001/2015-03-31/functions/sample/invocations

レスポンス

{"statusCode":200,"body":"\"hallo sample!\""}

終わりに

デプロイなんかもDocker使ってできるみたいですね。
時間があれば、そちらも記載したいと思います:relaxed:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Harborのコンパイルとデバッグ

はじめに

HarborをHelmから導入した際に不可解な挙動をしたので、git cloneしたコードをビルドしてみることにしました。その際のメモを残しておきます。

コンパイル & 再コンパイルのプロセス

初期のコンパイルは、公式のガイド https://github.com/goharbor/harbor/blob/master/docs/compile_guide.md に従って操作をします。

$ git clone https://github.com/goharbor/harbor.git
$ cd harbor
## git tag で最新版を確認し、checkoutする
$ git checkout refs/tags/v1.10.0 -b my_v1.10.0
## あらかじめTLS鍵ファイルを任意の場所に準備しておき、make/harbor.ymlに記述する
## 今回は、pki/ディレクトリを作成し、配置しておきます
$ mkdir pki
$ cp ..../pki/issued/harbor.example.com.crt pki/
$ cp ..../pki/private/harbor.example.com.key pki/
## keyファイルのパスワードを解除します
$ openssl rsa -in pki/harbor.example.com.key -out pki/harbor.example.com.nopass.key
$ vi make/harbor.yml

make/harbor.ymlファイルの差分は次のようになっています。

make/harbor.yml
diff --git a/make/harbor.yml b/make/harbor.yml
index 4589c352b..83a9ec31d 100644
--- a/make/harbor.yml
+++ b/make/harbor.yml
@@ -2,7 +2,7 @@

 # The IP address or hostname to access admin UI and registry service.
 # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
-hostname: reg.mydomain.com
+hostname: harbor.example.com

 # http related config
 http:
@@ -14,22 +14,22 @@ https:
   # https port for harbor, default is 443
   port: 443
   # The path of cert and key files for nginx
-  certificate: /your/certificate/path
-  private_key: /your/private/key/path
+  certificate: ..../git/harbor/pki/harbor.example.com.crt
+  private_key: ..../git/harbor/pki/harbor.example.com.key

 # Uncomment external_url if you want to enable external proxy
 # And when it enabled the hostname will no longer used
@@ -24,12 +24,12 @@ https:
 # The initial password of Harbor admin
 # It only works in first time to install harbor
 # Remember Change the admin password from UI after launching Harbor.
-harbor_admin_password: Harbor12345
+harbor_admin_password: XXXXXXXXXXXXXX

 # Harbor DB configuration 
 database:
   # The password for the root user of Harbor DB. Change this before any production use.
-  password: root123
+  password: XXXXXXXXXXX
   # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
   max_idle_conns: 50
   # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.

ファイルを編集したところでコンパイルを実行しますが、先に挙げた問題を回避するためにsudo makeを利用しています。コンパイル方法の詳細については、https://github.com/goharbor/harbor/blob/master/docs/compile_guide.md を参照してください。

コンパイルの実行
$ sudo docker pull golang:1.13.4
$ sudo make install GOBUILDIMAGE=golang:1.13.4 COMPILETAG=compile_golangimage

この操作をした後では、make/harbor.ymlファイルでDBやadminのパスワードを変更し、make cleanall; make install ... を再度実行しても反映されません。

再コンパイル手順

git cloneしたharborディレクトリに移動した後で、作業を行ないます。

$ sudo make down
$ sudo make cleanall
## 以下の作業は必要に応じて実施
$ sudo docker system prune -a  ## Dockerイメージを登録し直したい場合
$ sudo mv /data /data.old      ## DBのパスワード・データなどを初期化・削除した場合

ここまでしたら再度make installを実行します。

$ sudo make install GOBUILDIMAGE=golang:1.13.4 COMPILETAG=compile_golangimage

Easy-RSAによる鍵ファイルの準備

Easy-RSA3を利用して、独自プライベートネットワーク用ドメイン(example.com)用のCA局を構築しておきます。

easy-rsa-v3によるCA局の準備
$ git clone https://github.com/OpenVPN/easy-rsa.git
$ cd easy-rsa
$ git checkout refs/tags/v3.0.6 -b my_v3.0.6
$ cd ..
$ easy-rsa/easyrsa3/easyrsa init-pki
$ easy-rsa/easyrsa3/easyrsa build-ca
## Passphraseには出来るだけ長い文字列を指定、CN(Common Name)には対象となるドメインが分かる名称を指定する - e.g. "EXAMPLE.COM Easy-RSA CA"
$ ls 
easy-rsa/  pki/

easy-rsa/README.quickstart.md を確認すると、reqファイルは別のマシンで作成するように書かれています。これはkeyファイルとcrtファイルを同一のeas-rsa/ディレクトリ配下に収めてしまう事での情報漏洩を懸念していると思われます。利用する状況に応じて適切にファイルを分離するようにしてください。ここでは禁忌とされている同一マシン上でのgen-req, sign-req clientを実施しています。

また build-server-full, build-client-full オプションの指定があります。今回はそれでもほぼ同じ結果になりますが、柔軟にファイル名と、Common Name(CN)を分離したファイルを作成するためには、gen-req, sign-reqを順番に呼び出す方法を覚えておいた方が便利だと思うので、ここではその方法を記述しています。

"harbor.localdomain"に対応するTLS鍵を生成
## easy-rsa/, pki/ が存在するディレクトリで作業を実施
$ easy-rsa/easyrsa3/easyrsa gen-req harbor.example.com
...
Keypair and certificate request completed. Your files are:
req: .../pki/reqs/harbor.example.com.req
key: .../pki/private/harbor.example.com.key

$ easy-rsa/easyrsa3/easyrsa sign-req client harbor.example.com
$ find pki -type f | grep harbor.example.com
pki/reqs/harbor.example.com.req
pki/issued/harbor.example.com.crt
pki/private/harbor.example.com.key

"harbor.example.com"の部分はプライベートネットワーク内部で名前解決できるホスト名を指定します。準備したcrtファイルとkeyファイルをmake/harbor.ymlに指定します。pki/ca.crtファイルは利用するシステムが認識できるように登録しておきます。

Ubuntu 18.04上での自己証明TLSファイルの登録について

作業やFirefoxなどのWeb UIへのアクセスをするUbuntu 18.04ホスト上ではシステムにCAファイルを登録します。ca-certificatesパッケージが導入されている場合には、次の方法が基本的なフローになります。

  1. /usr/share/ca-certificates/ 以下に(通常はサブディレクトリを作成して)任意の名前(通常は"harbor.example.com.crt"のように、FQDN+".crt")でCAファイルを配置
  2. /etc/ca-certificates.conf に /usr/share/ca-certificates/ からの相対パスで、配置したCAファイルを登録
  3. $ sudo update-ca-certificates を実行

作業の結果は、/etc/ssl/certs/ ディレクトリに反映されますが、直接ここにファイルを配置する方法はお勧めしません。

実行例
$ sudo mkdir /usr/share/ca-certificates/local
$ sudo cp pki/ca.crt /usr/share/ca-certificates/local/harbor.example.com
$ sudo vi /etc/ca-certificates.conf
$ tail /etc/ca-certificates.conf
...
local/harbor.example.com.crt

$ sudo update-ca-certificates

firefoxが実行中であれば、再起動が必要です。

Kubernetes上へのCAファイルの配置

既に説明したように、/etc/docker/certs.d/以下に配置します。ansibleでは該当ディレクトリをあらかじめ作成する必要があるので、ちゃんとtasks/main.ymlなどにTASKを追加するか、$ ansible all -m command -b -a "mkdir -p /etc/docker/certs.d/_hostname__"のようにディレクトリを準備します。("hostname"の部分はdocker loginの引数に指定するホスト名に変更)

コンパイル時に遭遇した問題

  1. 一般ユーザーでmakeコマンドを実行すると、harbor/make/common/config/log/logrotate.conf の書き込み権限がないためmakeに失敗する (golangにDockerイメージを利用する際に作成されるファイルのUID,GIDが1000:1000となる。もしUID,GIDが一致していればこのエラーには遭遇しないかもしれません)
  2. TLS用のcert,keyファイルを準備・指定する必要がある
  3. make installによってdocker runまで実行されるため、(何も設定していなければ)root権限が必要になる

  4. についてはsudo makeで回避します。2.については今後のためにもプライベートネットワークで利用するCA局をeasy-rsaを利用して構築しておきます。

Helmでtls:falseの際に、遭遇した unknown blob エラー について

tls: falseのまま$ helm installした場合、TLSを有効にしたReverse-Proxyを配置することで、docker loginまでは成功します。しかし、私の環境ではdocker pushの最後にunknown blobと表示されて失敗するエラーに遭遇しました。フロントエンドでTLSを有効にしたReverse-Proxy Serverを設置して、HTTPでHarborに通信させようとすると、エラーが発生します。

nginxのノードはNAPT-gatewayとしても機能している
<------ global ip space --------><------------ private address space ---------->
  +----------+              +-------+                 +--------------+   +-----+
  | Intranet |---TLS(443)---| nginx |---non-TLS(80)---| LoadBalancer |---| Pod |
  +----------+    ↑         +-------+                 +--------------+   +-----+
                  ↑             ↑                     (※ tls: false)
                  ↑            (proxy_pass: http://kubeweb.example.com;)
                (https://harbor.example.com/)

この前段まででは、ここで不具合が発生しているのと、docker/kubernetesはregistryとの通信にTLSを前提としているので、原因が100%はっきりしているわけではないですが、前段まではtls: trueを前提とした構成を説明しています。

エラーが発生した状況
$ sudo docker login example.com
$ sudo docker build . --tag proxy.example.com/library/mynginx:1.0 --no-cache
$ sudo docker push example.com/library/mynginx:1.0
4fc1aa8003a3: Pushing  3.584kB
5fb987d2e54d: Preparing 
831c5620387f: Pushing  69.21MB/69.21MB
unknown blob

proxy.example.comは正式なTLS鍵を利用していて、通信自体は問題なく行なえています。しかし、この時のReverse-Proxy nginxのログを確認すると、次のようになっています。

エラーと関連するaccess_log
...
192.168.1.240 - - [09/Jan/2020:22:03:30 +0900] "HEAD /v2/library/mynginx/blobs/sha256:eb22865337de3edb54ec8b52f6c06de320f415e7ec43f01426fdafb8df6d6eb7 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))"
192.168.1.240 - - [09/Jan/2020:22:03:30 +0900] "HEAD /v2/library/mynginx/blobs/sha256:bee5d581ef8bfee2b5a54685813ba6ad9bbe922115d7aef84a21a9dbfcc2d979 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))"
...

この状態のregistry podの/storage以下は次のようになっていて、pushされたイメージがそのまま保存されたまま、処理されていない様子が分かります。

エラーが発生する場合_uploads/以下のみ存在
$ kc exec -it my-harbor-harbor-registry-79767646d6-rbv6j find /storage
...
/storage/docker/registry/v2/repositories/library/mynginx
/storage/docker/registry/v2/repositories/library/mynginx/_uploads
/storage/docker/registry/v2/repositories/library/mynginx/_uploads/bbe0e1fa-2d97-4b55-8d4d-a41ed2ca7c3a
/storage/docker/registry/v2/repositories/library/mynginx/_uploads/bbe0e1fa-2d97-4b55-8d4d-a41ed2ca7c3a/hashstates
...

正常に動作しているHarborでは、.../_uploads/ディレクトリは空になって,library以下にイメージのメタ情報、blobs以下にイメージファイルが展開されています。

正常に稼動している場合
$ kubectl exec -it my-harbor-harbor-registry-57dc985f45-mql55 find /storage
/storage/docker/registry/v2/repositories/library
/storage/docker/registry/v2/repositories/library/mynginx
/storage/docker/registry/v2/repositories/library/mynginx/_uploads
/storage/docker/registry/v2/repositories/library/mynginx/_layers
/storage/docker/registry/v2/repositories/library/mynginx/_manifests/tags/1.0/current/link
...
/storage/docker/registry/v2/blobs/sha256
/storage/docker/registry/v2/blobs/sha256/be
/storage/docker/registry/v2/blobs/sha256/be/bee5d581ef...
...

_uploads/に配置されたファイルを処理して、library/, blobs/に展開する処理をするコードを探してみます。

$ git clone https://github.com/goharbor/harbor.git
$ cd harbor
$ find . -type f -exec grep _uploads {} \; -print
## 結果が表示されなかった

registory上の/storageに存在するので、何かしらそこに配置された理由があるはずですが、harborのコード中には原因がなさそうです。コードを詳細に読む前に、再現させてnginxのログファイルをもう少し詳しくみていこうと思います。

docker-push時のreverse-proxyログの抜粋
92.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "GET /v2/ HTTP/1.1" 401 87 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - user01 [10/Jan/2020:15:01:36 +0900] "GET /service/token?account=user01&scope=repository%3Alibrary%2Fmynginx%3Apush%2Cpull&service=harbor-registry HTTP/1.1" 200 984 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "HEAD /v2/library/mynginx/blobs/sha256:8...d HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "HEAD /v2/library/mynginx/blobs/sha256:d...7 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "HEAD /v2/library/mynginx/blobs/sha256:b...6 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "POST /v2/library/mynginx/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "POST /v2/library/mynginx/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "POST /v2/library/mynginx/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "GET /v2/library/mynginx/blobs/uploads/8...d?_state=m...Q%3D%3D HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/8...d?_state=m...Q%3D%3D" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "GET /v2/library/mynginx/blobs/uploads/5...5?_state=-8...Q%3D%3D HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/5...5?_state=-8...Q%3D%3D" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "GET /v2/library/mynginx/blobs/uploads/9...c?_state=E...Q%3D%3D HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/9...c?_state=E...Q%3D%3D" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "GET /v2/library/mynginx/blobs/uploads/9...c?_state=o...9&digest=sha256%3A1...9 HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/9...c?_state=o...9&digest=sha256%3A1...9" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "GET /v2/library/mynginx/blobs/uploads/5...5?_state=W...6 HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/5...5?_state=W...6" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "GET /v2/library/mynginx/blobs/uploads/8...d?_state=...9&digest=sha256%3A7...0 HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/8...d?_state=i...9&digest=sha256%3A7...0" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "HEAD /v2/library/mynginx/blobs/sha256:7...0 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "HEAD /v2/library/mynginx/blobs/sha256:1...9 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "HEAD /v2/library/mynginx/blobs/sha256:b...6 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"

この時にregistory podの/storageは次のようになっていて、library/ubuntu/_uploads以外にはファイルが存在しない状態です。

$ /storage
/storage/docker
/storage/docker/registry
/storage/docker/registry/v2
/storage/docker/registry/v2/repositories
/storage/docker/registry/v2/repositories/library
/storage/docker/registry/v2/repositories/library/ubuntu
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/hashstates
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/hashstates/sha256
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/hashstates/sha256/0
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/data   
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/startedat
....

ひとまずHarborを自分でコンパイルしてみて、_uploadsに配置されたファイルがblobsに移動されるまでの処理のどこに問題があるのか調べていきます。issuesを眺める限りは再現性がなく、いつのまにか解決しているようです。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Harborのコンパイルとデバッグ with easy-rsa3

はじめに

HarborをHelmから導入した際に不可解な挙動をしたので、git cloneしたコードをビルドしてみることにしました。その際のメモを残しておきます。

コンパイル & 再コンパイルのプロセス

初期のコンパイルは、公式のガイド https://github.com/goharbor/harbor/blob/master/docs/compile_guide.md に従って操作をします。

$ git clone https://github.com/goharbor/harbor.git
$ cd harbor
## git tag で最新版を確認し、checkoutする
$ git checkout refs/tags/v1.10.0 -b my_v1.10.0
## あらかじめTLS鍵ファイルを任意の場所に準備しておき、make/harbor.ymlに記述する
## 今回は、pki/ディレクトリを作成し、配置しておきます
$ mkdir pki
$ cp ..../pki/issued/harbor.example.com.crt pki/
$ cp ..../pki/private/harbor.example.com.key pki/
## keyファイルのパスワードを解除します
$ openssl rsa -in pki/harbor.example.com.key -out pki/harbor.example.com.nopass.key
$ vi make/harbor.yml

make/harbor.ymlファイルの差分は次のようになっています。

make/harbor.yml
diff --git a/make/harbor.yml b/make/harbor.yml
index 4589c352b..83a9ec31d 100644
--- a/make/harbor.yml
+++ b/make/harbor.yml
@@ -2,7 +2,7 @@

 # The IP address or hostname to access admin UI and registry service.
 # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
-hostname: reg.mydomain.com
+hostname: harbor.example.com

 # http related config
 http:
@@ -14,22 +14,22 @@ https:
   # https port for harbor, default is 443
   port: 443
   # The path of cert and key files for nginx
-  certificate: /your/certificate/path
-  private_key: /your/private/key/path
+  certificate: ..../git/harbor/pki/harbor.example.com.crt
+  private_key: ..../git/harbor/pki/harbor.example.com.key

 # Uncomment external_url if you want to enable external proxy
 # And when it enabled the hostname will no longer used
@@ -24,12 +24,12 @@ https:
 # The initial password of Harbor admin
 # It only works in first time to install harbor
 # Remember Change the admin password from UI after launching Harbor.
-harbor_admin_password: Harbor12345
+harbor_admin_password: XXXXXXXXXXXXXX

 # Harbor DB configuration 
 database:
   # The password for the root user of Harbor DB. Change this before any production use.
-  password: root123
+  password: XXXXXXXXXXX
   # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
   max_idle_conns: 50
   # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.

ファイルを編集したところでコンパイルを実行しますが、先に挙げた問題を回避するためにsudo makeを利用しています。コンパイル方法の詳細については、https://github.com/goharbor/harbor/blob/master/docs/compile_guide.md を参照してください。

コンパイルの実行
$ sudo docker pull golang:1.13.4
$ sudo make install GOBUILDIMAGE=golang:1.13.4 COMPILETAG=compile_golangimage

この操作をした後では、make/harbor.ymlファイルでDBやadminのパスワードを変更し、make cleanall; make install ... を再度実行しても反映されません。

再コンパイル手順

git cloneしたharborディレクトリに移動した後で、作業を行ないます。

$ sudo make down
$ sudo make cleanall
## 以下の作業は必要に応じて実施
$ sudo docker system prune -a  ## Dockerイメージを登録し直したい場合
$ sudo mv /data /data.old      ## DBのパスワード・データなどを初期化・削除した場合

ここまでしたら再度make installを実行します。

$ sudo make install GOBUILDIMAGE=golang:1.13.4 COMPILETAG=compile_golangimage

Easy-RSAによる鍵ファイルの準備

Easy-RSA3を利用して、独自プライベートネットワーク用ドメイン(example.com)用のCA局を構築しておきます。

easy-rsa-v3によるCA局の準備
$ git clone https://github.com/OpenVPN/easy-rsa.git
$ cd easy-rsa
$ git checkout refs/tags/v3.0.6 -b my_v3.0.6
$ cd ..
$ easy-rsa/easyrsa3/easyrsa init-pki
$ easy-rsa/easyrsa3/easyrsa build-ca
## Passphraseには出来るだけ長い文字列を指定、CN(Common Name)には対象となるドメインが分かる名称を指定する - e.g. "EXAMPLE.COM Easy-RSA CA"
$ ls 
easy-rsa/  pki/

easy-rsa/README.quickstart.md を確認すると、reqファイルは別のマシンで作成するように書かれています。これはkeyファイルとcrtファイルを同一のeas-rsa/ディレクトリ配下に収めてしまう事での情報漏洩を懸念していると思われます。利用する状況に応じて適切にファイルを分離するようにしてください。ここでは禁忌とされている同一マシン上でのgen-req, sign-req clientを実施しています。

また build-server-full, build-client-full オプションの指定があります。今回はそれでもほぼ同じ結果になりますが、柔軟にファイル名と、Common Name(CN)を分離したファイルを作成するためには、gen-req, sign-reqを順番に呼び出す方法を覚えておいた方が便利だと思うので、ここではその方法を記述しています。

"harbor.localdomain"に対応するTLS鍵を生成
## easy-rsa/, pki/ が存在するディレクトリで作業を実施
$ easy-rsa/easyrsa3/easyrsa gen-req harbor.example.com
...
Keypair and certificate request completed. Your files are:
req: .../pki/reqs/harbor.example.com.req
key: .../pki/private/harbor.example.com.key

$ easy-rsa/easyrsa3/easyrsa sign-req client harbor.example.com
$ find pki -type f | grep harbor.example.com
pki/reqs/harbor.example.com.req
pki/issued/harbor.example.com.crt
pki/private/harbor.example.com.key

"harbor.example.com"の部分はプライベートネットワーク内部で名前解決できるホスト名を指定します。準備したcrtファイルとkeyファイルをmake/harbor.ymlに指定します。pki/ca.crtファイルは利用するシステムが認識できるように登録しておきます。

Ubuntu 18.04上での自己証明TLSファイルの登録について

Ubuntu 18.04ホスト上ではシステムにCAファイルを登録する場合について説明します。ca-certificatesパッケージが導入されている場合には、次の方法が基本的なフローになります。

  1. /usr/share/ca-certificates/ 以下に(通常はサブディレクトリを作成して)任意の名前(通常は"harbor.example.com.crt"のように、FQDN+".crt")でCAファイルを配置
  2. /etc/ca-certificates.conf に /usr/share/ca-certificates/ からの相対パスで、配置したCAファイルを登録
  3. $ sudo update-ca-certificates を実行

作業の結果は、/etc/ssl/certs/ ディレクトリに反映されますが、直接ここにファイルを配置する方法はお勧めしません。

実行例
$ sudo mkdir /usr/share/ca-certificates/local
$ sudo cp pki/ca.crt /usr/share/ca-certificates/local/harbor.example.com
$ sudo vi /etc/ca-certificates.conf
$ tail /etc/ca-certificates.conf
...
local/harbor.example.com.crt

$ sudo update-ca-certificates

Firefoxへの自己証明CA情報の登録

この記事、https://askubuntu.com/questions/244582/add-certificate-authorities-system-wide-on-firefox にあるように、firefoxでは自前のcertificate DBを利用するため、ca-certificatesが準備する /etc/ssl/cets/ ファイルは利用できません。そのため certutils を利用して、sqlite DBを更新する方法が紹介されていますが、2020年1月時点では、プロファイルをリセットしても空になっているなど、変更できない挙動のように感じられます。

Web-UIにアクセスする際には、Advanced... → Accept の流れで、一時的に接続を許可しています。

Kubernetes上へのCAファイルの配置

既に説明したように、/etc/docker/certs.d/以下に配置します。ansibleでは該当ディレクトリをあらかじめ作成する必要があるので、ちゃんとtasks/main.ymlなどにTASKを追加するか、$ ansible all -m command -b -a "mkdir -p /etc/docker/certs.d/_hostname__"のようにディレクトリを準備します。("hostname"の部分はdocker loginの引数に指定するホスト名に変更)

Harborのコンパイル時に遭遇した問題

  1. 一般ユーザーでmakeコマンドを実行すると、harbor/make/common/config/log/logrotate.conf の書き込み権限がないためmakeに失敗する (golangにDockerイメージを利用する際に作成されるファイルのUID,GIDが1000:1000となる。もしUID,GIDが一致していればこのエラーには遭遇しないかもしれません)
  2. TLS用のcert,keyファイルを準備・指定する必要がある
  3. make installによってdocker runまで実行されるため、(何も設定していなければ)root権限が必要になる

  4. についてはsudo makeで回避します。2.については今後のためにもプライベートネットワークで利用するCA局をeasy-rsaを利用して構築しておきます。

Helmでtls:falseの際に、遭遇した unknown blob エラー について

tls: falseのまま$ helm installした場合、TLSを有効にしたReverse-Proxyを配置することで、docker loginまでは成功します。しかし、私の環境ではdocker pushの最後にunknown blobと表示されて失敗するエラーに遭遇しました。フロントエンドでTLSを有効にしたReverse-Proxy Serverを設置して、HTTPでHarborに通信させようとすると、エラーが発生します。

nginxのノードはNAPT-gatewayとしても機能している
<------ global ip space --------><------------ private address space ---------->
  +----------+              +-------+                 +--------------+   +-----+
  | Intranet |---TLS(443)---| nginx |---non-TLS(80)---| LoadBalancer |---| Pod |
  +----------+    ↑         +-------+                 +--------------+   +-----+
                  ↑             ↑                     (※ tls: false)
                  ↑            (proxy_pass: http://kubeweb.example.com;)
                (https://harbor.example.com/)

この前段まででは、ここで不具合が発生しているのと、docker/kubernetesはregistryとの通信にTLSを前提としているので、原因が100%はっきりしているわけではないですが、前段まではtls: trueを前提とした構成を説明しています。

エラーが発生した状況
$ sudo docker login example.com
$ sudo docker build . --tag proxy.example.com/library/mynginx:1.0 --no-cache
$ sudo docker push example.com/library/mynginx:1.0
4fc1aa8003a3: Pushing  3.584kB
5fb987d2e54d: Preparing 
831c5620387f: Pushing  69.21MB/69.21MB
unknown blob

proxy.example.comは正式なTLS鍵を利用していて、通信自体は問題なく行なえています。しかし、この時のReverse-Proxy nginxのログを確認すると、次のようになっています。

エラーと関連するaccess_log
...
192.168.1.240 - - [09/Jan/2020:22:03:30 +0900] "HEAD /v2/library/mynginx/blobs/sha256:eb22865337de3edb54ec8b52f6c06de320f415e7ec43f01426fdafb8df6d6eb7 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))"
192.168.1.240 - - [09/Jan/2020:22:03:30 +0900] "HEAD /v2/library/mynginx/blobs/sha256:bee5d581ef8bfee2b5a54685813ba6ad9bbe922115d7aef84a21a9dbfcc2d979 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))"
...

この状態のregistry podの/storage以下は次のようになっていて、pushされたイメージがそのまま保存されたまま、処理されていない様子が分かります。

エラーが発生する場合_uploads/以下のみ存在
$ kc exec -it my-harbor-harbor-registry-79767646d6-rbv6j find /storage
...
/storage/docker/registry/v2/repositories/library/mynginx
/storage/docker/registry/v2/repositories/library/mynginx/_uploads
/storage/docker/registry/v2/repositories/library/mynginx/_uploads/bbe0e1fa-2d97-4b55-8d4d-a41ed2ca7c3a
/storage/docker/registry/v2/repositories/library/mynginx/_uploads/bbe0e1fa-2d97-4b55-8d4d-a41ed2ca7c3a/hashstates
...

正常に動作しているHarborでは、.../_uploads/ディレクトリは空になって,library以下にイメージのメタ情報、blobs以下にイメージファイルが展開されています。

正常に稼動している場合
$ kubectl exec -it my-harbor-harbor-registry-57dc985f45-mql55 find /storage
/storage/docker/registry/v2/repositories/library
/storage/docker/registry/v2/repositories/library/mynginx
/storage/docker/registry/v2/repositories/library/mynginx/_uploads
/storage/docker/registry/v2/repositories/library/mynginx/_layers
/storage/docker/registry/v2/repositories/library/mynginx/_manifests/tags/1.0/current/link
...
/storage/docker/registry/v2/blobs/sha256
/storage/docker/registry/v2/blobs/sha256/be
/storage/docker/registry/v2/blobs/sha256/be/bee5d581ef...
...

_uploads/に配置されたファイルを処理して、library/, blobs/に展開する処理をするコードを探してみます。

$ git clone https://github.com/goharbor/harbor.git
$ cd harbor
$ find . -type f -exec grep _uploads {} \; -print
## 結果が表示されなかった

registory上の/storageに存在するので、何かしらそこに配置された理由があるはずですが、harborのコード中には原因がなさそうです。コードを詳細に読む前に、再現させてnginxのログファイルをもう少し詳しくみていこうと思います。

docker-push時のreverse-proxyログの抜粋
92.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "GET /v2/ HTTP/1.1" 401 87 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - user01 [10/Jan/2020:15:01:36 +0900] "GET /service/token?account=user01&scope=repository%3Alibrary%2Fmynginx%3Apush%2Cpull&service=harbor-registry HTTP/1.1" 200 984 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "HEAD /v2/library/mynginx/blobs/sha256:8...d HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "HEAD /v2/library/mynginx/blobs/sha256:d...7 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:36 +0900] "HEAD /v2/library/mynginx/blobs/sha256:b...6 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "POST /v2/library/mynginx/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "POST /v2/library/mynginx/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "POST /v2/library/mynginx/blobs/uploads/ HTTP/1.1" 202 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "GET /v2/library/mynginx/blobs/uploads/8...d?_state=m...Q%3D%3D HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/8...d?_state=m...Q%3D%3D" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "GET /v2/library/mynginx/blobs/uploads/5...5?_state=-8...Q%3D%3D HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/5...5?_state=-8...Q%3D%3D" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:37 +0900] "GET /v2/library/mynginx/blobs/uploads/9...c?_state=E...Q%3D%3D HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/9...c?_state=E...Q%3D%3D" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "GET /v2/library/mynginx/blobs/uploads/9...c?_state=o...9&digest=sha256%3A1...9 HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/9...c?_state=o...9&digest=sha256%3A1...9" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "GET /v2/library/mynginx/blobs/uploads/5...5?_state=W...6 HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/5...5?_state=W...6" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "GET /v2/library/mynginx/blobs/uploads/8...d?_state=...9&digest=sha256%3A7...0 HTTP/1.1" 204 0 "http://inovtst9.u-aizu.ac.jp/v2/library/mynginx/blobs/uploads/8...d?_state=i...9&digest=sha256%3A7...0" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "HEAD /v2/library/mynginx/blobs/sha256:7...0 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "HEAD /v2/library/mynginx/blobs/sha256:1...9 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"
192.168.1.240 - - [10/Jan/2020:15:01:38 +0900] "HEAD /v2/library/mynginx/blobs/sha256:b...6 HTTP/1.1" 404 0 "-" "docker/19.03.5 go/go1.12.12 git-commit/633a0ea838 kernel/4.15.0-74-generic os/linux arch/amd64 UpstreamClient(Docker-Client/19.03.5 \x5C(linux\x5C))" "-"

この時にregistory podの/storageは次のようになっていて、library/ubuntu/_uploads以外にはファイルが存在しない状態です。

$ /storage
/storage/docker
/storage/docker/registry
/storage/docker/registry/v2
/storage/docker/registry/v2/repositories
/storage/docker/registry/v2/repositories/library
/storage/docker/registry/v2/repositories/library/ubuntu
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/hashstates
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/hashstates/sha256
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/hashstates/sha256/0
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/data   
/storage/docker/registry/v2/repositories/library/ubuntu/_uploads/fc83002e-b800-4ef2-bbab-16d2014fbc82/startedat
....

ひとまずHarborを自分でコンパイルしてみて、_uploadsに配置されたファイルがblobsに移動されるまでの処理のどこに問題があるのか調べていきます。issuesを眺める限りは再現性がなく、いつのまにか解決しているようです。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今日のdocker 作業

OSを10.15.2 に上げた。

zsh
Last login: Wed Jan 15 08:56:14 on ttys001

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.2
BuildVersion:   19C57

$ system_profiler SPSoftwareDataType
Software:

    System Software Overview:

      System Version: macOS 10.15.2 (19C57)
      Kernel Version: Darwin 19.2.0
      Boot Volume: Macintosh HD
      Boot Mode: Normal
      Computer Name: my_com_name
      User Name: my_name (my_name)
      Secure Virtual Memory: Enabled
      System Integrity Protection: Enabled
      Time since boot: 22:56

$ uname -a
Darwin KM-S05.local 19.2.0 Darwin Kernel Version 19.2.0: Sat Nov  9 03:47:04 PST 2019; root:xnu-6153.61.1~20/RELEASE_X86_64 x86_64

$ $ uname -p
i386

$ cat /System/Library/CoreServices/SystemVersion.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>19C57</string>
    <key>ProductCopyright</key>
    <string>1983-2019 Apple Inc.</string>
    <key>ProductName</key>
    <string>Mac OS X</string>
    <key>ProductUserVisibleVersion</key>
    <string>10.15.2</string>
    <key>ProductVersion</key>
    <string>10.15.2</string>
    <key>iOSSupportVersion</key>
    <string>13.0</string>
</dict>
</plist>

$ brew update
Updated 2 taps (homebrew/core and homebrew/cask).
==> Updated Formulae
ack             assimp          bitrise         libsixel        opa
acpica          atlassian-cli   conan           libtensorflow   rhino
ammonite-repl   azure-cli       exploitdb       minio-mc        serverless
artifactory     babel           firebase-cli    mysql           snapcraft
ask-cli         balena-cli      kind            okteto          terragrunt
$ brew upgrade

docker(19) 言語処理100本ノックをdockerで。python覚えるのに最適。
https://qiita.com/kaizen_nagoya/items/7e7eb7c543e0c18438c4

zsh
$ docker run -v /tmp/work:/tmp/work -p 8080:8080 -it kaizenjapan/100pon /bin/bash

Unable to find image 'kaizenjapan/100pon:latest' locally
latest: Pulling from kaizenjapan/100pon
05d1a5232b46: Already exists 
33529d049adc: Already exists 
be72550a31b7: Already exists 
40cab810eef6: Extracting  1.312MB/1.312MB
90a7cfada776: Download complete 
63b10c589b27: Download complete 
3b74f2e93e93: Download complete 
4ad328879d5f: Downloading  113.9MB/985.1MB
53bb48f40962: Downloading  126.7MB/2.076GB
7430ebce441f: Download complete 
152f700bf3d8: Downloading  49.91MB/3.14GB

1) Already exists

すでにdocker で ubuntuなどを起動したことがある場合

2) Downloading

現在Downloading中

3) Download complete

4) Extracting

参考資料(reference)

macOS (OS X, Mac OS X) のバージョンを調べるコマンドやファイル
https://qiita.com/niwasawa/items/1b12ad162abb7f84eff9

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今日のdocker エラー: failed to register layer:

OSを10.15.2 に上げた。

macOS

zsh
Last login: Wed Jan 15 08:56:14 on ttys001

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.2
BuildVersion:   19C57

$ system_profiler SPSoftwareDataType
Software:

    System Software Overview:

      System Version: macOS 10.15.2 (19C57)
      Kernel Version: Darwin 19.2.0
      Boot Volume: Macintosh HD
      Boot Mode: Normal
      Computer Name: my_com_name
      User Name: my_name (my_name)
      Secure Virtual Memory: Enabled
      System Integrity Protection: Enabled
      Time since boot: 22:56

$ uname -a
Darwin KM-S05.local 19.2.0 Darwin Kernel Version 19.2.0: Sat Nov  9 03:47:04 PST 2019; root:xnu-6153.61.1~20/RELEASE_X86_64 x86_64

$ $ uname -p
i386

$ cat /System/Library/CoreServices/SystemVersion.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>19C57</string>
    <key>ProductCopyright</key>
    <string>1983-2019 Apple Inc.</string>
    <key>ProductName</key>
    <string>Mac OS X</string>
    <key>ProductUserVisibleVersion</key>
    <string>10.15.2</string>
    <key>ProductVersion</key>
    <string>10.15.2</string>
    <key>iOSSupportVersion</key>
    <string>13.0</string>
</dict>
</plist>

$ brew update
Updated 2 taps (homebrew/core and homebrew/cask).
==> Updated Formulae
ack             assimp          bitrise         libsixel        opa
acpica          atlassian-cli   conan           libtensorflow   rhino
ammonite-repl   azure-cli       exploitdb       minio-mc        serverless
artifactory     babel           firebase-cli    mysql           snapcraft
ask-cli         balena-cli      kind            okteto          terragrunt
$ brew upgrade

docker

docker(19) 言語処理100本ノックをdockerで。python覚えるのに最適。
https://qiita.com/kaizen_nagoya/items/7e7eb7c543e0c18438c4

zsh
$ docker run -v /tmp/work:/tmp/work -p 8080:8080 -it kaizenjapan/100pon /bin/bash

Unable to find image 'kaizenjapan/100pon:latest' locally
latest: Pulling from kaizenjapan/100pon
05d1a5232b46: Already exists 
33529d049adc: Already exists 
be72550a31b7: Already exists 
40cab810eef6: Extracting  1.312MB/1.312MB
90a7cfada776: Download complete 
63b10c589b27: Download complete 
3b74f2e93e93: Download complete 
4ad328879d5f: Downloading  113.9MB/985.1MB
53bb48f40962: Downloading  126.7MB/2.076GB
7430ebce441f: Download complete 
152f700bf3d8: Downloading  49.91MB/3.14GB

1) Already exists

すでにdocker で ubuntuなどを起動したことがある場合

2) Downloading

現在Downloading中

3) Download complete

4) Extracting

docker error

zsh
$ docker run -v /tmp/work:/tmp/work -p 8080:8080 -it kaizenjapan/100pon /bin/bash
Unable to find image 'kaizenjapan/100pon:latest' locally
latest: Pulling from kaizenjapan/100pon
05d1a5232b46: Already exists 
33529d049adc: Already exists 
be72550a31b7: Already exists 
40cab810eef6: Extracting  1.312MB/1.312MB
90a7cfada776: Download complete 
63b10c589b27: Download complete 
3b74f2e93e93: Download complete 
4ad328879d5f: Download complete 
53bb48f40962: Download complete 
7430ebce441f: Download complete 
152f700bf3d8: Download complete 
docker: failed to register layer: open /var/lib/docker/overlay2/598c537285d52ff0ae3bd2e551b1beba59e5608993a09ee3da118d9782ea4704/link: no such file or directory.

参考資料(reference)

macOS (OS X, Mac OS X) のバージョンを調べるコマンドやファイル
https://qiita.com/niwasawa/items/1b12ad162abb7f84eff9

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerでnode.jsプロジェクトの開発環境構築

動機

  • 新しくMac Book Pro 2019を購入。nodeやpytonの開発環境構築にあたっては, 素の環境を綺麗なままにしたいことや、いろいろな環境での開発を行いためDockerを用いることにした。
  • Docker周りの設定や概念の理解で少し躓いたのでここに記す。エキスパートには当たり前すぎる内容だとしてもだ。

やりたいこと

node.js, angular, ionic, webpack を使ったweb appやPWAの開発を、
- ホストのローカル環境を汚すことなく(Dockerを用い)
- ホストで動くVS Codeを用いたコーディング&デバッグしつつ
- ホストのターミナルからgitを用いたバージョニングしつつ
- 仮想マシンでionic server等で起動したサーバとその上で動くweb appを、ホストのブラウザからアクセスし動作確認・デバッグ

手順

1. Docker desktop for Macをインストール

https://hub.docker.com からダウンロード。ユーザ登録も済ます。

2. プロジェクトのディレクトリ構造

最終的に下記になります。順番に作っていきましょう。

- Dockerfile
- docker-compose.yml
- app
   |- ここに諸々のソースを置く

3. Dockerfile

Dockerfie : Imageを作成する設定ファイル
Image : 仮想マシンの雛形。OS, インストールされたソフトウェアセット等からなる。

node.js入りのalpine linuxのimageをベースに、ionicとcordovaをインストールしたimageを作成する。

alpine linux : 超軽量linux. Dockerの仮想マシンOSとして頻繁に利用されている.

host
$ cat Dockerfile
FROM node:10.13-alpine
WORKDIR /app
RUN npm install -g ionic cordova
CMD ["sh"]

下記コマンドでDocker imageを作成します。最初に実行する場合ローカルにnode:10.13-alpineのイメージがないのでdocker hubからダウンロードされてきます。2回目以降はローカルのイメージが使われます。

host
$ docker build . -t watashino-image

-tはイメージの名前を与えるオプションです。適当につけてOK。
正常に完了すればdocker imagesでimageが作成されていることが確認できます。nodeのイメージもダウンロードされローカルに保存されています。

host
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
watashino-image                latest              da6f921ba540        2 minutes ago       133MB
node                10.13-alpine        93f2dcbcddfe        13 months ago       70.3MB

このimageが仮想マシンの雛形となります。

4. docker-compose.yml

続いて、imageを実際に起動するためのファイルを記述します。

docker-compose.yml : docker-composeというコマンドへ与える設定ファイル

docker-compose :imageからcontainerを作成・起動するプログラム。

container : 厳密な話は置いておいて、ざっくりいうと、雛形であるimageから作成された仮想マシンを表す。型とそのインスタンス、という関係に近い。

実際のところ、"docker"コマンドだけでもcontainerの作成・起動はできるが、オプションの指定等が面倒だったり複数のcontainerの起動等も同時に行えるdocker-composeの方が便利そうなので、最初からこちらを採用。

host
$ cat docker-compose.yml
version: '3'
services:
  app:
    build: .
    image: watashino-image
    volumes:
      - ./app:/app
    ports:
      - "8100:8100"
    tty: true

下記のコマンドでcontainerの作成・起動。まだローカルにappフォルダを作っていない場合には作っておく。

host
$ mkdir app
$ docker-compose up -d

何事もなくコマンドが終了すれば成功。仮想マシンはバックグラウンドで動作している。下記コマンドで実行中のcontainerの一覧が見れる。

host
$ docker ps 

お気づきの方もいるでしょうが、実はstep 3のdocker buildのコマンドは実行しなくてもよかったのです。"build: ."の行はビルドに関する指示で、docker-composeファイルは指定されたimageが存在しない場合には自動的にDockerfileを参照してimageのbuildと、続いてcontaierの作成と起動を行います。imageとcontainerの関係を明らかにするために冗長な手順とさせてもらいました。

他の設定の意味:
services docker-composeでは仮想マシンをserviceという呼び方をするようです。ここでは"app"というサービスを一つ定義しています。複数の仮想マシン=サービスの設定を書いてまとめて起動することもできます。というかそれこそがdocker-composeが便利な点で使う理由です。
volumes ローカルの./appフォルダと仮想マシンにおける/app (root直下)を結びつけます。これによより仮想マシンとホストマシンのファイルが同期されるようになります。

ports ポートフィワーディングの設定。仮想マシンのport 8100とローカルのport 8100を結びつけます。仮想マシンにおけるlocalhost:8100に、ホストマシンからlocalhost:8100でアクセスできるようになります。(ただし後述の注意点あり)

tty これがtrueではないと、containerは起動後すぐに終了してしまう。

5. 動作中の仮想マシンを操作

バックグランドで実行されているcontainerには下記のコマンドでアクセスできます。

host
$ docker exec app sh

何をしているかというとappサービス(docker-compose.xmlで指定した名称)でshの実行を指示しています。上記を実行するとシェルで仮想環境の中をいじれるようになります。

仮想環境から退出するには

container
# exit

します。

6. gitからソースを持ってくる&VS Codeで読み込む

app以下にソースコードを持ってきましょう。ローカルのappフォルダで通常通りgitでソースファイルを持ってきます。

host
$ cd app
$ git clone アドレス

仮想環境にgitをinstallすれば仮想環境で直接gitを使えるでしょうが(未確認)、わざわざそうする必要もないかと思います。

ファイルは同期されていますから、特に意識することなくローカル環境のVS Codeを開き、ローカルのappフォルダを開けばOK

7. 仮想環境でビルド&実行

host
$ docker-compose exec app sh

で仮想環境に入りappフォルダを覗けばソースコードが見えるはずです。あとは通常通りの開発ルーチンに従います。ここではionicプロジェクトの例では、下記のようなことを行います。ionic(ng)のビルドインサーバをポートフォワーディングで設定したportで起動しています。

container
# npm install
# ionic serve -p 8100 --address 0.0.0.0

これによりホスト環境から localhost:8100 で仮想環境内のWEBサーバにアクセスできます。--address 0.0.0.0 を付けないとホストからは見れません。理由はこちらをご参考ください。

8. Containerの停止, 再開

開発が終わったら起動させておくのは無駄でしょうから、Containerを停止します。

host
$ docker-component stop

で停止,

host
$ docker-component up -d

で再開します。なお、containerを停止すると、Continerの起動中に作成したファイルは、volumesでホストのディレクトリに保存しているもの以外は全て消えてしまいます。

containerのライフサイクル、データの永続化については以下のような記事を参考ください。
- https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32
- https://qiita.com/onokatio/items/fcc9f8f94f8533bb030a

なお今回はホストのファイルシステムとの同期、という方法のみを扱っていますが、そのほかにも永続化手段もある模様(未トライ)

9. container, imageの削除

ニッチもさっちも行かなくなった場合、全ての過去を消し去りたいと思ったら、docker-component downコマンドを使います。下記が参考になります。

気軽に環境丸ごと削除してやり直せるというのが、Dockerを用いた開発の最大のメリットでしょう。

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む