寝ても覚めてもこんぴうた

プログラム書いたり、ネットワーク設計したり、サーバ構築したり、車いじったり、ゲームしたり。そんなひとにわたしはなりたい。

コンテナでgcloudコマンドを実行するとERROR: gcloud crashed (UnicodeDecodeError): 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128) みたいなエラーが出る

f:id:chidakiyo:20190719134440j:plain

タイトルの通りで、 コンテナ環境で gcloud コマンドを実行した際 ERROR: gcloud crashed (UnicodeDecodeError): 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128) のようなエラーが発生してうまく実行できない。

なぜ

glcoudコマンドの中でpythonを実行しているようなのですが、処理するファイルに非asciiな文字列が含まれている場合、pythonのレイヤーでエラーが出ているようです。

これはgcloudコマンド特有の問題ではなく、コンテナ内で各種コマンドを実行した際のあるあるです。 (昔一度ハマったのにまたハマったので記事にしました)

対策

解決方法としては、一番手っ取り早いのは

export LANG=C.UTF-8

のような形で環境変数にLANGを指定してあげれば良いです。

LANG="ja_JP.UTF-8" のような形で設定することもできますが、 その場合には apt-get -y install language-pack-ja みたいな形でlanguage packのインストールが必要そうです。

インストールしていない場合には -bash: warning: setlocale: LC_ALL: cannot change locale (ja_JP.UTF-8) のようなエラーメッセージが出ます

モノレポ(mono repository)内でgoのmoduleを相対パスで利用する方法

f:id:chidakiyo:20190703173656j:plain

goの依存管理ツールはいろいろありますが、最新はGo Modules(mod)を利用することが多くなってきたと思います。 dep(vendor)を利用した依存解決の場合にはgopath配下にあればある程度柔軟に相対的に依存を解決できましたが、 modは普通に利用するとリポジトリにコミットをした状態を期待しているような振る舞いをします。

モノレポで以下のように複数のモジュールを管理している場合には、modでは利用しづらいように思えましたが、 参照しているモジュールをコミットした状態ではなくとも参照したいという要望があったので解決してみました。

project
  ├ a_module
  │  ├ go.mod
  │  └ main.go
  ├ b_module
  │  ├ go.mod
  │  └ hoge
  │     └ say.go
  ...

各モジュールをmod化する

各モジュールをmod化します。 mod init する際に以下のように module 名を設定します。

// a_moduleをmod化
$ cd path/to/project/a_module
$ go mod init a_module

// b_moduleをmod化
$ cd path/to/project/a_module
$ go mod init b_module

作成されたmodファイルは以下のようになります。

a_module/go.mod

module a_module

go 1.12
b_module/go.mod
module b_module

go 1.12

a_moduleからb_moduleを参照する

a_moduleからb_moduleを利用したい場合、a_moduleのmodファイルを以下のように追記します

a_module/go.mod

module a_module

go 1.12

require (
    b_module v0.0.0
)

replace b_module => ../b_module

b_moduleを依存として利用します(require)という記述と、 b_moduleは ../b_module という相対位置にありますという記述が必要になります。 modの相対位置の関係はgo.modファイルがある位置になるようです。

コード側からb_moduleの関数を利用する

先程の記述は依存関係を定義したので、実際にa_moduleのファイルからb_moduleの関数を利用してみます。

a_module/main.go

package main

import (
    "b_module/hoge"
)

func main() {
    hoge.Say() // b_moduleで実装した関数 // Hello
}

main.goが作成できたら go run main.go などで実行します。 実行の際に依存関係の取得が行われます。

ちなみに b_module/hoge/say.go の中身はこんな感じになるかと思います。

package hoge

func Say() string {
    return "Hello"
}

まとめ

このようにmodファイルを構成することでモノレポで管理しているプロジェクトでも 共通のユーティリティモジュールなどを柔軟に参照することができます。

一時 GO111MODULE=off を利用し、vendor(dep) を引き続き利用していましたが、 こちらの方法でも同じように管理できるようになったのでまとめました。

ツッコミどころなどあればコメントください。

次回作の予告

上記のmodでの相対的なモジュール管理はGAEで利用しようとすると、Appengineのbuildのプロセスでは相対的に取得できるはずのモジュールが取得できないため、デプロイがエラーになります。 その部分も回避策があるため次回の記事で書きます。

参考

cmd/go: clarify go.mod documentation for trivial relative modules · Issue #27274 · golang/go · GitHub

go build keeps complaining that: go.mod has post-v0 module path - Stack Overflow

Docker build時にキャッシュを利用しない

Docker build する際に、基本的にはCacheを利用されますが、 それでは困る(毎回ちゃんと処理したい)という場合もあると思います。

そんなときは --no-cache オプションを docker build 時に付与すれば良い。

ま、それだけ。

docker build | Docker Documentation

BQMLのサンプルのqueryitを触ってみた

query-itってなに?

Groovenautsさんが作った、BQMLのサンプルアプリケーション ソースコードもろもろは多分 こちら

こちらのURL からアクセスできたのでメモがてら記事を残します。

使い方

URLでアクセス

http://queryit.magellanic-clouds.com/ にアクセスします。

最初、reCAPTCHAが表示されるのでポチッとしましょう。

f:id:chidakiyo:20190411085732p:plain

メニューを選ぶ

  • wikimediaのイメージから似たものを探す
  • ニューヨークのレンタル自転車の需要予測

の2つから選択できます。

f:id:chidakiyo:20190411085756p:plain

wikimediaを実行してみる

wikimediaのアイコンをクリックしたあとでランダムに画像が3点表示されます。 選択した画像に似た画像をBQを利用して公開画像から探して表示をしてくれます。

3つのうちのどれかを選択してみましょう

f:id:chidakiyo:20190411085813p:plain

実行するとBQでクエリが実行され少し待ち時間があります。

f:id:chidakiyo:20190411085835p:plain

クエリの実行が終了すると画面内にBQが似ていると判定した画像たちが表示されます。 たしかに結構似てますね。

f:id:chidakiyo:20190411085855p:plain

実行したクエリを見る

ShowSQLボタンを押すと実行したクエリが表示されます。 クエリの一部が表示されるので、スクロールして全体を見ることができます。

f:id:chidakiyo:20190411085914p:plain

レンタル自転車の需要予測を実行してみる

メニューからニューヨークのレンタル自転車の需要予測を選択します。

条件を指定するダイアログが表示されますので、 予測したい条件を入力します。

f:id:chidakiyo:20190411085935p:plain

クエリが実行され、しばらく待ちます。

f:id:chidakiyo:20190411085950p:plain

だいたい20秒ぐらいで予測が完了します。 めちゃ速いですね

f:id:chidakiyo:20190411090008p:plain

画面のcloseを選択し、地図上に表示された予測を見てみましょう

f:id:chidakiyo:20190411090030p:plain

先程と同様に ShowSQL ボタンを押すことでクエリを見ることができます。

さいごに

こちらのデモは2年ぐらい前のGoogle Next Tokyoで見たのですが、 BQの可能性を感じたとてもおもしろいサンプルで、今回publicにアクセスできるURLを見つけたので感動をシェアしたくて記事にしました。

BQ便利なのでどんどん使っていきましょう!

git diffで長い行を改行して表示させる

git diff をしたときに長い行がターミナルの外に行ってしまって見えない場合、

GIT_PAGER='' git diff ~~

とすればよい。

これだけ、簡単。

自分がよく利用するDockerのコンテナ(メモ)

CI/CDをする際によく利用する、GCPを利用するなら特に知っていたほうが良さそうなコンテナたちをメモ。

GoogleCloudPlatform/cloud-builders

GitHub - GoogleCloudPlatform/cloud-builders: Supported builder images for Google Cloud Build

この辺りが含まれています。

f:id:chidakiyo:20190311094126p:plain

GoogleCloudPlatform/cloud-builders-community

GitHub - GoogleCloudPlatform/cloud-builders-community: Community-contributed images for Google Cloud Build

だいぶいろいろあります。

gcpug/docker-appengine-go

GitHub - gcpug/docker-appengine-go: https://gcr.io/gcpug-container/appengine-go

gitlab-ciでデプロイする際に私は利用しています。

enjoy!

GCP Update 2019/03/06

直近のGCPのアップデートはこんな感じ

- BigQuery sandbox: beta
- Kubernetes Engine – node auto-repair: GA
- Kubernetes Engine – node auto-upgrades: GA
- Compute Engine – guest attributes: beta
- Kubernetes Engine – Application-layer Secrets Encryption: beta
- Compute Engine – health checking and autohealing for managed instance groups: GA
- Cloud Composer – support for multiple Apache Airflow versions: GA
- BigQuery available in São Paulo: GA
- Cloud TPU on Cloud Machine Learning Engine: GA
- Compute Engine machine types: beta
- Cloud ML Engine – training with custom containers: beta
- Cloud Storage – Bucket Policy Only: beta
- Transfer Appliance model TA480 available in Europe: beta

Key announcementsは BigQuery sandbox で アナリティクスに対して無料でクエリできるよ、みたいな感じだろうか。