【IIJ 2018 TECHアドベントカレンダー 12/17(月)の記事です】
IIJではGithub Enterpriseと連携するCIサーバーとしてdroneを利用していますが(IIJ Engineers Blog - IIJのサービス開発を支えるGithub Enterpriseとdrone.io)、droneの知名度はまだTravis CIやCircleCIほどではなく、エラーメッセージをググっても出てこないことがあります。こんな時にはdrone-serverを直接デバッグするとすぐ解決することがあります。デバッグを始めるまでちょっとしたノウハウが必要だったので本記事で紹介したいと思います。
drone-serverはUbuntuのデスクトップPCで動かしてデバッグすることを想定します。(多分macOSでも以下の手順で動くと思います。Windowsは /var/lib/drone/
などのパスを変える必要があると思います。)
droneのバージョン
2018/12/14現在droneの最新版は1.0.0-rc.2となっていますが、ソースコードはまだ公開されていません。公開されている最新版は0.8.10となっているため、このバージョンを使うことにします。ドキュメントはこちらです。
// docker inspect drone/drone:1.0.0-rc.2
を見ると、drone 1.0.0はプライベートレポジトリ https://github.com/bradrydzewski/drone-ee (あるいはそのフォーク元)で開発されているようです。
セットアップ
参考:
- https://0-8-0.docs.drone.io/installation/
- https://0-8-0.docs.drone.io/install-for-github/
- https://docs.drone.io/installation/github/single-machine/
- https://0-8-0.docs.drone.io/getting-started/
デスクトップPCで動かすためngrokを使います。
ngrokを使う際はセキュリティに十分気を付けて下さい。特にGitHub Enterpriseには繋がないで下さい。URLが分かればレポジトリ一覧を閲覧することができてしまいます。
ngrok http 9999
:
http://localhost:4040 を出しておくとトラブルシューティングに役立つかもしれません。
https://github.com/settings/applications/new でOAuth applicationを登録します。
以下の docker-compose.yaml
で docker-compose up
を実行してdrone-serverを起動してみます。
// httpsだとSSL handshakeが失敗したのでhttpにしています
version: '2'
services:
drone-server:
image: drone/drone:0.8
ports:
- 9999:8000
- 9000
- 2345:2345
volumes:
- ./:/var/lib/drone/
restart: always
environment:
- DRONE_OPEN=true
- DRONE_HOST=https://27be75f8.ngrok.io
- DRONE_GITHUB=true
- DRONE_GITHUB_CLIENT=07cf285492f97c12f701
- DRONE_GITHUB_SECRET=11a318b4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- DRONE_SECRET=foobar
- DRONE_DEBUG=true
privileged: true
drone-agent:
image: drone/agent:0.8
command: agent
restart: always
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_SERVER=drone-server:9000
- DRONE_SECRET=foobar
drone-serverの ports:2345:2345
, privileged: true
は後に出てくるdlvのために必要です。
http://27be75f8.ngrok.io にアクセスするとGitHubの認証ページにリダイレクトさるので "Authorize " をクリックします。
GitHubからdronetestのような適当なレポジトリを作って、droneでACTIVATEしてから以下の .drone.yml
をpushします。
pipeline:
build:
image: alpine
commands:
- ls
トラブルシューティング
上手く行かない場合環境をリセットすると良いかもしれません。
- ngrok再起動
- https://github.com/settings/developers -> "drone" の "Homepage URL" と "Authorization callback URL" を修正
-
docker run
の--env=DRONE_SERVER_HOST=
を修正
- docker containerリセット:
sudo rm /var/lib/drone/database.sqlite; docker stop drone; docker rm drone; docker run ...
- https://github.com/settings/developers -> "drone" -> "Revoke all user tokens"
drone-serverデバッグ用docker image作成
cd work/
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go get -v github.com/drone/drone/cmd/drone-server
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go get -v -u github.com/derekparker/delve/cmd/dlv
file $GOPATH/bin/drone-server # on macOS: $GOPATH/bin/linux_amd64/drone-server
file $GOPATH/bin/dlv # on macOS: $GOPATH/bin/linux_amd64/dlv
# => /home/wsh/go/bin/dlv: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped
# on linux, without CGO_ENABLED=0, dlv will be dynamically linked:
# /home/wsh/go/bin/dlv: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=f414998edff629d1700948bb15644cbd6985aa73, with debug_info, not stripped
vim Dockerfile
cp $GOPATH/bin/drone-server $GOPATH/bin/dlv ./
docker build -t dronedebug .
# drone-server: image: drone/drone:0.8 を
# drone-server: image: dronedebug に書き換え
vim docker-compose.yml
docker-compose up
# 別ターミナルで docker-compose exec app bash
Dockerfile
の内容:
FROM drone/drone:0.8
EXPOSE 8000 9000 80 443 2345
COPY dlv /bin/
COPY drone-server /bin/
ENTRYPOINT ["/bin/dlv", "exec", "--headless", "--listen=:2345", "/bin/drone-server"]
drone-serverのデバッグ
docker-compose up
を実行するとdlv serverがポート2345で待ち受けます。
$ docker-compose up
Recreating drone_drone-server_1_79abe9cfaada ... done
Recreating drone_drone-agent_1_ff203d9ce2d0 ... done
Attaching to drone_drone-server_1_79abe9cfaada, drone_drone-agent_1_ff203d9ce2d0
drone-agent_1_ff203d9ce2d0 | {"time":"2018-12-18T10:59:49Z","level":"debug","message":"request next execution"}
drone-server_1_79abe9cfaada | API server listening at: [::]:2345
drone-agent_1_ff203d9ce2d0 | INFO: 2018/12/18 10:59:49 grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: Error while dialing dial tcp 172.22.0.2:9000: getsockopt: connection refused"; Reconnecting to {drone-server:9000 <nil>}
ホストで dlv connect localhost:2345
を実行するとリモートデバッグが開始されます。
(dlv) b main.main
Breakpoint 1 set at 0xa3ecd3 for main.main() /home/wsh/go/src/github.com/drone/drone/cmd/drone-server/main.go:27
(dlv) c
> main.main() /home/wsh/go/src/github.com/drone/drone/cmd/drone-server/main.go:27 (hits goroutine(1):1 total:1) (PC: 0xa3ecd3)
Warning: debugging optimized function
22:
23: _ "github.com/joho/godotenv/autoload"
24: "github.com/urfave/cli"
25: )
26:
=> 27: func main() {
28: app := cli.NewApp()
29: app.Name = "drone-server"
30: app.Version = version.Version.String()
31: app.Usage = "drone server"
32: app.Action = server
(dlv) n
> main.main() /home/wsh/go/src/github.com/drone/drone/cmd/drone-server/main.go:28 (PC: 0xa3ece1)
Warning: debugging optimized function
23: _ "github.com/joho/godotenv/autoload"
24: "github.com/urfave/cli"
25: )
26:
27: func main() {
=> 28: app := cli.NewApp()
29: app.Name = "drone-server"
30: app.Version = version.Version.String()
31: app.Usage = "drone server"
32: app.Action = server
33: app.Flags = flags
冒頭の画像ではGoLandを使ってリモートデバッグしています。
おわりに
droneはdockerコンテナ上で動作する上にソースコードホスティングサービスとの連携もあるため手順は煩雑でしたが、ネイティブプログラムと同じようにdelveによるデバッグを行うことができました。
本記事の手順で検証用droneサーバーのリモートデバッグも可能になると思います。
ライセンス
この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。
関連するソフトウェアの公式ドキュメントのメンテナの方へ:この記事の内容を公式ドキュメントに記載して頂ける場合、この記事にコメントして頂くか、twitter @wata_ash にご連絡下さい。