Docker for Windows に GitLab CE をインストールする

ちょっとはまったので備忘録。

TL;DR

コンテナにホストのファイルシステムをマウントして使おうとするとうまくいかない事がある (パーミッション問題?) ので、そのような時は volume を作ってそっちにマウントする。

GitLab の設定

Docker for Windows は Ver.18.09.2 を使用。

GitLab の Docker イメージは offical ( gitlab/gitlab-ce ) を利用します。

Docker Compose のファイル を落としてきてマウント先をホストの任意のディレクトリに設定。起動しようとすると下記のようなエラーが出ます。

Error executing action run on resource 'ruby_block[directory resource: /var/opt/gitlab/git-data]'

これの回避の仕方が下記の Issue に記載されています。

ここでの結論は "/var/opt/gitlab" のマウント先をホストではなく volume を作成してそちらにマウントする、でした。

おそらくこちらの記事と同じ理由。

実際やってみると初期化まではうまくいきますが、ユーザーの ssh 公開鍵の登録がうまくいきませんでした。ので "/etc/gitlab" も volume を作成してマウントしてみると公開鍵の登録も成功し、 git push も ssh で通るようになりました。 (これはもしかしたら関係ないかも)

ログ ("/var/log/gitlab") は今のところ問題なかったのでホストにマウントさせています。

別件で最近の GitLab のイメージは Let's Encrypt を使うようになっているとのことなのですが、ローカルで使うには不要なのでオプションで無効化しています。

volume の作成:

> docker volume create gitlab-data
> docker volume create gitlab-config

Docker Compose:

version: "3"

services:
  web:
    image: 'gitlab/gitlab-ce:latest'
    restart: always
    hostname: '{PC名}'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url '{URL}'
        letsencrypt['enable'] = false
    ports:
      - '80:80'
      - '443:443'
      - '22:22'
    volumes:
      - 'gitlab-config:/etc/gitlab'
      - '{ホストへのログ保存先}:/var/log/gitlab'
      - 'gitlab-data:/var/opt/gitlab'
volumes:
    gitlab-data:
        external: true
    gitlab-config:
        external: true

WEX-1166DHP 設定メモ

www.buffalo.jp

久しぶりに設定を変えようとしたら大変はまったので備忘録。WPS の類は一切使わない人向け。

大ざっぱな手順

  1. 電源を入れて RESET ボタンを押し、設定をクリアする。
  2. 有線 LAN で PC と接続する。 (重要)
  3. 裏に貼ってある IP アドレスにブラウザで接続し、設定画面にログインする。
  4. 管理者パスワードを変える。
  5. WEX-1166DHP に対して無線で接続するなら無線 LAN 設定をする。有線でしか接続しないなら無線設定を全て無効化する。
    • 無線で設定できるようになら SSID2 がデフォルトオープンになっているので、 必ず暗号化設定 (WPA) をする。
  6. 最後に親機に対する無線設定をする。

親機に対する無線設定をするとおそらく無線経由の設定パス (SSID2) を有効にしておかないと設定できなくなると思います。その場合は親機の電源を落として親機に対して接続できないようにしてから有線 LAN で PC と直結する (未確認) 。あるいはあきらめて 1. から全てやり直す。

重要

無線 LAN で設定をしない。

SSID2 のデフォルトが暗号化なし状態なので 設定画面のパスワードや接続用の SSID を安全に設定できない 。無線でやるなら次のようにすればよい?

  1. 電源を入れて RESET ボタンを押し、設定をクリアする。
  2. 裏に貼ってある管理用 SSID で接続し、ブラウザで設定画面にログインする。
  3. 管理用 SSID (SSID2) に暗号化設定をして (SSID の名前自体も変えた方がよい) 再度接続する。
  4. もう一度管理用 SSID を変更して接続しなおす。
  5. 管理者パスワードを変える。

ここまですれば大抵は問題ないように思いますが、完全ではないし、無線による設定は (自分のところだけだったかもしれませんが) 不安定だったので有線 LAN で接続して設定した方がよいかなあと思いました。

BitLocker メモ

ちょっとはまったので備忘録。

BitLocker は Windows の Pro 以上が必要です。

グループポリシーの設定をする

ブートドライブに BitLocker の設定をする場合、実質必ずグループポリシーの設定が必要です。

TPM が搭載されている場合、 TPM に複合キーを格納するモードで動作するので何も設定しなくても BitLocker の構成を行えるのですが、この状態だとパスワード (PIN) などでの認証ができません。これらの設定をするためにも必要になります。

グループポリシーの設定は

  1. 管理者権限で "gpedit.msc" を実行します。
  2. "コンピューターの構成 - 管理用テンプレート - Windows コンポーネント - BitLocker ドライブ暗号化 - オペレーティングシステムのドライブ" を選択します。

TPM がない環境で BitLocker 起動を有効にする

  1. "スタートアップ時に追加の認証を要求する" を選択し、 "有効" にする。
  2. "互換性のある TPM が装備されていない BitLocker を許可する" にチェックし、適用する。

TPM がある環境で BitLocker 起動時の追加認証を設定する

  1. "スタートアップ時に追加の認証を要求する" を選択し、 "有効" にする。
  2. 各スタートアップ構成で "許可する" を選択する。デフォルトで全項目が "許可する" になってると思うので、実質有効にするだけで OK 。
  3. 設定を確認して適用する。

"要求をする" にするとそれだけ使うようになりますが、 "要求をする" が複数あると BitLocker での設定時にエラーになります。

追加認証の具体的な設定 (PIN やスタートアップキーの作成) はコントロールパネルでの設定か、コマンドラインツールで行います。

PIN に数字以外を使えるようにする

"スタートアップの拡張 PIN を許可する" を有効にすると数字以外の文字も使えるようになり、パスワードと同等に使えるようになります。

"TPM でスタートアップキーと PIN を許可する" を使う

今回の本題。一番はまった。 TPM 下でスタートアップキーと PIN の両方を認証に使うモード。

スタートアップキーは USB メモリに鍵情報を仕込み、起動時にこのメモリが接続されていないと起動できなくなる、物理的な鍵と同様に使える機能です。

スタートアップキーは便利なのですが、さしたままにしたままどこかに放置してしまった場合とか、セキュリティリスク的には微妙なところもあるので PIN と組み合わせるとベストになります。

この設定をする方法が

  1. "コントロールパネル - BitLocker ドライブ暗号化" の GUI
  2. コマンドプロンプトの "manage-bde" コマンド (manage-bde -protectors -add c: -tpsk)
  3. PowerShell のコマンドレット "Add-BitLockerKeyProtector" (Add-BitLockerKeyProtector -TpmAndPinAndStartupKeyProtector)

の 3 通りありますが、私の環境では実際にできたのは 3. の PowerShell だけでした。のでこの構成をしたい場合は PowerShell を使うのがよいかと思います。

(2020/5/29 追記)

PowerShell で登録する場合、コマンドラインのパラメーター渡しや対話式でもコンソールに設定する PIN が出力され見えるようになってしまいます。設定する PIN を見せたくない場合は

$pw = Read-Host -AsSecureString

で入力待ちになり、コンソールに出力せずに文字列が入力できます。これで $pw 変数に設定したい PIN を格納し、

Add-BitLockerKeyProtector -Pin $pw -TpmAndPinAndStartupKeyProtector

とすることで PIN をコンソールに出さずに設定する事ができます。

注意点として Read-Host では入力確認がないので、自分が考えていたものと違ったものを入れてしまうと一発アウトになります。ので再起動からログオンができることを確認するまでは回復キーはすぐに使えるようにしておいた方がよいでしょう。

(2022/5/14 追記)

PowerShell での登録はスタートアップキーの追加になるので、まずコントロールパネルの BitLocker から BitLocker の設定をして有効化する (解除方式は PIN でよい) 。その後再起動をして PowerShell でのスタートアップキーを追加します。

パスワードは事前に環境変数で設定しておくとして、それ以外は対話式入力になるので次のように入力する。

  • MountPoint[0] → ブートドライブ名を入力 (c: のはず)
  • MountPoint[1]: → Enter するだけ
  • StartupKeyPath: → スタートアップキーの格納先 (外部 USB メモリのドライブ名)

(2022/5/15 追記)

BitLocker の保護方法でで "数字パスワード" となってるものは回復キーそのものなので、これを消すと回復キーから解除できなくなってしまうので消してはならない。また、 "manage-bde -protectors -get" で設定されている保護方法が表示されるが、その際に数字パスワードが平文で表示されてしまうので、このコマンドを実行する際は要注意。

Win10 WSL + VS2017 のメモ

今更ながら Windows Subsystem for Linux (WSL) + Visual Studio 2017 + Visual C++ for Linux Development がとても便利だったので備忘録。本気出すなら VisualGDB とかになるんでしょうけど、お気軽に Visual Studio でコーディング、デバッグできるのはよいです。

WSL もさっと Bash が上がって閉じれば全てなかったことにできるお気軽さがよいです。 Linux プロセスの完全なデーモン化とかできない方が都合がよいくらい。運用に使うわけではなく開発作業の一時用になりますし。

インストールの仕方は上記の記事で非常に丁寧に説明されています。要点としては

Targeting the Windows Subsystem for Linux from Visual Studio

WSL の設定に加えて VS2017 含めた設定手順が詳しく書いてあります。

Microsoft / VSLinux - Enable x86 on x64

Visual Studio + VSLinux でビルドターゲットになっているリモート環境と同じビルド構成じゃないとビルド時にエラーになるのをなんとかしてほしい issue 。

最後のコメントにある Linux.Common.targets (VS2017 では "C:\Program Files (x86)\Microsoft Visual Studio\2017\*\Common7\IDE\VC\VCTargets\Application Type\Linux\1.0\Linux.targets") をいじるとプラットフォームチェックがなくなるので、事前に x86 のビルドに必要な library 等をターゲットの Linux にインストールしておくとビルドはできるようになります。が、

Microsoft / WSL - Support for 32-bit i386 ELF binaries
Please add 32 bit ELF support to the kernel

WSL は x64 カーネルLinuxx86 バイナリの実行はサポートしていないっぽいです。なので先に書いた MSBuild をいじるのは対 WSL では実質意味ないです。
まあ通常はほとんど困ることはないはずですが、 Qiita 記事 を書いてる時、実行して確かめるのあきらめました。

Godot Engine を試す (C# / 3.0-alpha2)

ふと思い立って Godot Engine というゲームエンジンを試してみました。

Godot Engine とは

Godot Engine - Free and open source 2D and 3D game engine

MIT ライセンスで開発されているマルチプラットフォーム対応のゲームエンジンです。
「ごどー」と読むようです。

先日、スクリプトエンジンとして Mono を利用した C# 対応が発表されました。

Introducing C# in Godot

現在公開されている 3.0-alpha2 から Mono 版が使えます。 Mono 対応は Xamarin 側の協力があったっぽく、また VR/AR 対応なども行っているようです。
これは気になってきた・・・ ので試してみました。

インストールしてみる

3.0-alpha2 は下記の記事からダウンロードできます。

Mono 版は別途最新の Mono 実行環境のインストールが必要です (Windows でも)。デフォルトでインストールすればそのまま使えるようですが、インストール先の変更等をした場合は環境変数の設定が必要のようですので、そこだけ注意。

起動してみる

起動するとプロジェクト選択ダイアログが開きます。初めてなので新規プロジェクトを適当に作って開始。

f:id:tan-y:20171111230501p:plain

メイン画面。レイアウトや名称は違うのですが、意味的には Unity に似ています。レイアウト変更が自由にできるといいんですけどね・・・

f:id:tan-y:20171111230510p:plain

何かしてみる

とりあえず Cube を置いてみましょう。

まず右上の "Scene" タブを押し、 "+" ボタンを押してください。 (もしくは Ctrl+A)
初期状態ではルートノードがないのでとりあえず作ります (ルートがないといろいろ困りました) 。 "Spatial" を選んで "作成" を押してください。この中にさらにアイテムがありますが、 Spatial 自体も追加できるアイテムです。

f:id:tan-y:20171111230517p:plain

続いて Spatial の下に Cube を追加します。先程と同じ手順で今度は "MeshInstance" を追加します。

MeshInstance を追加しても画面上は何も反映されません。これは MeshInstance にレンダリングする Mesh が登録されていないためです。 Mesh プロパティが null なのでクリックして "新しい CubeMesh" を選択すると箱が画面に出ます。

f:id:tan-y:20171111232724p:plain f:id:tan-y:20171111232728p:plain

あとはカメラがないと実行しても何も出ませんので、 InterpolatedCamera を追加して適当な位置、向きを設定します。

ツリービューから探すのは面倒なので "Search" にテキスト入力すると絞り込みしてくれます。

Unity でいう Game ビューは Scene で InterpolatedCamera を選択し、画面に出ている "preview" を押すと表示が切り替わります。エディッター表示と Game ビューを同時に確認したいのであれば、画面上部の View を押すとビューポートが選べますので 2 つ以上を選択し、一方を Game ビューにすればよいかと思います。

f:id:tan-y:20171111230602p:plain

2 ビューポートに変えて下側を Game ビューにしてみます。

f:id:tan-y:20171111230524p:plain

スクリプトを書いてみる

ここからが肝心。 C#スクリプトを書いてみましょう。

まず先程追加した MeshInstance の名前を "Cube" に変えます。 MeshInstance は既定のクラスと存在しており、このままにしておくと後でいろいろはまります (バグっぽい) 。そして "Cube" で右クリックをして "Attach Script" を選択。そのまま C# で作成します。

f:id:tan-y:20171111230531p:plain f:id:tan-y:20171111230534p:plain

初期状態では次のように内蔵のスクリプトエディッターが開きます。

f:id:tan-y:20171111230541p:plain

ただ現時点ではコード補完がきかないのでとても不便です。ドキュメントを見ても C# での名前は C# らしいものに微妙に変更されており、正確な名前がわかりません。困った。
ですが、スクリプトの追加時に合わせて .sln, .csproj が生成されていたので .sln を Visual Studio で開いてみると、無事開くことができました。

f:id:tan-y:20171111230545p:plain

.csproj には Godot Engine のアセンブリが参照に追加されており、コード補完もきくので全く違和感なくコーディングができます。素晴らしい。
Godot に戻れば動的に反映がされていますので、正しく記述されていれば実行することができます。 _Process はご想像通り Unity の MonoBehavior.Update と同じようですのでここにあれこれ書くとよいでしょう。

public override void _Process(float delta)
{
    this.RotateY(delta);
}

とだけ書いて実行すると Y 軸を中心にくるくるまわります。これでなんとなく雰囲気がつかめました。

Mono でのデバッガは現状は未対応のようで、ブレイクポイントを設定しても止まりませんでした。

その他

Godot 3.0 からは glTF のインポートに対応しています。
Khronos の glTF Sample Models からサンプルを適当に入れてみたところほどほど読めているようです。 2.1 までは COLLADA だけのようです。 glTF はこれからのフォーマットですが対応が早いですね。

glTF のサンプルを配置してライトをちょっと入れてみたらこんな感じ。

f:id:tan-y:20171111230551p:plain

まとめ

Unity や UE4 を使うことに特に制約 (主にライセンス費用面で) がなく、とにかく製品開発をしたいのであれば他のエンジンは検討の余地ないと思いますが、 Unity, UE4 が使えないか技術的に興味があるのでしたら Godot Engine を一度さわってみると面白いのではないかと思います。
ただ 2.1 と 3.0 で大分変わるような感じもするので、今から始めるなら alpha でも 3.0 からの方がいいような気もします。てなると製品での採用は無理と思うので現状では研究、様子見でしょうか。

Xamarin.Forms for Unityの概要の追記

前回記事の後、実装の見直しをしたのでちょっと状況が変わりました。

tan-y.hatenablog.com

Xamarin.Forms の VisualElementRenderer は標準的な手続きに従う場合、デフォルトコンストラクタでインスタンス生成ができるようにし、ExportRendererAttribute で VisualElement と VisualElementRenderer の関連付けを定義する事になっているようですが、これに従うことができないので今のところは UnityFormsApplicationActivity というクラスに集約しています。

と書きました。
これの原因は Xamarin.Forms.Internals.Registrar クラスの GetHandler メソッド

object handler = Activator.CreateInstance(handlerType);

のためだったのですが、よくよく考えたら VisualElementRenderer を MonoBehaviour 継承にしなければいいんじゃね?てことでほぼ通常の Platform 実装の構造にすることができました。現状では通常の Platform 実装と同じように ExportRendererAttribute で関連付けを指定できますので Custom Renderer もいけるはず。

ExportRendererAttribute はアセンブリ属性として定義しますが、 WebGL ビルド (IL2CPP) が実はアセンブリ属性をサポートしてないかとちよっと疑いましたが、特に問題なく動作しました。 XAML Loader が WebGL で動作しないのはこの辺かなあと思ったのですが。

VisualElementRenderer の実装クラスでは UI を描画するためのリソースを生成する処理の実装が必要になります (CreateBaseComponent をオーバーライド) 。標準の実装では予め対応を定義づけておいた Prefab からインスタンス生成します。

単純にコンストラクタで処理が記述できないのは

  • VisualElementRenderer が Unity 的には画面 (Scene) 上で管理する "GameObject" に適用する MonoBehaviour (直接的には MonoBehaviour ではなくなりましたが論理的には) であること。
  • MonoBehaviour は本体である GameObject が存在しないとインスタンス生成すらできないこと (GameObject.AddComponent メソッドを参照)
  • MonoBehaviour, GameObject は Unity.Object 継承であり、直接 new でインスタンス化できないこと

あたりが理由です。 Unity だけやってる時は「そういうものだ」で受け入れてしまってますがこういう時面倒になってきます。

描画リソース (コンポーネント) 生成に Prefab を利用しているのは、コードで生成処理を記述するのが実質不可能なための苦肉の策だったのですが、 Prefab を利用することで Custom Renderer がなくなても独自にデザインした UI コンポーネントをテンプレート的に設定できるので、このやり方は結果的によかったかなあと思います。

次の課題

NavigationPage の対応かなーというのはあるのですが、実は下記二つをどうやって対応するか悩み中。

  • ImageView
  • Opacity

「え、 Unity だから簡単じゃないの?」と思うでしょう。
Unity だからこそ逆に面倒なんですよ・・・

Xamarin.Forms for Unityの概要

技術ブログ始めてみました。

一発目として、鋭意 (?) 開発中の Xamarin.Forms for Unity の概要を解説していきたいと思います。

先日の .NET Conf 2017 Tokyo の Unconference で概要と簡単なデモを発表させてもらいましたが、駆け足だったので改めて。

Xamarin.Forms for Unity とは

Xamarin.Forms の Platform を Unity (Game Engine の方) の API で実装した (しようとしている) ものです。

Xamarin.Forms はアプリケーション開発者から見た場合、マルチプラットフォーム対応のアプリケーションフレームワークですが、内部的にはプラットフォーム共通の Core と、各プラットフォームに依存した Platform に分かれていて、実行対象としているプラットフォーム向けの Platform 実装があれば、そのプラットフォーム向けのアプリケーションが開発できます。

Xamarin.Forms では標準で Android, iOS, WinRT(UWP) などの Platform 実装が提供されています (その他にも公式 Platform はありますが割愛) が、ないなら作ってしまえば新しいプラットフォームに対応できるわけです。

・・・という感じで作っているのが Xamarin.Forms for Unity なわけです。 Xamarin とは全く無関係に勝手に作っている、 Unofficial Platform になります。

f:id:tan-y:20171028103507p:plain
Unity Editor 上での動作

Unity Editor 上ではこんな感じで動いています。

これは最近追加したサンプルの "XAMLPad もどき" です。 この XAMLPad アプリ自体の UI も XAML で記述しています。

結構 "Xamarin.Forms らしい" 記述ができるようになっているかなと思います。

やり始めた背景

Xamarin.Forms の Platform 実装を調査、勉強したかったのが第一です。
GitHub の Xamrin.Forms のソースを読みながら、 とりあえず扱いやすい Windows Forms 向けの実装をざっくり行ってみて 雰囲気を掴んだ後、それを踏まえて Unity をターゲットとして一通りの実装をすることを目標に開発を始めました。 Unity でやれば Unity の研究にもなりますしね。

加えて技術的な変化により実装を行うことが可能になってきたというのもあります。

Unity の .NET 4.6 対応

Unity 自体が .NET Framework 4.6 に対応した事が大きいです。 Unity は長い間 .NET 3.5 ベースでしたが、 Unity 5.5 くらいから段階的に .NET 4.6 のランタイムが組み込まれ、現時点でもまだ expermintal ですが正式バージョンの Unity で .NET 4.6 が選択可能になりました。

これにより Task など .NET 4 から追加された機能や様々な .NET 4 向けのライブラリ、フレームワーク (Xamarin.Forms もそうですね) が使えるようになったので、いろいろ試してみるとよいのではないかと思います。

Xamarin.Forms の Unofficial Platform 実装の解禁

Xamarin.Forms は従来 Unofficial Platform の実装は非常に困難で、 Core ライブラリ自体に手を加えるか、トリックを使う必要がありましたが 、 2.4.0 よりこの制限がなくなり正式な Core ライブラリの Pre Build バイナリを使用しての開発が可能になりました。

※結局 2.3.5 は stable にならず 2.4.0 になりました。

実際、 Xamarin.Forms for Unity も当初は NuGet から取得した DLL を組み込んで作業をしていましたが、 Unity に若干特殊なオプション指定を追加しなくてはならなかったことと、Unity でアプリケーションの Build をしようとすると必ず失敗するため、現状では Core ライブラリはソースコードで組み込んでいます。興味がある方はコミット履歴の最初の方を参照してください。

実際やってみて

結構しっかり動く

当然かもしれませんが、自分としては意外なほど普通に Xamarin.Forms の機能が動作してびっくりしました。

  • Binding
  • Layout
  • Animation
  • XAML Compiler

これらがしっかり機能していましたので、 Xamarin.Forms の流儀を Unity に持ち込む事はできそうです。
Navigation の実装ができたら Prism など MVVM フレームワークも使ってみたいですね。

XAML Compiler については動的にパースさせるのは本当はよくないので xamlc を使えるようにするのも課題です。

Unity ならではの問題

Unity はアプリケーションのランタイムに Mono を採用していて確かに .NET ベースなのですが、他の一般的な .NET 環境と比べて独特な面が多々あります。
公式の Platform 実装のコードはかなり読みましたが、公式で行っている共通的な手順に Unity では沿えない事も多々あり、そのような場合は仕方がないので独自の手法をとっています。

例えば Unity の機能を直接組み込むクラスは UnityEngine.Object というクラスを継承していないといけないわけですが、このクラスを継承したクラスは直接 new でインスタンス生成をすることができません。
Xamarin.Forms の VisualElementRenderer は標準的な手続きに従う場合、デフォルトコンストラクタでインスタンス生成ができるようにし、ExportRendererAttribute で VisualElement と VisualElementRenderer の関連付けを定義する事になっているようですが、これに従うことができないので今のところは UnityFormsApplicationActivity というクラスに集約しています。

終わりに

ドキュメントもペラ一枚程度しかないような状態ですので、とりあえずブログでちょっとずつでも書いていきたいと思います。

Xamarin.Forms か Unity のどちらかしかやってこられていない方はこれをベースにもう一方の技術にも興味もってもらえたら幸いだなあと思います。